# HG changeset patch # User frosch # Date 2008-08-03 14:16:57 # Node ID 848a574624351c0d6e02f3242ee6e6751857a7b2 # Parent a397a0f96cdf1e0115b928ba118b55ad710c0230 (svn r13974) -Fix [YAPP]: A train crash could lead to stale reservations. (michi_cc) diff --git a/src/pbs.cpp b/src/pbs.cpp --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -204,13 +204,24 @@ static PBSTileInfo FollowReservation(Own return PBSTileInfo(tile, trackdir, false); } +/** Callback for VehicleFromPos to find a train on a specific track. */ +static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) +{ + PBSTileInfo info = *(PBSTileInfo *)data; + + if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info.trackdir))) return v; + + return NULL; +} + /** * Follow a train reservation to the last tile. * * @param v the vehicle + * @param train_on_res Is set to a train we might encounter * @returns The last tile of the reservation or the current train tile if no reservation present. */ -PBSTileInfo FollowTrainReservation(const Vehicle *v) +PBSTileInfo FollowTrainReservation(const Vehicle *v, Vehicle **train_on_res) { assert(v->type == VEH_TRAIN); @@ -221,19 +232,10 @@ PBSTileInfo FollowTrainReservation(const PBSTileInfo res = FollowReservation(v->owner, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes, tile, trackdir); res.okay = IsSafeWaitingPosition(v, res.tile, res.trackdir, true, _settings_game.pf.forbid_90_deg); + if (train_on_res != NULL) *train_on_res = VehicleFromPos(res.tile, &res, FindTrainOnTrackEnum); return res; } -/** Callback for VehicleFromPos to find a train on a specific track. */ -static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) -{ - PBSTileInfo info = *(PBSTileInfo *)data; - - if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info.trackdir))) return v; - - return NULL; -} - /** * Find the train which has reserved a specific path. * diff --git a/src/pbs.h b/src/pbs.h --- a/src/pbs.h +++ b/src/pbs.h @@ -27,7 +27,7 @@ struct PBSTileInfo { PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {} }; -PBSTileInfo FollowTrainReservation(const Vehicle *v); +PBSTileInfo FollowTrainReservation(const Vehicle *v, Vehicle **train_on_res = NULL); bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3059,7 +3059,8 @@ bool TryPathReserve(Vehicle *v, bool mar } } - PBSTileInfo origin = FollowTrainReservation(v); + Vehicle *other_train = NULL; + PBSTileInfo origin = FollowTrainReservation(v, &other_train); /* If we have a reserved path and the path ends at a safe tile, we are finished already. */ if (origin.okay && (v->tile != origin.tile || first_tile_okay)) { /* Can't be stuck then. */ @@ -3067,6 +3068,14 @@ bool TryPathReserve(Vehicle *v, bool mar ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK); return true; } + /* The path we are driving on is alread blocked by some other train. + * This can only happen when tracks and signals are changed. A crash + * is probably imminent, don't do any further reservation because + * it might cause stale reservations. */ + if (other_train != NULL && v->tile != origin.tile) { + if (mark_as_stuck) MarkTrainAsStuck(v); + return false; + } /* If we are in a depot, tentativly reserve the depot. */ if (v->u.rail.track & TRACK_BIT_DEPOT) {