src/yapf/follow_track.hpp
branchNewGRF_ports
changeset 6877 889301acc299
parent 6872 1c4a4a609f85
child 6878 7d1ff2f621c7
equal deleted inserted replaced
6876:2c40faeef7a5 6877:889301acc299
    35 	}
    35 	}
    36 
    36 
    37 	FORCEINLINE static TransportType TT() {return Ttr_type_;}
    37 	FORCEINLINE static TransportType TT() {return Ttr_type_;}
    38 	FORCEINLINE static bool IsWaterTT() {return TT() == TRANSPORT_WATER;}
    38 	FORCEINLINE static bool IsWaterTT() {return TT() == TRANSPORT_WATER;}
    39 	FORCEINLINE static bool IsRailTT() {return TT() == TRANSPORT_RAIL;}
    39 	FORCEINLINE static bool IsRailTT() {return TT() == TRANSPORT_RAIL;}
       
    40 	FORCEINLINE bool IsTram() {return IsRoadTT() && HasBit(m_veh->u.road.compatible_roadtypes, ROADTYPE_TRAM);}
    40 	FORCEINLINE static bool IsRoadTT() {return TT() == TRANSPORT_ROAD;}
    41 	FORCEINLINE static bool IsRoadTT() {return TT() == TRANSPORT_ROAD;}
    41 	FORCEINLINE static bool Allow90degTurns() {return T90deg_turns_allowed_;}
    42 	FORCEINLINE static bool Allow90degTurns() {return T90deg_turns_allowed_;}
       
    43 
       
    44 	/** Tests if a tile is a road tile with a single tramtrack (tram can reverse) */
       
    45 	FORCEINLINE DiagDirection GetSingleTramBit(TileIndex tile)
       
    46 	{
       
    47 		if (IsTram() && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
       
    48 			RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
       
    49 			switch (rb) {
       
    50 				case ROAD_NW: return DIAGDIR_NW;
       
    51 				case ROAD_SW: return DIAGDIR_SW;
       
    52 				case ROAD_SE: return DIAGDIR_SE;
       
    53 				case ROAD_NE: return DIAGDIR_NE;
       
    54 				default: break;
       
    55 			}
       
    56 		}
       
    57 		return INVALID_DIAGDIR;
       
    58 	}
    42 
    59 
    43 	/** main follower routine. Fills all members and return true on success.
    60 	/** main follower routine. Fills all members and return true on success.
    44 	 *  Otherwise returns false if track can't be followed. */
    61 	 *  Otherwise returns false if track can't be followed. */
    45 	FORCEINLINE bool Follow(TileIndex old_tile, Trackdir old_td)
    62 	FORCEINLINE bool Follow(TileIndex old_tile, Trackdir old_td)
    46 	{
    63 	{
    47 		m_old_tile = old_tile;
    64 		m_old_tile = old_tile;
    48 		m_old_td = old_td;
    65 		m_old_td = old_td;
    49 		m_err = EC_NONE;
    66 		m_err = EC_NONE;
    50 		assert((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0);
    67 		assert(((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
       
    68 		       (GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits
    51 		m_exitdir = TrackdirToExitdir(m_old_td);
    69 		m_exitdir = TrackdirToExitdir(m_old_td);
    52 		if (EnteredDepot()) return true;
    70 		if (ForcedReverse()) return true;
    53 		if (!CanExitOldTile()) return false;
    71 		if (!CanExitOldTile()) return false;
    54 		FollowTileExit();
    72 		FollowTileExit();
    55 		if (!QueryNewTileTrackStatus()) return TryReverse();
    73 		if (!QueryNewTileTrackStatus()) return TryReverse();
    56 		if (!CanEnterNewTile()) return false;
    74 		if (!CanEnterNewTile()) return false;
    57 		m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir);
    75 		m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir);
    74 	FORCEINLINE void FollowTileExit()
    92 	FORCEINLINE void FollowTileExit()
    75 	{
    93 	{
    76 		m_is_station = m_is_bridge = m_is_tunnel = false;
    94 		m_is_station = m_is_bridge = m_is_tunnel = false;
    77 		m_tiles_skipped = 0;
    95 		m_tiles_skipped = 0;
    78 
    96 
    79 		// extra handling for tunnels in our direction
    97 		// extra handling for tunnels and bridges in our direction
    80 		if (IsTunnelTile(m_old_tile)) {
    98 		if (IsTileType(m_old_tile, MP_TUNNELBRIDGE)) {
    81 			DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_old_tile);
    99 			DiagDirection enterdir = GetTunnelBridgeDirection(m_old_tile);
    82 			if (tunnel_enterdir == m_exitdir) {
   100 			if (enterdir == m_exitdir) {
    83 				// we are entering the tunnel
   101 				// we are entering the tunnel / bridge
    84 				FindLengthOfTunnelResult flotr = FindLengthOfTunnel(m_old_tile, m_exitdir);
   102 				if (IsTunnel(m_old_tile)) {
    85 				m_new_tile = flotr.tile;
   103 					m_is_tunnel = true;
    86 				m_is_tunnel = true;
   104 					m_new_tile = GetOtherTunnelEnd(m_old_tile);
    87 				m_tiles_skipped = flotr.length - 1;
   105 				} else { // IsBridge(m_old_tile)
       
   106 					m_is_bridge = true;
       
   107 					m_new_tile = GetOtherBridgeEnd(m_old_tile);
       
   108 				}
       
   109 				m_tiles_skipped = GetTunnelBridgeLength(m_new_tile, m_old_tile);
    88 				return;
   110 				return;
    89 			}
   111 			}
    90 			assert(ReverseDiagDir(tunnel_enterdir) == m_exitdir);
   112 			assert(ReverseDiagDir(enterdir) == m_exitdir);
    91 		}
       
    92 
       
    93 		// extra handling for bridge ramp in our direction
       
    94 		if (IsBridgeTile(m_old_tile)) {
       
    95 			DiagDirection bridge_enterdir = GetTunnelBridgeDirection(m_old_tile);
       
    96 			if (bridge_enterdir == m_exitdir) {
       
    97 				// we are entering the bridge ramp
       
    98 				m_new_tile = GetOtherBridgeEnd(m_old_tile);
       
    99 				uint32 bridge_length = GetBridgeLength(m_old_tile, m_new_tile);
       
   100 				m_tiles_skipped = bridge_length;
       
   101 				m_is_bridge = true;
       
   102 				return;
       
   103 			}
       
   104 			assert(ReverseDiagDir(bridge_enterdir) == m_exitdir);
       
   105 		}
   113 		}
   106 
   114 
   107 		// normal or station tile, do one step
   115 		// normal or station tile, do one step
   108 		TileIndexDiff diff = TileOffsByDiagDir(m_exitdir);
   116 		TileIndexDiff diff = TileOffsByDiagDir(m_exitdir);
   109 		m_new_tile = TILE_ADD(m_old_tile, diff);
   117 		m_new_tile = TILE_ADD(m_old_tile, diff);
   125 		if (IsRailTT() && GetTileType(m_new_tile) == MP_RAILWAY && IsPlainRailTile(m_new_tile)) {
   133 		if (IsRailTT() && GetTileType(m_new_tile) == MP_RAILWAY && IsPlainRailTile(m_new_tile)) {
   126 			m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
   134 			m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
   127 		} else {
   135 		} else {
   128 			uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes);
   136 			uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes);
   129 			m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
   137 			m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
       
   138 
       
   139 			if (m_new_td_bits == 0) {
       
   140 				/* GetTileTrackStatus() returns 0 for single tram bits.
       
   141 				 * As we cannot change it there (easily) without breaking something, change it here */
       
   142 				switch (GetSingleTramBit(m_new_tile)) {
       
   143 					case DIAGDIR_NE:
       
   144 					case DIAGDIR_SW:
       
   145 						m_new_td_bits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW;
       
   146 						break;
       
   147 
       
   148 					case DIAGDIR_NW:
       
   149 					case DIAGDIR_SE:
       
   150 						m_new_td_bits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE;
       
   151 						break;
       
   152 
       
   153 					default: break;
       
   154 				}
       
   155 			}
   130 		}
   156 		}
   131 		return (m_new_td_bits != TRACKDIR_BIT_NONE);
   157 		return (m_new_td_bits != TRACKDIR_BIT_NONE);
   132 	}
   158 	}
   133 
   159 
   134 	/** return true if we can leave m_old_tile in m_exitdir */
   160 	/** return true if we can leave m_old_tile in m_exitdir */
   141 				m_err = EC_NO_WAY;
   167 				m_err = EC_NO_WAY;
   142 				return false;
   168 				return false;
   143 			}
   169 			}
   144 		}
   170 		}
   145 
   171 
       
   172 		/* single tram bits can only be left in one direction */
       
   173 		DiagDirection single_tram = GetSingleTramBit(m_old_tile);
       
   174 		if (single_tram != INVALID_DIAGDIR && single_tram != m_exitdir) {
       
   175 			m_err = EC_NO_WAY;
       
   176 			return false;
       
   177 		}
       
   178 
   146 		// road depots can be also left in one direction only
   179 		// road depots can be also left in one direction only
   147 		if (IsRoadTT() && IsTileDepotType(m_old_tile, TT())) {
   180 		if (IsRoadTT() && IsTileDepotType(m_old_tile, TT())) {
   148 			DiagDirection exitdir = GetRoadDepotDirection(m_old_tile);
   181 			DiagDirection exitdir = GetRoadDepotDirection(m_old_tile);
   149 			if (exitdir != m_exitdir) {
   182 			if (exitdir != m_exitdir) {
   150 				m_err = EC_NO_WAY;
   183 				m_err = EC_NO_WAY;
   162 			DiagDirection exitdir = GetRoadStopDir(m_new_tile);
   195 			DiagDirection exitdir = GetRoadStopDir(m_new_tile);
   163 			if (ReverseDiagDir(exitdir) != m_exitdir) {
   196 			if (ReverseDiagDir(exitdir) != m_exitdir) {
   164 				m_err = EC_NO_WAY;
   197 				m_err = EC_NO_WAY;
   165 				return false;
   198 				return false;
   166 			}
   199 			}
       
   200 		}
       
   201 
       
   202 		/* single tram bits can only be entered from one direction */
       
   203 		DiagDirection single_tram = GetSingleTramBit(m_new_tile);
       
   204 		if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(m_exitdir)) {
       
   205 			m_err = EC_NO_WAY;
       
   206 			return false;
   167 		}
   207 		}
   168 
   208 
   169 		// road and rail depots can also be entered from one direction only
   209 		// road and rail depots can also be entered from one direction only
   170 		if (IsRoadTT() && IsTileDepotType(m_new_tile, TT())) {
   210 		if (IsRoadTT() && IsTileDepotType(m_new_tile, TT())) {
   171 			DiagDirection exitdir = GetRoadDepotDirection(m_new_tile);
   211 			DiagDirection exitdir = GetRoadDepotDirection(m_new_tile);
   212 					if (tunnel_enterdir != m_exitdir) {
   252 					if (tunnel_enterdir != m_exitdir) {
   213 						m_err = EC_NO_WAY;
   253 						m_err = EC_NO_WAY;
   214 						return false;
   254 						return false;
   215 					}
   255 					}
   216 				}
   256 				}
   217 			} else if (IsBridge(m_new_tile)) {
   257 			} else { // IsBridge(m_new_tile)
   218 				if (!m_is_bridge) {
   258 				if (!m_is_bridge) {
   219 					DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile);
   259 					DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile);
   220 					if (ramp_enderdir != m_exitdir) {
   260 					if (ramp_enderdir != m_exitdir) {
   221 						m_err = EC_NO_WAY;
   261 						m_err = EC_NO_WAY;
   222 						return false;
   262 						return false;
   240 		}
   280 		}
   241 
   281 
   242 		return true;
   282 		return true;
   243 	}
   283 	}
   244 
   284 
   245 	/** return true if we entered depot and reversed inside */
   285 	/** return true if we must reverse (in depots and single tram bits) */
   246 	FORCEINLINE bool EnteredDepot()
   286 	FORCEINLINE bool ForcedReverse()
   247 	{
   287 	{
   248 		// rail and road depots cause reversing
   288 		// rail and road depots cause reversing
   249 		if (!IsWaterTT() && IsTileDepotType(m_old_tile, TT())) {
   289 		if (!IsWaterTT() && IsTileDepotType(m_old_tile, TT())) {
   250 			DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile);
   290 			DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(m_old_tile) : GetRoadDepotDirection(m_old_tile);
   251 			if (exitdir != m_exitdir) {
   291 			if (exitdir != m_exitdir) {
   256 				m_tiles_skipped = 0;
   296 				m_tiles_skipped = 0;
   257 				m_is_tunnel = m_is_bridge = m_is_station = false;
   297 				m_is_tunnel = m_is_bridge = m_is_station = false;
   258 				return true;
   298 				return true;
   259 			}
   299 			}
   260 		}
   300 		}
       
   301 
       
   302 		// single tram bits cause reversing
       
   303 		if (GetSingleTramBit(m_old_tile) == ReverseDiagDir(m_exitdir)) {
       
   304 			// reverse
       
   305 			m_new_tile = m_old_tile;
       
   306 			m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(m_old_td));
       
   307 			m_exitdir = ReverseDiagDir(m_exitdir);
       
   308 			m_tiles_skipped = 0;
       
   309 			m_is_tunnel = m_is_bridge = m_is_station = false;
       
   310 			return true;
       
   311 		}
       
   312 
   261 		return false;
   313 		return false;
   262 	}
   314 	}
   263 
   315 
   264 	/** return true if we successfully reversed at end of road/track */
   316 	/** return true if we successfully reversed at end of road/track */
   265 	FORCEINLINE bool TryReverse()
   317 	FORCEINLINE bool TryReverse()
   266 	{
   318 	{
   267 		if (IsRoadTT()) {
   319 		if (IsRoadTT() && !IsTram()) {
   268 			// if we reached the end of road, we can reverse the RV and continue moving
   320 			// if we reached the end of road, we can reverse the RV and continue moving
   269 			m_exitdir = ReverseDiagDir(m_exitdir);
   321 			m_exitdir = ReverseDiagDir(m_exitdir);
   270 			// new tile will be the same as old one
   322 			// new tile will be the same as old one
   271 			m_new_tile = m_old_tile;
   323 			m_new_tile = m_old_tile;
   272 			// set new trackdir bits to all reachable trackdirs
   324 			// set new trackdir bits to all reachable trackdirs