void AIConstruction::SetFlagsAlongRoad(const noRoadNode& roadNode, Direction dir)
{
    // does the roadsegment still exist?
    const RoadSegment& roadSeg = *roadNode.GetRoute(dir);
    bool isBwdDir = roadSeg.GetNodeID(roadNode);
    MapPoint curPos = roadNode.GetPos();
    // Skip first
    curPos = aii.gwb.GetNeighbour(curPos, roadSeg.GetDir(isBwdDir, 0));
    // Start after getting first neighbor (min distance == 2)
    // and skip last 2 points (min distance and last is flag)
    for(unsigned i = 1; i + 2 < roadSeg.GetLength(); ++i)
    {
        curPos = aii.gwb.GetNeighbour(curPos, roadSeg.GetDir(isBwdDir, i));
        aii.SetFlag(curPos);
        constructionlocations.push_back(curPos);
    }
}
示例#2
0
 unsigned operator()(const noRoadNode& curNode, const unsigned char nextDir) const
 {
     // Im Warenmodus m�ssen wir Strafpunkte für �berlastete Tr�ger hinzuaddieren, 
     // damit der Algorithmus auch Ausweichrouten ausw�hlt
     return curNode.GetPunishmentPoints(nextDir);
 }
示例#3
0
bool RoadPathFinder::FindPathImpl(const noRoadNode& start, const noRoadNode& goal,
                              const unsigned max,
                              const T_AdditionalCosts addCosts, const T_SegmentConstraints isSegmentAllowed,
                              unsigned* const length, unsigned char* const firstDir, MapPoint* const firstNodePos)
{
    if(&start == &goal)
    {
        // Path where start==goal should never happen
        RTTR_Assert(false);
        LOG.write("WARNING: Bug detected (GF: %u). Please report this with the savegame and replay (Start==Goal in pathfinding %u,%u)\n") % gwb_.GetEvMgr().GetCurrentGF() % unsigned(start.GetX()) % unsigned(start.GetY());
        // But for now we assume it to be valid and return (kind of) correct values
        if(length)
            *length = 0;
        if(firstDir)
            *firstDir = 0xff;
        if(firstNodePos)
            *firstNodePos = start.GetPos();
        return true;
    }

    // increase current_visit_on_roads, so we don't have to clear the visited-states at every run
    currentVisit++;

    // if the counter reaches its maxium, tidy up
    if (currentVisit == std::numeric_limits<unsigned>::max())
    {
        int w = gwb_.GetWidth();
        int h = gwb_.GetHeight();
        for(int y = 0; y < h; y++)
        {
            for(int x = 0; x < w; x++)
            {
                noRoadNode* const node = gwb_.GetSpecObj<noRoadNode>(MapPoint(x, y));
                if(node)
                    node->last_visit = 0;
            }
        }
        currentVisit = 1;
    }

    // Anfangsknoten einf�gen
    todo.clear();

    start.targetDistance = gwb_.CalcDistance(start.GetPos(), goal.GetPos());
    start.estimate = start.targetDistance;
    start.last_visit = currentVisit;
    start.prev = NULL;
    start.cost = 0;
    start.dir_ = 0;

    todo.push(&start);

    while (!todo.empty())
    {
        // Knoten mit den geringsten Wegkosten ausw�hlen
        const noRoadNode& best = *todo.pop();

        // Ziel erreicht?
        if (&best == &goal)
        {
            // Jeweils die einzelnen Angaben zur�ckgeben, falls gew�nscht (Pointer �bergeben)
            if (length)
                *length = best.cost;

            // Backtrace to get the last node that is not the start node (has a prev node) --> Next node from start on path
            const noRoadNode* firstNode = &best;
            while(firstNode->prev != &start)
            {
                firstNode = firstNode->prev;
            }

            if (firstDir)
                *firstDir = (unsigned char) firstNode->dir_;

            if (firstNodePos)
                *firstNodePos = firstNode->GetPos();

            // Done, path found
            return true;
        }

        // Nachbarflagge bzw. Wege in allen 6 Richtungen verfolgen
        for (unsigned i = 0; i < 6; ++i)
        {
            // Gibt es auch einen solchen Weg bzw. Nachbarflagge?
            noRoadNode* neighbour = best.GetNeighbour(i);

            // Wenn nicht, brauchen wir mit dieser Richtung gar nicht weiter zu machen
            if (!neighbour)
                continue;

            // this eliminates 1/6 of all nodes and avoids cost calculation and further checks, 
            // therefore - and because the profiler says so - it is more efficient that way
            if (neighbour == best.prev)
                continue;

            // No pathes over buildings
            if ((i == 1) && (neighbour != &goal))
            {
                // Flags and harbors are allowed
                const GO_Type got = neighbour->GetGOT();
                if(got != GOT_FLAG && got != GOT_NOB_HARBORBUILDING)
                    continue;
            }

            // evtl verboten?
            if(!isSegmentAllowed(*best.routes[i]))
                continue;

            // Neuer Weg für diesen neuen Knoten berechnen
            unsigned cost = best.cost + best.routes[i]->GetLength();
            cost += addCosts(best, i);

            if (cost > max)
                continue;

            // Was node already visited?
            if (neighbour->last_visit == currentVisit)
            {
                // Dann nur ggf. Weg und Vorg�nger korrigieren, falls der Weg k�rzer ist
                if (cost < neighbour->cost)
                {
                    neighbour->cost = cost;
                    neighbour->prev = &best;
                    neighbour->estimate = neighbour->targetDistance + cost;
                    todo.rearrange(neighbour);
                    neighbour->dir_ = i;
                }
            }else
            {
                // Not visited yet -> Add to list
                neighbour->last_visit = currentVisit;
                neighbour->cost = cost;
                neighbour->dir_ = i;
                neighbour->prev = &best;

                neighbour->targetDistance = gwb_.CalcDistance(neighbour->GetPos(), goal.GetPos());
                neighbour->estimate = neighbour->targetDistance + cost;

                todo.push(neighbour);
            }
        }

        // Stehen wir hier auf einem Hafenplatz
        if (best.GetGOT() == GOT_NOB_HARBORBUILDING)
        {
            std::vector<nobHarborBuilding::ShipConnection> scs = static_cast<const nobHarborBuilding&>(best).GetShipConnections();

            for (unsigned i = 0; i < scs.size(); ++i)
            {
                // Neuer Weg für diesen neuen Knoten berechnen
                unsigned cost = best.cost + scs[i].way_costs;

                if (cost > max)
                    continue;

                noRoadNode& dest = *scs[i].dest;
                // Was node already visited?
                if (dest.last_visit == currentVisit)
                {
                    // Dann nur ggf. Weg und Vorg�nger korrigieren, falls der Weg k�rzer ist
                    if (cost < dest.cost)
                    {
                        dest.dir_ = SHIP_DIR;
                        dest.cost = cost;
                        dest.prev = &best;
                        dest.estimate = dest.targetDistance + cost;
                        todo.rearrange(&dest);
                    }
                }else
                {
                    // Not visited yet -> Add to list
                    dest.last_visit = currentVisit;

                    dest.dir_ = SHIP_DIR;
                    dest.prev = &best;
                    dest.cost = cost;

                    dest.targetDistance = gwb_.CalcDistance(dest.GetPos(), goal.GetPos());
                    dest.estimate = dest.targetDistance + cost;

                    todo.push(&dest);
                }
            }
        }
    }

    // Liste leer und kein Ziel erreicht --> kein Weg
    return false;
}