mirror of https://github.com/OpenTTD/OpenTTD
(svn r3329) - Doc: Some documentation cleanups.
- Add: TracksOverlap() (from the map branch), TrackdirBitsToTrackBits(), DiagdirReachesTrackdirs(), DiagdirReachesTracks(). - Fix: Infinite loop in the pathfinder introduces in r3321.release/0.4.5
parent
be01586049
commit
128317d3ec
39
pathfind.c
39
pathfind.c
|
@ -585,6 +585,13 @@ static bool NtpVisit(NewTrackPathFinder *tpf, TileIndex tile, uint dir, uint len
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the shortest path to the given tile/dir so far is still the given
|
||||||
|
* length.
|
||||||
|
* @return true if the length is still the same
|
||||||
|
* @pre The given tile/dir combination should be present in the hash, by a
|
||||||
|
* previous call to NtpVisit().
|
||||||
|
*/
|
||||||
static bool NtpCheck(NewTrackPathFinder *tpf, TileIndex tile, uint dir, uint length)
|
static bool NtpCheck(NewTrackPathFinder *tpf, TileIndex tile, uint dir, uint length)
|
||||||
{
|
{
|
||||||
uint hash,head,offs;
|
uint hash,head,offs;
|
||||||
|
@ -666,7 +673,9 @@ static const byte _length_of_track[16] = {
|
||||||
|
|
||||||
static void NTPEnum(NewTrackPathFinder *tpf, TileIndex tile, uint direction)
|
static void NTPEnum(NewTrackPathFinder *tpf, TileIndex tile, uint direction)
|
||||||
{
|
{
|
||||||
uint bits, tile_org, track;
|
TrackBits bits, allbits;
|
||||||
|
uint track;
|
||||||
|
TileIndex tile_org;
|
||||||
StackedItem si;
|
StackedItem si;
|
||||||
FindLengthOfTunnelResult flotr;
|
FindLengthOfTunnelResult flotr;
|
||||||
int estimation;
|
int estimation;
|
||||||
|
@ -745,8 +754,7 @@ start_at:
|
||||||
bits = (bits | (bits >> 8)) & 0x3F;
|
bits = (bits | (bits >> 8)) & 0x3F;
|
||||||
|
|
||||||
// Check that the tile contains exactly one track
|
// Check that the tile contains exactly one track
|
||||||
if (bits == 0 || KILL_FIRST_BIT(bits) != 0)
|
if (bits == 0 || KILL_FIRST_BIT(bits) != 0) break;
|
||||||
break;
|
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// If we reach here, the tile has exactly one track.
|
// If we reach here, the tile has exactly one track.
|
||||||
|
@ -759,16 +767,18 @@ start_at:
|
||||||
goto callback_and_continue;
|
goto callback_and_continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular rail tile, determine which tracks exist.
|
/* Regular rail tile, determine which tracks exist. */
|
||||||
bits = _m[tile].m5 & _bits_mask[direction];
|
allbits = _m[tile].m5 & TRACK_BIT_MASK;
|
||||||
|
/* Which tracks are reachable? */
|
||||||
|
bits = allbits & DiagdirReachesTracks(direction);
|
||||||
|
|
||||||
// The tile has no reachable tracks, or
|
/* The tile has no reachable tracks => End of rail segment
|
||||||
// does the tile contain more than one track?
|
* or Intersection => End of rail segment. We check this agains all the
|
||||||
if (bits == 0 || KILL_FIRST_BIT(bits) != 0)
|
* bits, not just reachable ones, to prevent infinite loops. */
|
||||||
break;
|
if (bits == 0 || TracksOverlap(allbits)) break;
|
||||||
|
|
||||||
// If we reach here, the tile has exactly one track, and this
|
/* If we reach here, the tile has exactly one track, and this
|
||||||
// track is reachable.
|
track is reachable => Rail segment continues */
|
||||||
|
|
||||||
track = _new_track[FIND_FIRST_BIT(bits)][direction];
|
track = _new_track[FIND_FIRST_BIT(bits)][direction];
|
||||||
assert(track != 0xff);
|
assert(track != 0xff);
|
||||||
|
@ -788,7 +798,7 @@ start_at:
|
||||||
|
|
||||||
m3 = _m[tile].m3;
|
m3 = _m[tile].m3;
|
||||||
if (!(m3 & SignalAlongTrackdir(track))) {
|
if (!(m3 & SignalAlongTrackdir(track))) {
|
||||||
// if one way signal not pointing towards us, stop going in this direction.
|
// if one way signal not pointing towards us, stop going in this direction => End of rail segment.
|
||||||
if (m3 & SignalAgainstTrackdir(track)) {
|
if (m3 & SignalAgainstTrackdir(track)) {
|
||||||
bits = 0;
|
bits = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -800,7 +810,7 @@ start_at:
|
||||||
// reached a red signal.
|
// reached a red signal.
|
||||||
if (m3 & SignalAgainstTrackdir(track)) {
|
if (m3 & SignalAgainstTrackdir(track)) {
|
||||||
// two way red signal. unless we passed another green signal on the way,
|
// two way red signal. unless we passed another green signal on the way,
|
||||||
// stop going in this direction.
|
// stop going in this direction => End of rail segment.
|
||||||
// this is to prevent us from going into a full platform.
|
// this is to prevent us from going into a full platform.
|
||||||
if (!(si.state&1)) {
|
if (!(si.state&1)) {
|
||||||
bits = 0;
|
bits = 0;
|
||||||
|
@ -819,7 +829,7 @@ start_at:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tpf->enum_proc(tile, tpf->userdata, si.first_track, si.cur_length))
|
if (tpf->enum_proc(tile, tpf->userdata, si.first_track, si.cur_length))
|
||||||
return;
|
return; /* Don't process this tile any further */
|
||||||
}
|
}
|
||||||
|
|
||||||
// continue with the next track
|
// continue with the next track
|
||||||
|
@ -864,6 +874,7 @@ start_at:
|
||||||
si.tile = tile;
|
si.tile = tile;
|
||||||
do {
|
do {
|
||||||
si.track = _new_track[FIND_FIRST_BIT(bits)][direction];
|
si.track = _new_track[FIND_FIRST_BIT(bits)][direction];
|
||||||
|
assert(si.track != 0xFF);
|
||||||
si.priority = si.cur_length + estimation;
|
si.priority = si.cur_length + estimation;
|
||||||
|
|
||||||
// out of stack items, bail out?
|
// out of stack items, bail out?
|
||||||
|
|
58
rail.h
58
rail.h
|
@ -341,26 +341,36 @@ static inline Trackdir ReverseTrackdir(Trackdir trackdir) {
|
||||||
return _reverse_trackdir[trackdir];
|
return _reverse_trackdir[trackdir];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Maps a Track to the corresponding TrackBits value
|
* Maps a Track to the corresponding TrackBits value
|
||||||
*/
|
*/
|
||||||
static inline TrackBits TrackToTrackBits(Track track) { return (TrackBits)(1 << track); }
|
static inline TrackBits TrackToTrackBits(Track track) { return (TrackBits)(1 << track); }
|
||||||
|
|
||||||
/* Returns the Track that a given Trackdir represents */
|
/**
|
||||||
|
* Returns the Track that a given Trackdir represents
|
||||||
|
*/
|
||||||
static inline Track TrackdirToTrack(Trackdir trackdir) { return (Track)(trackdir & 0x7); }
|
static inline Track TrackdirToTrack(Trackdir trackdir) { return (Track)(trackdir & 0x7); }
|
||||||
|
|
||||||
/* Returns a Trackdir for the given Track. Since every Track corresponds to
|
/**
|
||||||
|
* Returns a Trackdir for the given Track. Since every Track corresponds to
|
||||||
* two Trackdirs, we choose the one which points between NE and S.
|
* two Trackdirs, we choose the one which points between NE and S.
|
||||||
* Note that the actual implementation is quite futile, but this might change
|
* Note that the actual implementation is quite futile, but this might change
|
||||||
* in the future.
|
* in the future.
|
||||||
*/
|
*/
|
||||||
static inline Trackdir TrackToTrackdir(Track track) { return (Trackdir)track; }
|
static inline Trackdir TrackToTrackdir(Track track) { return (Trackdir)track; }
|
||||||
|
|
||||||
/* Returns a TrackdirBit mask that contains the two TrackdirBits that
|
/**
|
||||||
|
* Returns a TrackdirBit mask that contains the two TrackdirBits that
|
||||||
* correspond with the given Track (one for each direction).
|
* correspond with the given Track (one for each direction).
|
||||||
*/
|
*/
|
||||||
static inline TrackdirBits TrackToTrackdirBits(Track track) { Trackdir td = TrackToTrackdir(track); return TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td));}
|
static inline TrackdirBits TrackToTrackdirBits(Track track) { Trackdir td = TrackToTrackdir(track); return TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td));}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discards all directional information from the given TrackdirBits. Any
|
||||||
|
* Track which is present in either direction will be present in the result.
|
||||||
|
*/
|
||||||
|
static inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits) { return bits | (bits >> 8); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a trackdir to the trackdir that you will end up on if you go straight
|
* Maps a trackdir to the trackdir that you will end up on if you go straight
|
||||||
* ahead. This will be the same trackdir for diagonal trackdirs, but a
|
* ahead. This will be the same trackdir for diagonal trackdirs, but a
|
||||||
|
@ -424,14 +434,28 @@ static inline Trackdir DiagdirToDiagTrackdir(DiagDirection diagdir) {
|
||||||
return _dir_to_diag_trackdir[diagdir];
|
return _dir_to_diag_trackdir[diagdir];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all trackdirs that can be reached when entering a tile from a given
|
||||||
|
* (diagonal) direction. This will obviously include 90 degree turns, since no
|
||||||
|
* information is available about the exact angle of entering */
|
||||||
|
static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir) { return _exitdir_reaches_trackdirs[diagdir]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all tracks that can be reached when entering a tile from a given
|
||||||
|
* (diagonal) direction. This will obviously include 90 degree turns, since no
|
||||||
|
* information is available about the exact angle of entering */
|
||||||
|
static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a trackdir to the trackdirs that can be reached from it (ie, when
|
* Maps a trackdir to the trackdirs that can be reached from it (ie, when
|
||||||
* entering the next tile. This
|
* entering the next tile. This will include 90 degree turns!
|
||||||
*/
|
*/
|
||||||
extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
|
static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; }
|
||||||
/* Note that there is no direct table for this function (there used to be),
|
/* Note that there is no direct table for this function (there used to be),
|
||||||
* but it uses two simpeler tables to achieve the result */
|
* but it uses two simpeler tables to achieve the result */
|
||||||
static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a trackdir to all trackdirs that make 90 deg turns with it.
|
* Maps a trackdir to all trackdirs that make 90 deg turns with it.
|
||||||
|
@ -594,6 +618,26 @@ static inline bool IsCompatibleRail(RailType enginetype, RailType tiletype)
|
||||||
return HASBIT(GetRailTypeInfo(enginetype)->compatible_railtypes, tiletype);
|
return HASBIT(GetRailTypeInfo(enginetype)->compatible_railtypes, tiletype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given tracks overlap, ie form a crossing. Basically this
|
||||||
|
* means when there is more than one track on the tile, exept when there are
|
||||||
|
* two parallel tracks.
|
||||||
|
* @param bits The tracks present.
|
||||||
|
* @return Whether the tracks present overlap in any way.
|
||||||
|
*/
|
||||||
|
static inline bool TracksOverlap(TrackBits bits)
|
||||||
|
{
|
||||||
|
/* With no, or only one track, there is no overlap */
|
||||||
|
if (bits == 0 || KILL_FIRST_BIT(bits) == 0)
|
||||||
|
return false;
|
||||||
|
/* We know that there are at least two tracks present. When there are more
|
||||||
|
* than 2 tracks, they will surely overlap. When there are two, they will
|
||||||
|
* always overlap unless they are lower & upper or right & left. */
|
||||||
|
if ((bits == (TRACK_BIT_UPPER|TRACK_BIT_LOWER)) || (bits == (TRACK_BIT_LEFT | TRACK_BIT_RIGHT)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DrawTrackBits(TileInfo *ti, TrackBits track, bool earth, bool snow, bool flat);
|
void DrawTrackBits(TileInfo *ti, TrackBits track, bool earth, bool snow, bool flat);
|
||||||
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
|
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
|
||||||
void DrawDefaultWaypointSprite(int x, int y, RailType railtype);
|
void DrawDefaultWaypointSprite(int x, int y, RailType railtype);
|
||||||
|
|
Loading…
Reference in New Issue