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 */