# track_func.h

Go to the documentation of this file.

    00001 /* $Id: track_func.h 17248 2009-08-21 20:21:05Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #ifndef TRACK_FUNC_H
    00013 #define TRACK_FUNC_H
    00014
    00015 #include "core/bitmath_func.hpp"
    00016 #include "track_type.h"
    00017 #include "direction_type.h"
    00018 #include "slope_func.h"
    00019
    00029 static inline Track AxisToTrack(Axis a)
    00030 {
    00031   return (Track)a;
    00032 }
    00033
    00039 static inline TrackBits TrackToTrackBits(Track track)
    00040 {
    00041   return (TrackBits)(1 << track);
    00042 }
    00043
    00049 static inline TrackBits AxisToTrackBits(Axis a)
    00050 {
    00051   return TrackToTrackBits(AxisToTrack(a));
    00052 }
    00053
    00060 static inline TrackBits CornerToTrackBits(Corner corner)
    00061 {
    00062   extern const TrackBits _corner_to_trackbits[];
    00063   assert(IsValidCorner(corner));
    00064   return _corner_to_trackbits[corner];
    00065 }
    00066
    00067
    00068
    00074 static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
    00075 {
    00076   return (TrackdirBits)(1 << trackdir);
    00077 }
    00078
    00093 static inline Track RemoveFirstTrack(TrackBits *tracks)
    00094 {
    00095   if (*tracks != TRACK_BIT_NONE && *tracks != INVALID_TRACK_BIT) {
    00096     Track first = (Track)FIND_FIRST_BIT(*tracks);
    00097     ClrBit(*tracks, first);
    00098     return first;
    00099   }
    00100   return INVALID_TRACK;
    00101 }
    00102
    00117 static inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
    00118 {
    00119   if (*trackdirs != TRACKDIR_BIT_NONE && *trackdirs != INVALID_TRACKDIR_BIT) {
    00120     Trackdir first = (Trackdir)FindFirstBit2x64(*trackdirs);
    00121     ClrBit(*trackdirs, first);
    00122     return first;
    00123   }
    00124   return INVALID_TRACKDIR;
    00125 }
    00126
    00137 static inline Track FindFirstTrack(TrackBits tracks)
    00138 {
    00139   return (tracks != TRACK_BIT_NONE && tracks != INVALID_TRACK_BIT) ? (Track)FIND_FIRST_BIT(tracks) : INVALID_TRACK;
    00140 }
    00141
    00153 static inline Track TrackBitsToTrack(TrackBits tracks)
    00154 {
    00155   assert(tracks == INVALID_TRACK_BIT || (tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE));
    00156   return tracks != INVALID_TRACK_BIT ? (Track)FIND_FIRST_BIT(tracks & TRACK_BIT_MASK) : INVALID_TRACK;
    00157 }
    00158
    00171 static inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
    00172 {
    00173   assert((trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
    00174   return (trackdirs != TRACKDIR_BIT_NONE) ? (Trackdir)FindFirstBit2x64(trackdirs) : INVALID_TRACKDIR;
    00175 }
    00176
    00184 static inline bool IsValidTrack(Track track)
    00185 {
    00186   return track < TRACK_END;
    00187 }
    00188
    00196 static inline bool IsValidTrackdir(Trackdir trackdir)
    00197 {
    00198   return (TrackdirToTrackdirBits(trackdir) & TRACKDIR_BIT_MASK) != 0;
    00199 }
    00200
    00201
    00202 /*
    00203  * Functions describing logical relations between Tracks, TrackBits, Trackdirs
    00204  * TrackdirBits, Direction and DiagDirections.
    00205  */
    00206
    00216 static inline Track TrackToOppositeTrack(Track t)
    00217 {
    00218   assert(t != INVALID_TRACK);
    00219   return (Track)(t ^ 1);
    00220 }
    00221
    00232 static inline Trackdir ReverseTrackdir(Trackdir trackdir)
    00233 {
    00234   assert(trackdir != INVALID_TRACKDIR);
    00235   return (Trackdir)(trackdir ^ 8);
    00236 }
    00237
    00247 static inline Track TrackdirToTrack(Trackdir trackdir)
    00248 {
    00249   return (Track)(trackdir & 0x7);
    00250 }
    00251
    00263 static inline Trackdir TrackToTrackdir(Track track)
    00264 {
    00265   return (Trackdir)track;
    00266 }
    00267
    00277 static inline TrackdirBits TrackToTrackdirBits(Track track)
    00278 {
    00279   Trackdir td = TrackToTrackdir(track);
    00280   return (TrackdirBits)(TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td)));
    00281 }
    00282
    00291 static inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
    00292 {
    00293   return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK);
    00294 }
    00295
    00302 static inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
    00303 {
    00304   return (TrackdirBits)(bits * 0x101);
    00305 }
    00306
    00313 static inline TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
    00314 {
    00315   return (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
    00316 }
    00317
    00324 static inline TrackBits TrackStatusToTrackBits(TrackStatus ts)
    00325 {
    00326   return TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(ts));
    00327 }
    00328
    00337 static inline TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
    00338 {
    00339   return (TrackdirBits)((ts >> 16) & TRACKDIR_BIT_MASK);
    00340 }
    00341
    00349 static inline TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
    00350 {
    00351   return (TrackStatus)(trackdirbits | (red_signals << 16));
    00352 }
    00353
    00364 static inline Trackdir NextTrackdir(Trackdir trackdir)
    00365 {
    00366   extern const Trackdir _next_trackdir[TRACKDIR_END];
    00367   return _next_trackdir[trackdir];
    00368 }
    00369
    00380 static inline TrackBits TrackCrossesTracks(Track track)
    00381 {
    00382   extern const TrackBits _track_crosses_tracks[TRACK_END];
    00383   return _track_crosses_tracks[track];
    00384 }
    00385
    00398 static inline DiagDirection TrackdirToExitdir(Trackdir trackdir)
    00399 {
    00400   extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END];
    00401   return _trackdir_to_exitdir[trackdir];
    00402 }
    00403
    00419 static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
    00420 {
    00421   extern const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END];
    00422   return _track_exitdir_to_trackdir[track][diagdir];
    00423 }
    00424
    00442 static inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
    00443 {
    00444   extern const Trackdir _track_enterdir_to_trackdir[TRACK_END][DIAGDIR_END];
    00445   return _track_enterdir_to_trackdir[track][diagdir];
    00446 }
    00447
    00452 static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir)
    00453 {
    00454   extern const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END];
    00455   return _track_direction_to_trackdir[track][dir];
    00456 }
    00457
    00464 static inline Track DiagDirToDiagTrack(DiagDirection diagdir)
    00465 {
    00466   return (Track)(diagdir & 1);
    00467 }
    00468
    00475 static inline TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
    00476 {
    00477   return TrackToTrackBits(DiagDirToDiagTrack(diagdir));
    00478 }
    00479
    00487 static inline Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
    00488 {
    00489   extern const Trackdir _dir_to_diag_trackdir[DIAGDIR_END];
    00490   return _dir_to_diag_trackdir[diagdir];
    00491 }
    00492
    00504 static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
    00505 {
    00506   extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
    00507   return _exitdir_reaches_trackdirs[diagdir];
    00508 }
    00509
    00521 static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); }
    00522
    00532 static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
    00533 {
    00534   extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
    00535   return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)];
    00536 }
    00537 /* Note that there is no direct table for this function (there used to be),
    00538  * but it uses two simpeler tables to achieve the result */
    00539
    00553 static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
    00554 {
    00555   extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END];
    00556   return _track_crosses_trackdirs[TrackdirToTrack(trackdir)];
    00557 }
    00558
    00565 static inline bool IsDiagonalTrack(Track track)
    00566 {
    00567   return (track == TRACK_X) || (track == TRACK_Y);
    00568 }
    00569
    00576 static inline bool IsDiagonalTrackdir(Trackdir trackdir)
    00577 {
    00578   return IsDiagonalTrack(TrackdirToTrack(trackdir));
    00579 }
    00580
    00581
    00589 static inline bool TracksOverlap(TrackBits bits)
    00590 {
    00591   /* With no, or only one track, there is no overlap */
    00592   if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false;
    00593   /* We know that there are at least two tracks present. When there are more
    00594    * than 2 tracks, they will surely overlap. When there are two, they will
    00595    * always overlap unless they are lower & upper or right & left. */
    00596   return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT;
    00597 }
    00598
    00606 static inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
    00607 {
    00608   if (HasBit(tracks, track)) return true;
    00609   return TracksOverlap(tracks | TrackToTrackBits(track));
    00610 }
    00611
    00617 static inline bool IsReversingRoadTrackdir(Trackdir dir)
    00618 {
    00619   return (dir & 0x07) >= 6;
    00620 }
    00621
    00627 static inline bool IsStraightRoadTrackdir(Trackdir dir)
    00628 {
    00629   return (dir & 0x06) == 0;
    00630 }
    00631
    00642 static inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
    00643 {
    00644   extern const TrackdirBits _uphill_trackdirs[];
    00645   return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir);
    00646 }
    00647
    00648 #endif /* TRACK_FUNC_H */