summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-12-07 08:47:10 +0000
committerrubidium <rubidium@openttd.org>2009-12-07 08:47:10 +0000
commitd6e73ea1ce9db96cb76495c8a1edce199790c552 (patch)
tree570799367f7a580d5a67a14ce536d33f7aec75ee
parentad6d8c1f4634d8dabdff094110a263b53e223436 (diff)
downloadopenttd-d6e73ea1ce9db96cb76495c8a1edce199790c552.tar.xz
(svn r18421) -Fix [FS#3244]: pathfinders wouldn't consider the 'other' reachable waypoint tile if the closest one is free but there is no safe waiting point directly after it. Now check for a free safe waiting point beyond the waypoint unless there are junctions before the first safe waiting point.
-rw-r--r--src/pathfinder/npf/npf.cpp33
-rw-r--r--src/pathfinder/yapf/yapf_costrail.hpp34
2 files changed, 64 insertions, 3 deletions
diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp
index f6841796a..1fe5fe07f 100644
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -24,6 +24,7 @@
#include "../../roadstop_base.h"
#include "../pathfinder_func.h"
#include "../pathfinder_type.h"
+#include "../follow_track.hpp"
#include "aystar.h"
enum {
@@ -419,6 +420,38 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
* this penalty exactly once, on its end tile (if it's a station) and it
* will therefore not make a difference. */
cost = NPF_TILE_LENGTH + _settings_game.pf.npf.npf_rail_station_penalty;
+
+ if (IsRailWaypoint(tile)) {
+ NPFFindStationOrTileData *fstd = (NPFFindStationOrTileData*)as->user_target;
+ if (fstd->v->current_order.IsType(OT_GOTO_WAYPOINT) && GetStationIndex(tile) == fstd->v->current_order.GetDestination()) {
+ /* This waypoint is our destination; maybe this isn't an unreserved
+ * one, so check that and if so see that as the last signal being
+ * red. This way waypoints near stations should work better. */
+ const Train *train = Train::From(fstd->v);
+ CFollowTrackRail ft(train);
+ TileIndex t = tile;
+ Trackdir td = trackdir;
+ while (ft.Follow(t, td)) {
+ assert(t != ft.m_new_tile);
+ t = ft.m_new_tile;
+ if (KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
+ /* We encountered a junction; it's going to be too complex to
+ * handle this perfectly, so just bail out. There is no simple
+ * free path, so try the other possibilities. */
+ td = INVALID_TRACKDIR;
+ break;
+ }
+ td = RemoveFirstTrackdir(&ft.m_new_td_bits);
+ /* If this is a safe waiting position we're done searching for it */
+ if (IsSafeWaitingPosition(train, t, td, true, _settings_game.pf.forbid_90_deg)) break;
+ }
+ if (td == INVALID_TRACKDIR ||
+ !IsSafeWaitingPosition(train, t, td, true, _settings_game.pf.forbid_90_deg) ||
+ !IsWaitingPositionFree(train, t, td, _settings_game.pf.forbid_90_deg)) {
+ cost += _settings_game.pf.npf.npf_rail_lastred_penalty;
+ }
+ }
+ }
break;
default:
diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp
index 959431520..cfc1bba82 100644
--- a/src/pathfinder/yapf/yapf_costrail.hpp
+++ b/src/pathfinder/yapf/yapf_costrail.hpp
@@ -404,6 +404,37 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* We will end in this pass (depot is possible target) */
end_segment_reason |= ESRB_DEPOT;
+ } else if (cur.tile_type == MP_STATION && IsRailWaypoint(cur.tile)) {
+ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && GetStationIndex(cur.tile) == v->current_order.GetDestination()) {
+ /* This waypoint is our destination; maybe this isn't an unreserved
+ * one, so check that and if so see that as the last signal being
+ * red. This way waypoints near stations should work better. */
+ CFollowTrackRail ft(v);
+ TileIndex t = cur.tile;
+ Trackdir td = cur.td;
+ while (ft.Follow(t, td)) {
+ assert(t != ft.m_new_tile);
+ t = ft.m_new_tile;
+ if (KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
+ /* We encountered a junction; it's going to be too complex to
+ * handle this perfectly, so just bail out. There is no simple
+ * free path, so try the other possibilities. */
+ td = INVALID_TRACKDIR;
+ break;
+ }
+ td = RemoveFirstTrackdir(&ft.m_new_td_bits);
+ /* If this is a safe waiting position we're done searching for it */
+ if (IsSafeWaitingPosition(v, t, td, true, _settings_game.pf.forbid_90_deg)) break;
+ }
+ if (td == INVALID_TRACKDIR ||
+ !IsSafeWaitingPosition(v, t, td, true, _settings_game.pf.forbid_90_deg) ||
+ !IsWaitingPositionFree(v, t, td, _settings_game.pf.forbid_90_deg)) {
+ extra_cost += Yapf().PfGetSettings().rail_lastred_exit_penalty;
+ }
+ }
+ /* Waypoint is also a good reason to finish. */
+ end_segment_reason |= ESRB_WAYPOINT;
+
} else if (tf->m_is_station) {
/* Station penalties. */
uint platform_length = tf->m_tiles_skipped + 1;
@@ -413,9 +444,6 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* We will end in this pass (station is possible target) */
end_segment_reason |= ESRB_STATION;
- } else if (cur.tile_type == MP_STATION && IsRailWaypoint(cur.tile)) {
- /* Waypoint is also a good reason to finish. */
- end_segment_reason |= ESRB_WAYPOINT;
} else if (TrackFollower::DoTrackMasking() && cur.tile_type == MP_RAILWAY) {
/* Searching for a safe tile? */
if (HasSignalOnTrackdir(cur.tile, cur.td) && !IsPbsSignal(GetSignalType(cur.tile, TrackdirToTrack(cur.td)))) {