KUDr@3900: /* $Id$ */ KUDr@3900: rubidium@9111: /** @file yapf_destrail.hpp Determining the destination for rail vehicles. */ celestar@6121: KUDr@3900: #ifndef YAPF_DESTRAIL_HPP KUDr@3900: #define YAPF_DESTRAIL_HPP KUDr@3900: KUDr@3900: class CYapfDestinationRailBase KUDr@3900: { KUDr@3900: protected: rubidium@8236: RailTypes m_compatible_railtypes; KUDr@3900: KUDr@3900: public: rubidium@9797: void SetDestination(const Vehicle *v, bool override_rail_type = false) KUDr@3900: { KUDr@3900: m_compatible_railtypes = v->u.rail.compatible_railtypes; rubidium@9797: if (override_rail_type) m_compatible_railtypes |= GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes; KUDr@3900: } KUDr@3900: KUDr@3900: bool IsCompatibleRailType(RailType rt) KUDr@3900: { skidd13@7928: return HasBit(m_compatible_railtypes, rt); KUDr@3900: } rubidium@9797: rubidium@9797: RailTypes GetCompatibleRailTypes() const rubidium@9797: { rubidium@9797: return m_compatible_railtypes; rubidium@9797: } KUDr@3900: }; KUDr@3900: KUDr@3900: template KUDr@3900: class CYapfDestinationAnyDepotRailT KUDr@3900: : public CYapfDestinationRailBase KUDr@3900: { KUDr@3900: public: KUDr@3914: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) KUDr@3900: typedef typename Types::NodeList::Titem Node; ///< this will be our node type KUDr@3914: typedef typename Node::Key Key; ///< key to hash tables KUDr@3900: KUDr@3914: /// to access inherited path finder KUDr@3900: Tpf& Yapf() {return *static_cast(this);} KUDr@3900: KUDr@3914: /// Called by YAPF to detect if node ends in the desired destination KUDr@3900: FORCEINLINE bool PfDetectDestination(Node& n) KUDr@3900: { KUDr@3930: return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); KUDr@3930: } KUDr@3930: KUDr@3930: /// Called by YAPF to detect if node ends in the desired destination KUDr@3930: FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) KUDr@3930: { smatz@8961: bool bDest = IsRailDepotTile(tile); KUDr@3900: return bDest; KUDr@3900: } KUDr@3900: KUDr@3914: /** Called by YAPF to calculate cost estimate. Calculates distance to the destination rubidium@4549: * adds it to the actual cost from origin and stores the sum to the Node::m_estimate */ KUDr@3900: FORCEINLINE bool PfCalcEstimate(Node& n) KUDr@3900: { KUDr@3900: n.m_estimate = n.m_cost; KUDr@3900: return true; KUDr@3900: } KUDr@3900: }; KUDr@3900: KUDr@3900: template rubidium@9802: class CYapfDestinationAnySafeTileRailT rubidium@9802: : public CYapfDestinationRailBase rubidium@9802: { rubidium@9802: public: rubidium@9802: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) rubidium@9802: typedef typename Types::NodeList::Titem Node; ///< this will be our node type rubidium@9802: typedef typename Node::Key Key; ///< key to hash tables smatz@9842: typedef typename Types::TrackFollower TrackFollower; ///< TrackFollower. Need to typedef for gcc 2.95 rubidium@9802: rubidium@9802: /// to access inherited path finder rubidium@9802: Tpf& Yapf() {return *static_cast(this);} rubidium@9802: rubidium@9802: /// Called by YAPF to detect if node ends in the desired destination rubidium@9802: FORCEINLINE bool PfDetectDestination(Node& n) rubidium@9802: { rubidium@9802: return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); rubidium@9802: } rubidium@9802: rubidium@9802: /// Called by YAPF to detect if node ends in the desired destination rubidium@9802: FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) rubidium@9802: { rubidium@9802: return michi_cc@10210: IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) && michi_cc@10210: IsWaitingPositionFree(Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns()); rubidium@9802: } rubidium@9802: rubidium@9802: /** Called by YAPF to calculate cost estimate. Calculates distance to the destination rubidium@9802: * adds it to the actual cost from origin and stores the sum to the Node::m_estimate. */ rubidium@9802: FORCEINLINE bool PfCalcEstimate(Node& n) rubidium@9802: { rubidium@9802: n.m_estimate = n.m_cost; rubidium@9802: return true; rubidium@9802: } rubidium@9802: }; rubidium@9802: rubidium@9802: template KUDr@3900: class CYapfDestinationTileOrStationRailT KUDr@3900: : public CYapfDestinationRailBase KUDr@3900: { KUDr@3900: public: KUDr@3914: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) KUDr@3900: typedef typename Types::NodeList::Titem Node; ///< this will be our node type KUDr@3914: typedef typename Node::Key Key; ///< key to hash tables KUDr@3900: KUDr@3900: protected: KUDr@3900: TileIndex m_destTile; KUDr@3900: TrackdirBits m_destTrackdirs; KUDr@3900: StationID m_dest_station_id; KUDr@3900: KUDr@3914: /// to access inherited path finder KUDr@3900: Tpf& Yapf() {return *static_cast(this);} KUDr@3900: KUDr@3900: static TileIndex CalcStationCenterTile(StationID station) KUDr@3900: { KUDr@3900: const Station* st = GetStation(station); KUDr@3900: KUDr@3900: uint x = TileX(st->train_tile) + st->trainst_w / 2; KUDr@3900: uint y = TileY(st->train_tile) + st->trainst_h / 2; KUDr@3900: // return the tile of our target coordinates KUDr@3900: return TileXY(x, y); KUDr@3900: } KUDr@3900: KUDr@3900: public: rubidium@9439: void SetDestination(const Vehicle* v) KUDr@3900: { rubidium@8836: switch (v->current_order.GetType()) { KUDr@6548: case OT_GOTO_STATION: rubidium@8840: m_destTile = CalcStationCenterTile(v->current_order.GetDestination()); rubidium@8840: m_dest_station_id = v->current_order.GetDestination(); KUDr@6548: m_destTrackdirs = INVALID_TRACKDIR_BIT; KUDr@6548: break; KUDr@6548: KUDr@6548: case OT_GOTO_WAYPOINT: { rubidium@8840: Waypoint *wp = GetWaypoint(v->current_order.GetDestination()); KUDr@6549: if (wp == NULL) { KUDr@6549: /* Invalid waypoint in orders! */ rubidium@10207: DEBUG(yapf, 0, "Invalid waypoint in orders == 0x%04X (train %d, company %d)", v->current_order.GetDestination(), v->unitnumber, (CompanyID)v->owner); KUDr@6549: break; KUDr@6549: } KUDr@6548: m_destTile = wp->xy; KUDr@6549: if (m_destTile != v->dest_tile) { KUDr@6549: /* Something is wrong with orders! */ rubidium@10207: DEBUG(yapf, 0, "Invalid v->dest_tile == 0x%04X (train %d, company %d)", v->dest_tile, v->unitnumber, (CompanyID)v->owner); KUDr@6549: } KUDr@6548: m_dest_station_id = INVALID_STATION; KUDr@6548: m_destTrackdirs = TrackToTrackdirBits(AxisToTrack(GetWaypointAxis(wp->xy))); KUDr@6548: break; KUDr@6548: } KUDr@6548: KUDr@6548: default: KUDr@6548: m_destTile = v->dest_tile; KUDr@6548: m_dest_station_id = INVALID_STATION; frosch@8616: m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0)); KUDr@6548: break; KUDr@3900: } KUDr@3900: CYapfDestinationRailBase::SetDestination(v); KUDr@3900: } KUDr@3900: KUDr@3914: /// Called by YAPF to detect if node ends in the desired destination KUDr@3900: FORCEINLINE bool PfDetectDestination(Node& n) KUDr@3900: { KUDr@3930: return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); KUDr@3930: } KUDr@3930: KUDr@3930: /// Called by YAPF to detect if node ends in the desired destination KUDr@3930: FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) KUDr@3930: { KUDr@3900: bool bDest; KUDr@3900: if (m_dest_station_id != INVALID_STATION) { KUDr@3930: bDest = IsRailwayStationTile(tile) KUDr@3930: && (GetStationIndex(tile) == m_dest_station_id) KUDr@3930: && (GetRailStationTrack(tile) == TrackdirToTrack(td)); KUDr@3900: } else { KUDr@3930: bDest = (tile == m_destTile) KUDr@3930: && ((m_destTrackdirs & TrackdirToTrackdirBits(td)) != TRACKDIR_BIT_NONE); KUDr@3900: } KUDr@3900: return bDest; KUDr@3900: } KUDr@3900: KUDr@3914: /** Called by YAPF to calculate cost estimate. Calculates distance to the destination rubidium@4549: * adds it to the actual cost from origin and stores the sum to the Node::m_estimate */ KUDr@3900: FORCEINLINE bool PfCalcEstimate(Node& n) KUDr@3900: { KUDr@3900: static int dg_dir_to_x_offs[] = {-1, 0, 1, 0}; KUDr@3900: static int dg_dir_to_y_offs[] = {0, 1, 0, -1}; KUDr@3900: if (PfDetectDestination(n)) { KUDr@3900: n.m_estimate = n.m_cost; KUDr@3900: return true; KUDr@3900: } KUDr@3900: KUDr@3900: TileIndex tile = n.GetLastTile(); KUDr@3900: DiagDirection exitdir = TrackdirToExitdir(n.GetLastTrackdir()); KUDr@3900: int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir]; KUDr@3900: int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir]; KUDr@3900: int x2 = 2 * TileX(m_destTile); KUDr@3900: int y2 = 2 * TileY(m_destTile); KUDr@3900: int dx = abs(x1 - x2); KUDr@3900: int dy = abs(y1 - y2); KUDr@3900: int dmin = min(dx, dy); KUDr@3900: int dxy = abs(dx - dy); KUDr@3900: int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2); KUDr@3900: n.m_estimate = n.m_cost + d; KUDr@3900: assert(n.m_estimate >= n.m_parent->m_estimate); KUDr@3900: return true; KUDr@3900: } KUDr@3900: }; KUDr@3900: KUDr@3900: KUDr@3900: #endif /* YAPF_DESTRAIL_HPP */