# track_func.h

Go to the documentation of this file.

    00001 /* $Id: track_func.h 26105 2013-11-25 13:16:06Z 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_func.h"
    00018 #include "slope_func.h"
    00019
    00029 #define FOR_EACH_SET_TRACK(var, track_bits) FOR_EACH_SET_BIT_EX(Track, var, TrackBits, track_bits)
    00030
    00038 static inline bool IsValidTrack(Track track)
    00039 {
    00040   return track < TRACK_END;
    00041 }
    00042
    00050 static inline bool IsValidTrackdirForRoadVehicle(Trackdir trackdir)
    00051 {
    00052   return trackdir < TRACKDIR_END;
    00053 }
    00054
    00062 static inline bool IsValidTrackdir(Trackdir trackdir)
    00063 {
    00064   return (1 << trackdir & TRACKDIR_BIT_MASK) != 0;
    00065 }
    00066
    00076 static inline Track AxisToTrack(Axis a)
    00077 {
    00078   assert(IsValidAxis(a));
    00079   return (Track)a;
    00080 }
    00081
    00087 static inline TrackBits TrackToTrackBits(Track track)
    00088 {
    00089   assert(IsValidTrack(track));
    00090   return (TrackBits)(1 << track);
    00091 }
    00092
    00098 static inline TrackBits AxisToTrackBits(Axis a)
    00099 {
    00100   return TrackToTrackBits(AxisToTrack(a));
    00101 }
    00102
    00109 static inline TrackBits CornerToTrackBits(Corner corner)
    00110 {
    00111   extern const TrackBits _corner_to_trackbits[];
    00112   assert(IsValidCorner(corner));
    00113   return _corner_to_trackbits[corner];
    00114 }
    00115
    00121 static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
    00122 {
    00123   assert(IsValidTrackdir(trackdir));
    00124   return (TrackdirBits)(1 << trackdir);
    00125 }
    00126
    00141 static inline Track RemoveFirstTrack(TrackBits *tracks)
    00142 {
    00143   if (*tracks != TRACK_BIT_NONE && *tracks != INVALID_TRACK_BIT) {
    00144     assert((*tracks & ~TRACK_BIT_MASK) == TRACK_BIT_NONE);
    00145     Track first = (Track)FIND_FIRST_BIT(*tracks);
    00146     ClrBit(*tracks, first);
    00147     return first;
    00148   }
    00149   return INVALID_TRACK;
    00150 }
    00151
    00166 static inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
    00167 {
    00168   if (*trackdirs != TRACKDIR_BIT_NONE && *trackdirs != INVALID_TRACKDIR_BIT) {
    00169     assert((*trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
    00170     Trackdir first = (Trackdir)FindFirstBit2x64(*trackdirs);
    00171     ClrBit(*trackdirs, first);
    00172     return first;
    00173   }
    00174   return INVALID_TRACKDIR;
    00175 }
    00176
    00187 static inline Track FindFirstTrack(TrackBits tracks)
    00188 {
    00189   return (tracks != TRACK_BIT_NONE && tracks != INVALID_TRACK_BIT) ? (Track)FIND_FIRST_BIT(tracks) : INVALID_TRACK;
    00190 }
    00191
    00203 static inline Track TrackBitsToTrack(TrackBits tracks)
    00204 {
    00205   assert(tracks == INVALID_TRACK_BIT || (tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE));
    00206   return tracks != INVALID_TRACK_BIT ? (Track)FIND_FIRST_BIT(tracks & TRACK_BIT_MASK) : INVALID_TRACK;
    00207 }
    00208
    00221 static inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
    00222 {
    00223   assert((trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
    00224   return (trackdirs != TRACKDIR_BIT_NONE) ? (Trackdir)FindFirstBit2x64(trackdirs) : INVALID_TRACKDIR;
    00225 }
    00226
    00227 /*
    00228  * Functions describing logical relations between Tracks, TrackBits, Trackdirs
    00229  * TrackdirBits, Direction and DiagDirections.
    00230  */
    00231
    00241 static inline Track TrackToOppositeTrack(Track t)
    00242 {
    00243   assert(IsValidTrack(t));
    00244   return (Track)(t ^ 1);
    00245 }
    00246
    00257 static inline Trackdir ReverseTrackdir(Trackdir trackdir)
    00258 {
    00259   assert(IsValidTrackdirForRoadVehicle(trackdir));
    00260   return (Trackdir)(trackdir ^ 8);
    00261 }
    00262
    00272 static inline Track TrackdirToTrack(Trackdir trackdir)
    00273 {
    00274   assert(IsValidTrackdir(trackdir));
    00275   return (Track)(trackdir & 0x7);
    00276 }
    00277
    00289 static inline Trackdir TrackToTrackdir(Track track)
    00290 {
    00291   assert(IsValidTrack(track));
    00292   return (Trackdir)track;
    00293 }
    00294
    00304 static inline TrackdirBits TrackToTrackdirBits(Track track)
    00305 {
    00306   Trackdir td = TrackToTrackdir(track);
    00307   return (TrackdirBits)(TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td)));
    00308 }
    00309
    00318 static inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
    00319 {
    00320   return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK);
    00321 }
    00322
    00329 static inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
    00330 {
    00331   return (TrackdirBits)(bits * 0x101);
    00332 }
    00333
    00340 static inline TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
    00341 {
    00342   return (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
    00343 }
    00344
    00351 static inline TrackBits TrackStatusToTrackBits(TrackStatus ts)
    00352 {
    00353   return TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(ts));
    00354 }
    00355
    00364 static inline TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
    00365 {
    00366   return (TrackdirBits)((ts >> 16) & TRACKDIR_BIT_MASK);
    00367 }
    00368
    00376 static inline TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
    00377 {
    00378   return (TrackStatus)(trackdirbits | (red_signals << 16));
    00379 }
    00380
    00391 static inline Trackdir NextTrackdir(Trackdir trackdir)
    00392 {
    00393   assert(IsValidTrackdir(trackdir));
    00394   extern const Trackdir _next_trackdir[TRACKDIR_END];
    00395   return _next_trackdir[trackdir];
    00396 }
    00397
    00408 static inline TrackBits TrackCrossesTracks(Track track)
    00409 {
    00410   assert(IsValidTrack(track));
    00411   extern const TrackBits _track_crosses_tracks[TRACK_END];
    00412   return _track_crosses_tracks[track];
    00413 }
    00414
    00427 static inline DiagDirection TrackdirToExitdir(Trackdir trackdir)
    00428 {
    00429   assert(IsValidTrackdirForRoadVehicle(trackdir));
    00430   extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END];
    00431   return _trackdir_to_exitdir[trackdir];
    00432 }
    00433
    00449 static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
    00450 {
    00451   assert(IsValidTrack(track));
    00452   assert(IsValidDiagDirection(diagdir));
    00453   extern const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END];
    00454   return _track_exitdir_to_trackdir[track][diagdir];
    00455 }
    00456
    00474 static inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
    00475 {
    00476   assert(IsValidTrack(track));
    00477   assert(IsValidDiagDirection(diagdir));
    00478   extern const Trackdir _track_enterdir_to_trackdir[TRACK_END][DIAGDIR_END];
    00479   return _track_enterdir_to_trackdir[track][diagdir];
    00480 }
    00481
    00486 static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir)
    00487 {
    00488   assert(IsValidTrack(track));
    00489   assert(IsValidDirection(dir));
    00490   extern const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END];
    00491   return _track_direction_to_trackdir[track][dir];
    00492 }
    00493
    00500 static inline Track DiagDirToDiagTrack(DiagDirection diagdir)
    00501 {
    00502   assert(IsValidDiagDirection(diagdir));
    00503   return (Track)(diagdir & 1);
    00504 }
    00505
    00512 static inline TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
    00513 {
    00514   assert(IsValidDiagDirection(diagdir));
    00515   return TrackToTrackBits(DiagDirToDiagTrack(diagdir));
    00516 }
    00517
    00525 static inline Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
    00526 {
    00527   assert(IsValidDiagDirection(diagdir));
    00528   extern const Trackdir _dir_to_diag_trackdir[DIAGDIR_END];
    00529   return _dir_to_diag_trackdir[diagdir];
    00530 }
    00531
    00543 static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
    00544 {
    00545   assert(IsValidDiagDirection(diagdir));
    00546   extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
    00547   return _exitdir_reaches_trackdirs[diagdir];
    00548 }
    00549
    00561 static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); }
    00562
    00572 static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
    00573 {
    00574   assert(IsValidTrackdir(trackdir));
    00575   extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
    00576   return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)];
    00577 }
    00578 /* Note that there is no direct table for this function (there used to be),
    00579  * but it uses two simpler tables to achieve the result */
    00580
    00594 static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
    00595 {
    00596   assert(IsValidTrackdirForRoadVehicle(trackdir));
    00597   extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END];
    00598   return _track_crosses_trackdirs[TrackdirToTrack(trackdir)];
    00599 }
    00600
    00607 static inline bool IsDiagonalTrack(Track track)
    00608 {
    00609   assert(IsValidTrack(track));
    00610   return (track == TRACK_X) || (track == TRACK_Y);
    00611 }
    00612
    00619 static inline bool IsDiagonalTrackdir(Trackdir trackdir)
    00620 {
    00621   assert(IsValidTrackdir(trackdir));
    00622   return IsDiagonalTrack(TrackdirToTrack(trackdir));
    00623 }
    00624
    00625
    00633 static inline bool TracksOverlap(TrackBits bits)
    00634 {
    00635   /* With no, or only one track, there is no overlap */
    00636   if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false;
    00637   /* We know that there are at least two tracks present. When there are more
    00638    * than 2 tracks, they will surely overlap. When there are two, they will
    00639    * always overlap unless they are lower & upper or right & left. */
    00640   return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT;
    00641 }
    00642
    00650 static inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
    00651 {
    00652   if (HasBit(tracks, track)) return true;
    00653   return TracksOverlap(tracks | TrackToTrackBits(track));
    00654 }
    00655
    00661 static inline bool IsReversingRoadTrackdir(Trackdir dir)
    00662 {
    00663   assert(IsValidTrackdirForRoadVehicle(dir));
    00664   return (dir & 0x07) >= 6;
    00665 }
    00666
    00672 static inline bool IsStraightRoadTrackdir(Trackdir dir)
    00673 {
    00674   assert(IsValidTrackdirForRoadVehicle(dir));
    00675   return (dir & 0x06) == 0;
    00676 }
    00677
    00688 static inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
    00689 {
    00690   assert(IsValidTrackdirForRoadVehicle(dir));
    00691   extern const TrackdirBits _uphill_trackdirs[];
    00692   return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir);
    00693 }
    00694
    00695 #endif /* TRACK_FUNC_H */