Exemplo n.º 1
0
Path::Path(Unit* unit, Tile* targetTile, bool attack)
    : m_path  (),
      m_attack(attack)
{
    Q_ASSERT(unit != nullptr);
    Q_ASSERT(targetTile != nullptr);

    OpenList open;
    open.push(new Node(unit->tile(), 0, distance(unit->tile(), targetTile)));

    ClosedList closed;

    while (!open.isEmpty())
    {
        Node* current = open.pop();
        closed.push(current);

        if (current->tile() == targetTile)
        {
            // Target found
            constructPath(current);
            break;
        }

        for (Tile* neighbour : current->tile()->neighbours())
        {
            if (closed.contains(neighbour))
            {
                continue;
            }

            QScopedPointer<Node> newNode(new Node(
                neighbour,
                current->g() + 1,
                distance(neighbour, targetTile),
                current
            ));

            auto existing = open.find(neighbour);

            if (existing == open.end())
            {
                // Tile we haven't check before - make sure we can enter
                if (unit->canEnter(neighbour) ||
                    (attack && neighbour == targetTile))
                {
                    open.push(newNode.take());
                }
                else
                {
                    // If we can't enter, don't check again
                    closed.push(newNode.take());
                }
            }
            else if (newNode->g() < (*existing)->g())
            {
                open.replace(existing, newNode.take());
            }
        }
    }
}