00001 /* $Id: track_func.h 12313 2008-02-28 17:34:34Z frosch $ */ 00002 00005 #ifndef TRACK_FUNC_H 00006 #define TRACK_FUNC_H 00007 00008 #include "core/bitmath_func.hpp" 00009 #include "track_type.h" 00010 #include "direction_type.h" 00011 #include "slope_func.h" 00012 00022 static inline Track AxisToTrack(Axis a) 00023 { 00024 return (Track)a; 00025 } 00026 00027 00028 00034 static inline TrackBits TrackToTrackBits(Track track) 00035 { 00036 return (TrackBits)(1 << track); 00037 } 00038 00044 static inline TrackBits AxisToTrackBits(Axis a) 00045 { 00046 return TrackToTrackBits(AxisToTrack(a)); 00047 } 00048 00055 static inline TrackBits CornerToTrackBits(Corner corner) 00056 { 00057 extern const TrackBits _corner_to_trackbits[]; 00058 assert(IsValidCorner(corner)); 00059 return _corner_to_trackbits[corner]; 00060 } 00061 00062 00063 00069 static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) 00070 { 00071 return (TrackdirBits)(1 << trackdir); 00072 } 00073 00088 static inline Track RemoveFirstTrack(TrackBits *tracks) 00089 { 00090 if (*tracks != TRACK_BIT_NONE && *tracks != INVALID_TRACK_BIT) { 00091 Track first = (Track)FIND_FIRST_BIT(*tracks); 00092 ClrBit(*tracks, first); 00093 return first; 00094 } 00095 return INVALID_TRACK; 00096 } 00097 00112 static inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs) 00113 { 00114 if (*trackdirs != TRACKDIR_BIT_NONE && *trackdirs != INVALID_TRACKDIR_BIT) { 00115 Trackdir first = (Trackdir)FindFirstBit2x64(*trackdirs); 00116 ClrBit(*trackdirs, first); 00117 return first; 00118 } 00119 return INVALID_TRACKDIR; 00120 } 00121 00132 static inline Track FindFirstTrack(TrackBits tracks) 00133 { 00134 return (tracks != TRACK_BIT_NONE && tracks != INVALID_TRACK_BIT) ? (Track)FIND_FIRST_BIT(tracks) : INVALID_TRACK; 00135 } 00136 00148 static inline Track TrackBitsToTrack(TrackBits tracks) 00149 { 00150 assert(tracks == INVALID_TRACK_BIT || (tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE)); 00151 return tracks != INVALID_TRACK_BIT ? (Track)FIND_FIRST_BIT(tracks & TRACK_BIT_MASK) : INVALID_TRACK; 00152 } 00153 00166 static inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs) 00167 { 00168 assert((trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE); 00169 return (trackdirs != TRACKDIR_BIT_NONE) ? (Trackdir)FindFirstBit2x64(trackdirs) : INVALID_TRACKDIR; 00170 } 00171 00179 static inline bool IsValidTrack(Track track) 00180 { 00181 return track < TRACK_END; 00182 } 00183 00191 static inline bool IsValidTrackdir(Trackdir trackdir) 00192 { 00193 return (TrackdirToTrackdirBits(trackdir) & TRACKDIR_BIT_MASK) != 0; 00194 } 00195 00196 00197 /* 00198 * Functions describing logical relations between Tracks, TrackBits, Trackdirs 00199 * TrackdirBits, Direction and DiagDirections. 00200 */ 00201 00212 static inline Trackdir ReverseTrackdir(Trackdir trackdir) 00213 { 00214 assert(trackdir != INVALID_TRACKDIR); 00215 return (Trackdir)(trackdir ^ 8); 00216 } 00217 00227 static inline Track TrackdirToTrack(Trackdir trackdir) 00228 { 00229 return (Track)(trackdir & 0x7); 00230 } 00231 00243 static inline Trackdir TrackToTrackdir(Track track) 00244 { 00245 return (Trackdir)track; 00246 } 00247 00257 static inline TrackdirBits TrackToTrackdirBits(Track track) 00258 { 00259 Trackdir td = TrackToTrackdir(track); 00260 return (TrackdirBits)(TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td))); 00261 } 00262 00271 static inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits) 00272 { 00273 return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK); 00274 } 00275 00282 static inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits) 00283 { 00284 return (TrackdirBits)(bits * 0x101); 00285 } 00286 00293 static inline TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts) 00294 { 00295 return (TrackdirBits)(ts & TRACKDIR_BIT_MASK); 00296 } 00297 00304 static inline TrackBits TrackStatusToTrackBits(TrackStatus ts) 00305 { 00306 return TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(ts)); 00307 } 00308 00317 static inline TrackdirBits TrackStatusToRedSignals(TrackStatus ts) 00318 { 00319 return (TrackdirBits)((ts >> 16) & TRACKDIR_BIT_MASK); 00320 } 00321 00329 static inline TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals) 00330 { 00331 return (TrackStatus)(trackdirbits | (red_signals << 16)); 00332 } 00333 00344 static inline Trackdir NextTrackdir(Trackdir trackdir) 00345 { 00346 extern const Trackdir _next_trackdir[TRACKDIR_END]; 00347 return _next_trackdir[trackdir]; 00348 } 00349 00360 static inline TrackBits TrackCrossesTracks(Track track) 00361 { 00362 extern const TrackBits _track_crosses_tracks[TRACK_END]; 00363 return _track_crosses_tracks[track]; 00364 } 00365 00378 static inline DiagDirection TrackdirToExitdir(Trackdir trackdir) 00379 { 00380 extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END]; 00381 return _trackdir_to_exitdir[trackdir]; 00382 } 00383 00399 static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir) 00400 { 00401 extern const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END]; 00402 return _track_exitdir_to_trackdir[track][diagdir]; 00403 } 00404 00422 static inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir) 00423 { 00424 extern const Trackdir _track_enterdir_to_trackdir[TRACK_END][DIAGDIR_END]; 00425 return _track_enterdir_to_trackdir[track][diagdir]; 00426 } 00427 00432 static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir) 00433 { 00434 extern const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END]; 00435 return _track_direction_to_trackdir[track][dir]; 00436 } 00437 00445 static inline Trackdir DiagdirToDiagTrackdir(DiagDirection diagdir) 00446 { 00447 extern const Trackdir _dir_to_diag_trackdir[DIAGDIR_END]; 00448 return _dir_to_diag_trackdir[diagdir]; 00449 } 00450 00462 static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir) 00463 { 00464 extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END]; 00465 return _exitdir_reaches_trackdirs[diagdir]; 00466 } 00467 00479 static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); } 00480 00490 static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) 00491 { 00492 extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END]; 00493 return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; 00494 } 00495 /* Note that there is no direct table for this function (there used to be), 00496 * but it uses two simpeler tables to achieve the result */ 00497 00511 static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir) 00512 { 00513 extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END]; 00514 return _track_crosses_trackdirs[TrackdirToTrack(trackdir)]; 00515 } 00516 00523 static inline bool IsDiagonalTrack(Track track) 00524 { 00525 return (track == TRACK_X) || (track == TRACK_Y); 00526 } 00527 00534 static inline bool IsDiagonalTrackdir(Trackdir trackdir) 00535 { 00536 return IsDiagonalTrack(TrackdirToTrack(trackdir)); 00537 } 00538 00539 00547 static inline bool TracksOverlap(TrackBits bits) 00548 { 00549 /* With no, or only one track, there is no overlap */ 00550 if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false; 00551 /* We know that there are at least two tracks present. When there are more 00552 * than 2 tracks, they will surely overlap. When there are two, they will 00553 * always overlap unless they are lower & upper or right & left. */ 00554 return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT; 00555 } 00556 00562 static inline bool IsReversingRoadTrackdir(Trackdir dir) 00563 { 00564 return (dir & 0x07) >= 6; 00565 } 00566 00572 static inline bool IsStraightRoadTrackdir(Trackdir dir) 00573 { 00574 return (dir & 0x06) == 0; 00575 } 00576 00587 static inline bool IsUphillTrackdir(Slope slope, Trackdir dir) 00588 { 00589 extern const TrackdirBits _uphill_trackdirs[]; 00590 return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir); 00591 } 00592 00593 #endif /* TRACK_FUNC_H */