summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2008-08-03 14:16:57 +0000
committerfrosch <frosch@openttd.org>2008-08-03 14:16:57 +0000
commit983e297ff0836199d6544a3201ea51c7525bd849 (patch)
tree91aa49f7db5969ec5f76576c6d2f900a65774dd8
parent9a1958be91096d77294c196fa543d6e45b7c9873 (diff)
downloadopenttd-983e297ff0836199d6544a3201ea51c7525bd849.tar.xz
(svn r13974) -Fix [YAPP]: A train crash could lead to stale reservations. (michi_cc)
-rw-r--r--src/pbs.cpp24
-rw-r--r--src/pbs.h2
-rw-r--r--src/train_cmd.cpp11
3 files changed, 24 insertions, 13 deletions
diff --git a/src/pbs.cpp b/src/pbs.cpp
index 089591e9b..bf3913bc4 100644
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -204,13 +204,24 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
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 Vehicle *v)
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
index 8a6a5533f..d01123ed1 100644
--- 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
index efdbd5c2a..dc7ff694c 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -3059,7 +3059,8 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
}
}
- 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 mark_as_stuck, bool first_tile_okay)
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) {