- 01
 - 02
 - 03
 - 04
 - 05
 - 06
 - 07
 - 08
 - 09
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 - 81
 - 82
 - 83
 - 84
 - 85
 - 86
 - 87
 - 88
 - 89
 - 90
 - 91
 - 92
 - 93
 
                        std::deque<std::pair<int, int>> Pathing::findPath(int sx, int sy, int fx, int fy) const
{
    std::list<Node> openNodes;
    std::list<Node> closeNodes;
    const Node startNode{nullptr, sx, sy, 0, 0, 0};
    openNodes.push_back(startNode);
    auto cells = gameMap->getCells();
    auto findNode = [](auto&& list, int x, int y)
    {
        return std::find_if(std::begin(std::forward<decltype(list)>(list)),
                            std::end(std::forward<decltype(list)>(list)),
                [x, y](auto n) {return n.x == x && n.y == y;});
    };
    auto isNodeInList = [findNode](auto&& list, int x, int y)
    {
        return findNode(std::forward<decltype(list)>(list), x, y) != list.cend();
    };
    auto processNode = [&](auto iterCurrentNode, int x, int y)
    {
        const auto nx = iterCurrentNode->x + x;
        const auto ny = iterCurrentNode->y + y;
        if (cells[nx][ny].passable && !isNodeInList(closeNodes, nx, ny))
        {
            const auto G = iterCurrentNode->G + (x && y ? 14 : 10);
            const auto H = (std::abs(fx - nx) + std::abs(fy - ny)) * 10;
            const auto F = G + H;
            auto node = findNode(openNodes, nx, ny);
            if (node == openNodes.cend())
            {
                openNodes.push_back({&(*iterCurrentNode), nx, ny, G, H, F});
                if (nx == fx && ny == fy)
                    return true;
            }
            else
            {
                if (G < node->G)
                {
                    node->parent = &(*iterCurrentNode);
                    node->G = G;
                    node->H = H;
                    node->F = F;
                }
            }
        }
        return false;
    };
    while (!openNodes.empty())
    {
        auto iterMinF = std::min_element(openNodes.cbegin(), openNodes.cend(),
                [](auto n1, auto n2) {return n1.F < n2.F;});
        closeNodes.push_back(*iterMinF);
        auto iter = closeNodes.insert(closeNodes.cend(), *iterMinF);
        openNodes.erase(iterMinF);
        if (processNode(iter,  1,  0) ||
            processNode(iter,  1,  1) ||
            processNode(iter,  0,  1) ||
            processNode(iter, -1,  1) ||
            processNode(iter, -1,  0) ||
            processNode(iter, -1, -1) ||
            processNode(iter,  0, -1) ||
            processNode(iter,  1, -1))
            break;
    }
    auto finalNode = findNode(openNodes, fx, fy);
    if (finalNode == openNodes.cend())
        return {};
    std::deque<std::pair<int, int>> route{{finalNode->x, finalNode->y}};
    const Node* temp = finalNode->parent;
    while (temp)
    {
        route.push_front({temp->x, temp->y});
        temp = temp->parent;
    }
    return route;
}