Example #1
0
Trackdir Ship::GetVehicleTrackdir() const
{
	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;

	if (this->IsInDepot()) {
		/* We'll assume the ship is facing outwards */
		return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile));
	}

	if (this->state == TRACK_BIT_WORMHOLE) {
		/* ship on aqueduct, so just use his direction and assume a diagonal track */
		return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
	}

	return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction);
}
Example #2
0
    inline Trackdir ChooseRoadTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, bool &path_found)
    {
        /* Handle special case - when next tile is destination tile.
         * However, when going to a station the (initial) destination
         * tile might not be a station, but a junction, in which case
         * this method forces the vehicle to jump in circles. */
        if (tile == v->dest_tile && !v->current_order.IsType(OT_GOTO_STATION)) {
            /* choose diagonal trackdir reachable from enterdir */
            return DiagDirToDiagTrackdir(enterdir);
        }
        /* our source tile will be the next vehicle tile (should be the given one) */
        TileIndex src_tile = tile;
        /* get available trackdirs on the start tile */
        TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes));
        /* select reachable trackdirs only */
        src_trackdirs &= DiagdirReachesTrackdirs(enterdir);

        /* set origin and destination nodes */
        Yapf().SetOrigin(src_tile, src_trackdirs);
        Yapf().SetDestination(v);

        /* find the best path */
        path_found = Yapf().FindPath(v);

        /* if path not found - return INVALID_TRACKDIR */
        Trackdir next_trackdir = INVALID_TRACKDIR;
        Node *pNode = Yapf().GetBestNode();
        if (pNode != NULL) {
            /* path was found or at least suggested
             * walk through the path back to its origin */
            while (pNode->m_parent != NULL) {
                pNode = pNode->m_parent;
            }
            /* return trackdir from the best origin node (one of start nodes) */
            Node& best_next_node = *pNode;
            assert(best_next_node.GetTile() == tile);
            next_trackdir = best_next_node.GetTrackdir();
        }
        return next_trackdir;
    }
Example #3
0
    /**
     * Called by YAPF to calculate the cost from the origin to the given node.
     *  Calculates only the cost of given node, adds it to the parent node cost
     *  and stores the result into Node::m_cost member
     */
    inline bool PfCalcCost(Node& n, const TrackFollower *tf)
    {
        int segment_cost = 0;
        uint tiles = 0;
        /* start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment */
        TileIndex tile = n.m_key.m_tile;
        Trackdir trackdir = n.m_key.m_td;
        for (;;) {
            /* base tile cost depending on distance between edges */
            segment_cost += Yapf().OneTileCost(tile, trackdir);

            const RoadVehicle *v = Yapf().GetVehicle();
            /* we have reached the vehicle's destination - segment should end here to avoid target skipping */
            if (Yapf().PfDetectDestinationTile(tile, trackdir)) break;

            /* stop if we have just entered the depot */
            if (IsRoadDepotTile(tile) && trackdir == DiagDirToDiagTrackdir(ReverseDiagDir(GetRoadDepotDirection(tile)))) {
                /* next time we will reverse and leave the depot */
                break;
            }

            /* if there are no reachable trackdirs on new tile, we have end of road */
            TrackFollower F(Yapf().GetVehicle());
            if (!F.Follow(tile, trackdir)) break;

            /* if there are more trackdirs available & reachable, we are at the end of segment */
            if (KillFirstBit(F.m_new_td_bits) != TRACKDIR_BIT_NONE) break;

            Trackdir new_td = (Trackdir)FindFirstBit2x64(F.m_new_td_bits);

            /* stop if RV is on simple loop with no junctions */
            if (F.m_new_tile == n.m_key.m_tile && new_td == n.m_key.m_td) return false;

            /* if we skipped some tunnel tiles, add their cost */
            segment_cost += F.m_tiles_skipped * YAPF_TILE_LENGTH;
            tiles += F.m_tiles_skipped + 1;

            /* add hilly terrain penalty */
            segment_cost += Yapf().SlopeCost(tile, F.m_new_tile, trackdir);

            /* add min/max speed penalties */
            int min_speed = 0;
            int max_veh_speed = v->GetDisplayMaxSpeed();
            int max_speed = F.GetSpeedLimit(&min_speed);
            if (max_speed < max_veh_speed) segment_cost += 1 * (max_veh_speed - max_speed);
            if (min_speed > max_veh_speed) segment_cost += 10 * (min_speed - max_veh_speed);

            /* move to the next tile */
            tile = F.m_new_tile;
            trackdir = new_td;
            if (tiles > MAX_MAP_SIZE) break;
        }

        /* save end of segment back to the node */
        n.m_segment_last_tile = tile;
        n.m_segment_last_td = trackdir;

        /* save also tile cost */
        int parent_cost = (n.m_parent != NULL) ? n.m_parent->m_cost : 0;
        n.m_cost = parent_cost + segment_cost;
        return true;
    }