summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhackykid <hackykid@openttd.org>2005-07-17 20:09:02 +0000
committerhackykid <hackykid@openttd.org>2005-07-17 20:09:02 +0000
commit1d11bbb34da6bb1cfd8d8351f61940c92027ed55 (patch)
tree2aa47a2f10516c02b42213645730108be6987d02
parenteabc48218413f5d3e9e26d3675e32055af8cfc61 (diff)
downloadopenttd-1d11bbb34da6bb1cfd8d8351f61940c92027ed55.tar.xz
(svn r2625) - Fix: [pbs] Store the end of a train's reserved path explicitly. Prevents trains from unreserving eachothers paths in some cases.
- CodeChange: Use the TrackdirToTrack function instead of &7, and remove an unneeded variable.
-rw-r--r--npf.c26
-rw-r--r--pbs.c14
-rw-r--r--pbs.h4
-rw-r--r--train_cmd.c34
-rw-r--r--vehicle.c6
-rw-r--r--vehicle.h2
6 files changed, 57 insertions, 29 deletions
diff --git a/npf.c b/npf.c
index 81601cb97..a1f5e52df 100644
--- a/npf.c
+++ b/npf.c
@@ -180,27 +180,35 @@ void NPFReservePBSPath(AyStar *as)
* BUT, you have to have a pretty fucked up junction layout for this to happen,
* so we'll just stop this train, the user will eventually notice, so he can fix it.
*/
- PBSClearPath(start, trackdir);
+ PBSClearPath(start, trackdir, curr->node.tile, curr->node.direction);
NPFSetFlag(&ftd->node, NPF_FLAG_PBS_BLOCKED, true);
DEBUG(pbs, 1) ("PBS: Self-crossing path!!!");
return;
};
- PBSReserveTrack(curr->node.tile, (curr->node.direction & 7) );
-
- /* we want to reserve the last tile (with the signal) on the path too */
- if (prev != NULL && start == INVALID_TILE) {
- PBSReserveTrack(prev->node.tile, (prev->node.direction & 7) );
- start = prev->node.tile;
- trackdir = ReverseTrackdir(prev->node.direction);
+ PBSReserveTrack(curr->node.tile, TrackdirToTrack(curr->node.direction) );
+
+ /* we want to reserve the last tile (with the signal) on the path too
+ also remember this tile, cause its the end of the path (where we exit the block) */
+ if (start == INVALID_TILE) {
+ if (prev != NULL) {
+ PBSReserveTrack(prev->node.tile, TrackdirToTrack(prev->node.direction) );
+ start = prev->node.tile;
+ trackdir = ReverseTrackdir(prev->node.direction);
+ } else {
+ start = curr->node.tile;
+ trackdir = curr->node.direction;
+ }
}
}
prev = curr;
curr = curr->parent;
} while (curr != NULL);
+ // we remember the tile/track where this path leaves the pbs junction
+ ftd->node.tile = start;
+ ftd->node.direction = trackdir;
}
-
}
diff --git a/pbs.c b/pbs.c
index 493d60690..53711a75b 100644
--- a/pbs.c
+++ b/pbs.c
@@ -189,13 +189,17 @@ void PBSClearTrack(TileIndex tile, Track track) {
MarkTileDirtyByTile(tile);
};
-void PBSClearPath(TileIndex tile, Trackdir trackdir) {
+void PBSClearPath(TileIndex tile, Trackdir trackdir, TileIndex end_tile, Trackdir end_trackdir) {
uint16 res;
FindLengthOfTunnelResult flotr;
assert(IsValidTile(tile));
- assert((trackdir & ~8) <= 5);
+ assert(IsValidTrackdir(trackdir));
+
do {
- PBSClearTrack(tile, trackdir & 7);
+ PBSClearTrack(tile, TrackdirToTrack(trackdir));
+
+ if (tile == end_tile && TrackdirToTrack(trackdir) == TrackdirToTrack(end_trackdir))
+ return;
if (IsTileType(tile, MP_TUNNELBRIDGE) && (_m[tile].m5 & 0xF0)==0 && (unsigned)(_m[tile].m5 & 3) == TrackdirToExitdir(trackdir)) {
// this is a tunnel
@@ -204,11 +208,7 @@ void PBSClearPath(TileIndex tile, Trackdir trackdir) {
tile = flotr.tile;
} else {
byte exitdir = TrackdirToExitdir(trackdir);
- if (IsTileDepotType(tile, TRANSPORT_RAIL) && (exitdir != GetDepotDirection(tile, TRANSPORT_RAIL)))
- return;
tile = AddTileIndexDiffCWrap(tile, TileIndexDiffCByDir(exitdir));
- if (IsTileDepotType(tile, TRANSPORT_RAIL) && (exitdir != ReverseDiagdir(GetDepotDirection(tile, TRANSPORT_RAIL))))
- return;
};
res = PBSTileReserved(tile);
diff --git a/pbs.h b/pbs.h
index 398bd73d9..013802ee6 100644
--- a/pbs.h
+++ b/pbs.h
@@ -56,11 +56,13 @@ void PBSClearTrack(TileIndex tile, Track track);
* @param track The track to unreserve, valid values 0-5.
*/
-void PBSClearPath(TileIndex tile, Trackdir trackdir);
+void PBSClearPath(TileIndex tile, Trackdir trackdir, TileIndex end_tile, Trackdir end_trackdir);
/**<
* Follows a planned(reserved) path, and unreserves the tracks.
* @param tile The tile on which the path starts
* @param trackdir The trackdirection in which the path starts
+ * @param end_tile The tile on which the path ends
+ * @param end_trackdir The trackdirection in which the path ends
*/
bool PBSIsPbsSignal(TileIndex tile, Trackdir trackdir);
diff --git a/train_cmd.c b/train_cmd.c
index e14087b71..5fe2b0a6d 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -1321,13 +1321,15 @@ static void ReverseTrainDirection(Vehicle *v)
int l = 0, r = -1;
Vehicle *u;
TileIndex tile;
- byte trackdir;
+ Trackdir trackdir;
+ TileIndex pbs_end_tile = v->u.rail.pbs_end_tile; // these may be changed, and we may need
+ Trackdir pbs_end_trackdir = v->u.rail.pbs_end_trackdir; // the old values, so cache them
u = GetLastVehicleInChain(v);
tile = GetVehicleTileOutOfTunnel(u, false);
trackdir = ReverseTrackdir(GetVehicleTrackdir(u));
- if (PBSTileReserved(tile) & (1 << (trackdir&7))) {
+ if (PBSTileReserved(tile) & (1 << TrackdirToTrack(trackdir))) {
NPFFindStationOrTileData fstd;
NPFFoundTargetData ftd;
@@ -1351,13 +1353,15 @@ static void ReverseTrainDirection(Vehicle *v)
return;
}
}
+
+ v->u.rail.pbs_end_tile = ftd.node.tile;
+ v->u.rail.pbs_end_trackdir = ftd.node.direction;
}
tile = GetVehicleTileOutOfTunnel(v, false);
trackdir = GetVehicleTrackdir(v);
if (v->u.rail.pbs_status == PBS_STAT_HAS_PATH) {
- byte trackdir = GetVehicleTrackdir(v);
TileIndex tile = AddTileIndexDiffCWrap(v->tile, TileIndexDiffCByDir(TrackdirToExitdir(trackdir)));
uint32 ts;
assert(tile != INVALID_TILE);
@@ -1365,10 +1369,10 @@ static void ReverseTrainDirection(Vehicle *v)
ts &= TrackdirReachesTrackdirs(trackdir);
assert(ts != 0 && KillFirstBit2x64(ts) == 0);
trackdir = FindFirstBit2x64(ts);
- PBSClearPath(tile, trackdir);
+ PBSClearPath(tile, trackdir, pbs_end_tile, pbs_end_trackdir);
v->u.rail.pbs_status = PBS_STAT_NONE;
- } else if (PBSTileReserved(tile) & (1 << (trackdir&7))) {
- PBSClearPath(tile, trackdir);
+ } else if (PBSTileReserved(tile) & (1 << TrackdirToTrack(trackdir))) {
+ PBSClearPath(tile, trackdir, pbs_end_tile, pbs_end_trackdir);
if (v->u.rail.track != 0x40)
PBSReserveTrack(tile, trackdir & 7);
};
@@ -1838,8 +1842,11 @@ static bool CheckTrainStayInDepot(Vehicle *v)
if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) {
if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED))
return true;
- else
+ else {
+ v->u.rail.pbs_end_tile = ftd.node.tile;
+ v->u.rail.pbs_end_trackdir = ftd.node.direction;
goto green;
+ }
}
}
@@ -2007,11 +2014,14 @@ static byte ChooseTrainTrack(Vehicle *v, TileIndex tile, int enterdir, TrackdirB
if (pbs_tracks || (v->u.rail.pbs_status == PBS_STAT_NEED_PATH)) {
DEBUG(pbs, 2) ("pbs: (%i) choosefromblock, tile_org:%x tile_dst:%x trackdir:%i pbs_tracks:%i",v->unitnumber, tile,tile - TileOffsByDir(enterdir), trackdir, pbs_tracks);
// clear the currently planned path
- if (v->u.rail.pbs_status != PBS_STAT_NEED_PATH) PBSClearPath(tile, FindFirstBit2x64(pbs_tracks));
+ if (v->u.rail.pbs_status != PBS_STAT_NEED_PATH) PBSClearPath(tile, FindFirstBit2x64(pbs_tracks), v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir);
// try to find a route to a green exit signal
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_ANY);
+ v->u.rail.pbs_end_tile = ftd.node.tile;
+ v->u.rail.pbs_end_trackdir = ftd.node.direction;
+
} else
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_NONE);
@@ -2779,6 +2789,8 @@ static void TrainController(Vehicle *v)
if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED))
goto red_light;
else {
+ v->u.rail.pbs_end_tile = ftd.node.tile;
+ v->u.rail.pbs_end_trackdir = ftd.node.direction;
goto green_light;
}
@@ -2955,8 +2967,8 @@ static void DeleteLastWagon(Vehicle *v)
// clear up reserved pbs tracks
if (PBSTileReserved(v->tile) & v->u.rail.track) {
if (v == u) {
- PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track));
- PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track) + 8);
+ PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track), v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir);
+ PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track) + 8, v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir);
};
if (v->tile != u->tile) {
PBSClearTrack(v->tile, FIND_FIRST_BIT(v->u.rail.track));
@@ -3206,6 +3218,8 @@ static bool TrainCheckIfLineEnds(Vehicle *v)
if (ftd.best_trackdir != 0xFF && NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) {
if (!(NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED))) {
v->u.rail.pbs_status = PBS_STAT_HAS_PATH;
+ v->u.rail.pbs_end_tile = ftd.node.tile;
+ v->u.rail.pbs_end_trackdir = ftd.node.direction;
return true;
}
};
diff --git a/vehicle.c b/vehicle.c
index 6eae858ed..9d4580c67 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -1947,8 +1947,10 @@ static const SaveLoad _train_desc[] = {
SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,days_since_order_progr), SLE_UINT16, 2, 255),
SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,pbs_status), SLE_UINT8, 2, 255),
- // reserve extra space in savegame here. (currently 12 bytes)
- SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 12, 2, 255),
+ SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,pbs_end_tile), SLE_UINT32, 2, 255),
+ SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRail,pbs_end_trackdir), SLE_UINT8, 2, 255),
+ // reserve extra space in savegame here. (currently 7 bytes)
+ SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 7, 2, 255),
SLE_END()
};
diff --git a/vehicle.h b/vehicle.h
index a413426af..1391bdc3e 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -70,6 +70,8 @@ typedef struct VehicleRail {
byte flags;
byte pbs_status;
+ TileIndex pbs_end_tile;
+ Trackdir pbs_end_trackdir;
} VehicleRail;
enum {