--- a/src/yapf/follow_track.hpp Sun Feb 03 01:34:21 2008 +0000
+++ b/src/yapf/follow_track.hpp Sun Feb 03 20:34:26 2008 +0000
@@ -37,9 +37,26 @@
FORCEINLINE static TransportType TT() {return Ttr_type_;}
FORCEINLINE static bool IsWaterTT() {return TT() == TRANSPORT_WATER;}
FORCEINLINE static bool IsRailTT() {return TT() == TRANSPORT_RAIL;}
+ FORCEINLINE bool IsTram() {return IsRoadTT() && HasBit(m_veh->u.road.compatible_roadtypes, ROADTYPE_TRAM);}
FORCEINLINE static bool IsRoadTT() {return TT() == TRANSPORT_ROAD;}
FORCEINLINE static bool Allow90degTurns() {return T90deg_turns_allowed_;}
+ /** Tests if a tile is a road tile with a single tramtrack (tram can reverse) */
+ FORCEINLINE DiagDirection GetSingleTramBit(TileIndex tile)
+ {
+ if (IsTram() && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
+ RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
+ switch (rb) {
+ case ROAD_NW: return DIAGDIR_NW;
+ case ROAD_SW: return DIAGDIR_SW;
+ case ROAD_SE: return DIAGDIR_SE;
+ case ROAD_NE: return DIAGDIR_NE;
+ default: break;
+ }
+ }
+ return INVALID_DIAGDIR;
+ }
+
/** main follower routine. Fills all members and return true on success.
* Otherwise returns false if track can't be followed. */
FORCEINLINE bool Follow(TileIndex old_tile, Trackdir old_td)
@@ -47,9 +64,10 @@
m_old_tile = old_tile;
m_old_td = old_td;
m_err = EC_NONE;
- assert((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0);
+ assert(((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
+ (GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits
m_exitdir = TrackdirToExitdir(m_old_td);
- if (EnteredDepot()) return true;
+ if (ForcedReverse()) return true;
if (!CanExitOldTile()) return false;
FollowTileExit();
if (!QueryNewTileTrackStatus()) return TryReverse();
@@ -76,32 +94,22 @@
m_is_station = m_is_bridge = m_is_tunnel = false;
m_tiles_skipped = 0;
- // extra handling for tunnels in our direction
- if (IsTunnelTile(m_old_tile)) {
- DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(m_old_tile);
- if (tunnel_enterdir == m_exitdir) {
- // we are entering the tunnel
- FindLengthOfTunnelResult flotr = FindLengthOfTunnel(m_old_tile, m_exitdir);
- m_new_tile = flotr.tile;
- m_is_tunnel = true;
- m_tiles_skipped = flotr.length - 1;
+ // extra handling for tunnels and bridges in our direction
+ if (IsTileType(m_old_tile, MP_TUNNELBRIDGE)) {
+ DiagDirection enterdir = GetTunnelBridgeDirection(m_old_tile);
+ if (enterdir == m_exitdir) {
+ // we are entering the tunnel / bridge
+ if (IsTunnel(m_old_tile)) {
+ m_is_tunnel = true;
+ m_new_tile = GetOtherTunnelEnd(m_old_tile);
+ } else { // IsBridge(m_old_tile)
+ m_is_bridge = true;
+ m_new_tile = GetOtherBridgeEnd(m_old_tile);
+ }
+ m_tiles_skipped = GetTunnelBridgeLength(m_new_tile, m_old_tile);
return;
}
- assert(ReverseDiagDir(tunnel_enterdir) == m_exitdir);
- }
-
- // extra handling for bridge ramp in our direction
- if (IsBridgeTile(m_old_tile)) {
- DiagDirection bridge_enterdir = GetTunnelBridgeDirection(m_old_tile);
- if (bridge_enterdir == m_exitdir) {
- // we are entering the bridge ramp
- m_new_tile = GetOtherBridgeEnd(m_old_tile);
- uint32 bridge_length = GetBridgeLength(m_old_tile, m_new_tile);
- m_tiles_skipped = bridge_length;
- m_is_bridge = true;
- return;
- }
- assert(ReverseDiagDir(bridge_enterdir) == m_exitdir);
+ assert(ReverseDiagDir(enterdir) == m_exitdir);
}
// normal or station tile, do one step
@@ -127,6 +135,24 @@
} else {
uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes);
m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
+
+ if (m_new_td_bits == 0) {
+ /* GetTileTrackStatus() returns 0 for single tram bits.
+ * As we cannot change it there (easily) without breaking something, change it here */
+ switch (GetSingleTramBit(m_new_tile)) {
+ case DIAGDIR_NE:
+ case DIAGDIR_SW:
+ m_new_td_bits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW;
+ break;
+
+ case DIAGDIR_NW:
+ case DIAGDIR_SE:
+ m_new_td_bits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE;
+ break;
+
+ default: break;
+ }
+ }
}
return (m_new_td_bits != TRACKDIR_BIT_NONE);
}
@@ -143,6 +169,13 @@
}
}
+ /* single tram bits can only be left in one direction */
+ DiagDirection single_tram = GetSingleTramBit(m_old_tile);
+ if (single_tram != INVALID_DIAGDIR && single_tram != m_exitdir) {
+ m_err = EC_NO_WAY;
+ return false;
+ }
+
// road depots can be also left in one direction only
if (IsRoadTT() && IsTileDepotType(m_old_tile, TT())) {
DiagDirection exitdir = GetRoadDepotDirection(m_old_tile);
@@ -166,6 +199,13 @@
}
}
+ /* single tram bits can only be entered from one direction */
+ DiagDirection single_tram = GetSingleTramBit(m_new_tile);
+ if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(m_exitdir)) {
+ m_err = EC_NO_WAY;
+ return false;
+ }
+
// road and rail depots can also be entered from one direction only
if (IsRoadTT() && IsTileDepotType(m_new_tile, TT())) {
DiagDirection exitdir = GetRoadDepotDirection(m_new_tile);
@@ -214,7 +254,7 @@
return false;
}
}
- } else if (IsBridge(m_new_tile)) {
+ } else { // IsBridge(m_new_tile)
if (!m_is_bridge) {
DiagDirection ramp_enderdir = GetTunnelBridgeDirection(m_new_tile);
if (ramp_enderdir != m_exitdir) {
@@ -242,8 +282,8 @@
return true;
}
- /** return true if we entered depot and reversed inside */
- FORCEINLINE bool EnteredDepot()
+ /** return true if we must reverse (in depots and single tram bits) */
+ FORCEINLINE bool ForcedReverse()
{
// rail and road depots cause reversing
if (!IsWaterTT() && IsTileDepotType(m_old_tile, TT())) {
@@ -258,13 +298,25 @@
return true;
}
}
+
+ // single tram bits cause reversing
+ if (GetSingleTramBit(m_old_tile) == ReverseDiagDir(m_exitdir)) {
+ // reverse
+ m_new_tile = m_old_tile;
+ m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(m_old_td));
+ m_exitdir = ReverseDiagDir(m_exitdir);
+ m_tiles_skipped = 0;
+ m_is_tunnel = m_is_bridge = m_is_station = false;
+ return true;
+ }
+
return false;
}
/** return true if we successfully reversed at end of road/track */
FORCEINLINE bool TryReverse()
{
- if (IsRoadTT()) {
+ if (IsRoadTT() && !IsTram()) {
// if we reached the end of road, we can reverse the RV and continue moving
m_exitdir = ReverseDiagDir(m_exitdir);
// new tile will be the same as old one