From 552aa1b4dc172a9d769e3c94ff40c99743f428b0 Mon Sep 17 00:00:00 2001 From: hackykid Date: Sun, 17 Jul 2005 20:09:02 +0000 Subject: [PATCH] (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. --- npf.c | 24 ++++++++++++++++-------- pbs.c | 14 +++++++------- pbs.h | 4 +++- train_cmd.c | 34 ++++++++++++++++++++++++---------- vehicle.c | 6 ++++-- vehicle.h | 2 ++ 6 files changed, 56 insertions(+), 28 deletions(-) diff --git a/npf.c b/npf.c index 81601cb979..a1f5e52df1 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) ); + PBSReserveTrack(curr->node.tile, TrackdirToTrack(curr->node.direction) ); - /* 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); + /* 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 493d60690a..53711a75b6 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 398bd73d9e..013802ee6a 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 e14087b719..5fe2b0a6d8 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 6eae858ed7..9d4580c679 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 a413426afe..1391bdc3ec 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 {