yapf/yapf_costrail.hpp
branchcustombridgeheads
changeset 5626 1811beeb472f
parent 5623 ef2a8a524a95
child 5627 f5c656cf0a0e
--- a/yapf/yapf_costrail.hpp	Mon Jan 01 18:27:08 2007 +0000
+++ b/yapf/yapf_costrail.hpp	Mon Jan 01 19:44:02 2007 +0000
@@ -195,38 +195,57 @@
 		Trackdir trackdir = n.m_key.m_td;
 		TileType tile_type = GetTileType(tile);
 
+		DEBUG(yapf, 3, "PfCalcCost(Node:tile=%04X td=%s; Parent:tile=%04X td=%s)", tile, GetTrackdirName(trackdir), prev_tile, GetTrackdirName(prev_trackdir));
+
 		RailType rail_type = GetTileRailType(tile, trackdir);
 
 		// detect exit from bridge wormhole
 		if (IsBridgeTile(tile) && TrackdirToExitdir(ReverseTrackdir(trackdir)) == GetBridgeRampDirection(tile)) {
 			// we are jumping over bridge (possible now with custom bridge heads) we must add the cost of skipped tiles
-			segment_cost += (DistanceManhattan(prev_tile, tile) - 1) * YAPF_TILE_LENGTH;
+			int skipped_tiles = DistanceManhattan(prev_tile, tile) - 1;
+			if (skipped_tiles > 0) {
+				segment_cost += skipped_tiles * YAPF_TILE_LENGTH;
+				DEBUG(yapf, 6, "    Cost: skipped=%d", skipped_tiles * YAPF_TILE_LENGTH);
+				intermediate_trackdir = DiagdirToDiagTrackdir(ReverseDiagDir(GetBridgeRampDirection(tile)));
+			}
 		}
 
 		bool target_seen = Yapf().PfDetectDestination(tile, trackdir);
 
 		while (true) {
-			segment_cost += Yapf().OneTileCost(tile, trackdir);
-			segment_cost += Yapf().CurveCost(prev_trackdir, trackdir);
-			segment_cost += Yapf().SlopeCost(tile, trackdir);
-			segment_cost += Yapf().SignalCost(n, tile, trackdir);
+			int tile_cost = Yapf().OneTileCost(tile, trackdir);
+			int curve_cost;
+			if (intermediate_trackdir == INVALID_TRACKDIR) {
+				curve_cost = Yapf().CurveCost(prev_trackdir, trackdir);
+			} else {
+				curve_cost = Yapf().CurveCost(prev_trackdir, intermediate_trackdir) + Yapf().CurveCost(intermediate_trackdir, trackdir);
+				intermediate_trackdir = INVALID_TRACKDIR;
+			}
+			int slope_cost = Yapf().SlopeCost(tile, trackdir);
+			int signal_cost = Yapf().SignalCost(n, tile, trackdir);
+			DEBUG(yapf, 6, "    Cost: tile=%d, curve=%d, slope=%d, signal=%d", tile_cost, curve_cost, slope_cost, signal_cost);
+			segment_cost += tile_cost + curve_cost + slope_cost + signal_cost;
 			if (n.m_segment->flags_u.flags_s.m_end_of_line) {
+				DEBUG(yapf, 4, "  end: EOL (signal)");
 				break;
 			}
 
 			// finish if we have reached the destination
 			if (target_seen) {
+				DEBUG(yapf, 4, "  end: target_seen");
 				break;
 			}
 
 			// finish on first station tile - segment should end here to avoid target skipping
 			// when cached segments are used
 			if (tile_type == MP_STATION && prev_tile_type != MP_STATION) {
+				DEBUG(yapf, 4, "  end: first station tile");
 				break;
 			}
 
 			// finish also on waypoint - same workaround as for first station tile
 			if (tile_type == MP_RAILWAY && IsRailWaypoint(tile)) {
+				DEBUG(yapf, 4, "  end: waypoint");
 				break;
 			}
 
@@ -235,11 +254,15 @@
 			if (!F.Follow(tile, trackdir)) {
 				// we can't continue?
 				// n.m_segment->flags_u.flags_s.m_end_of_line = true;
+				DEBUG(yapf, 4, "  end: can't foolow (dead end?)");
 				break;
 			}
+			if (F.m_is_bridge && F.m_tiles_skipped > 0) intermediate_trackdir = F.m_intermediate_trackdir;
+			DEBUG(yapf, 4, " next: tile=%04X td=%s", F.m_new_tile, GetTrackdirBitsName(F.m_new_td_bits).Data());
 
 			// if there are more trackdirs available & reachable, we are at the end of segment
 			if (KillFirstBit2x64(F.m_new_td_bits) != 0) {
+				DEBUG(yapf, 4, "  end: choice");
 				break;
 			}
 
@@ -248,18 +271,23 @@
 			{
 				// end segment if train is about to enter simple loop with no junctions
 				// so next time it should stop on the next if
-				if (segment_cost > s_max_segment_cost && IsTileType(F.m_new_tile, MP_RAILWAY))
+				if (segment_cost > s_max_segment_cost && IsTileType(F.m_new_tile, MP_RAILWAY)) {
+					DEBUG(yapf, 4, "  end: loop fuse");
 					break;
+				}
 
 				// stop if train is on simple loop with no junctions
-				if (F.m_new_tile == n.m_key.m_tile && new_td == n.m_key.m_td)
+				if (F.m_new_tile == n.m_key.m_tile && new_td == n.m_key.m_td) {
+					DEBUG(yapf, 4, "  end: loop detected");
 					return false;
+				}
 			}
 
-			// if tail type changes, finish segment (cached segment can't contain more rail types)
+			// if rail type changes, finish segment (cached segment can't contain more rail types)
 			{
 				RailType new_rail_type = GetTileRailType(F.m_new_tile, (Trackdir)FindFirstBit2x64(F.m_new_td_bits));
 				if (new_rail_type != rail_type) {
+					DEBUG(yapf, 4, "  end: rail type changes");
 					break;
 				}
 				rail_type = new_rail_type;
@@ -278,12 +306,15 @@
 
 			// reversing in depot penalty
 			if (tile == prev_tile) {
-				segment_cost += Yapf().PfGetSettings().rail_depot_reverse_penalty;
+				int reverse_in_depot_cost = Yapf().PfGetSettings().rail_depot_reverse_penalty;
+				segment_cost += reverse_in_depot_cost;
+				DEBUG(yapf, 4, "  end: reversing in depot (cost=%d)", reverse_in_depot_cost);
 				break;
 			}
 
 			// if we skipped some tunnel tiles, add their cost
 			segment_cost += YAPF_TILE_LENGTH * F.m_tiles_skipped;
+			DEBUG(yapf, 6, "    Cost: wormhole=%d", YAPF_TILE_LENGTH * F.m_tiles_skipped);
 
 			// add penalty for skipped station tiles
 			if (F.m_is_station)
@@ -291,10 +322,14 @@
 				if (target_seen) {
 					// it is our destination station
 					uint platform_length = F.m_tiles_skipped + 1;
-					segment_cost += PlatformLengthPenalty(platform_length);
+					int platform_length_cost = PlatformLengthPenalty(platform_length);
+					segment_cost += platform_length_cost;
+					DEBUG(yapf, 6, "    Cost: platform=%d", platform_length_cost);
 				} else {
 					// station is not our destination station, apply penalty for skipped platform tiles
-					segment_cost += Yapf().PfGetSettings().rail_station_penalty * F.m_tiles_skipped;
+					int station_cost = Yapf().PfGetSettings().rail_station_penalty * F.m_tiles_skipped;
+					segment_cost += station_cost;
+					DEBUG(yapf, 6, "    Cost: station=%d", station_cost);
 				}
 			}
 
@@ -308,6 +343,7 @@
 
 			// finish if we already exceeded the maximum cost
 			if (m_max_cost > 0 && (parent_cost + first_tile_cost + segment_cost) > m_max_cost) {
+				DEBUG(yapf, 4, "  abort: maximum cost reached");
 				return false;
 			}
 
@@ -315,10 +351,12 @@
 				// we just have done first tile
 				first_tile_cost = segment_cost;
 				segment_cost = 0;
+				DEBUG(yapf, 5, "    TotalCost: first_tile=%d", first_tile_cost);
 
 				// look if we can reuse existing (cached) segment cost
 				if (n.m_segment->m_cost >= 0) {
 					// reuse the cached segment cost
+					DEBUG(yapf, 4, "  end: reusing the cached segment cost");
 					break;
 				}
 			}
@@ -331,15 +369,18 @@
 			// we have just finished first tile
 			first_tile_cost = segment_cost;
 			segment_cost = 0;
+			DEBUG(yapf, 5, "    TotalCost: first_tile=%d", first_tile_cost);
 		}
 
 		// do we have cached segment cost?
 		if (n.m_segment->m_cost >= 0) {
 			// reuse the cached segment cost
 			segment_cost = n.m_segment->m_cost;
+			DEBUG(yapf, 5, "    TotalCost: cached_segment=%d", segment_cost);
 		} else {
 			// save segment cost
 			n.m_segment->m_cost = segment_cost;
+			DEBUG(yapf, 5, "    TotalCost: segment=%d", segment_cost);
 
 			// save end of segment back to the node
 			n.SetLastTileTrackdir(tile, trackdir);
@@ -358,10 +399,12 @@
 				}
 			}
 		}
+		DEBUG(yapf, 5, "    TotalCost: extra=%d", extra_cost);
 
 		// total node cost
 		n.m_cost = parent_cost + first_tile_cost + segment_cost + extra_cost;
-
+		DEBUG(yapf, 3, "  leaving: last_tile=%04X, last_td=%s, cost=%d", n.m_segment->m_last_tile, GetTrackdirName(n.m_segment->m_last_td), n.m_cost);
+		DEBUG(yapf, 3, " returning %s", n.m_segment->flags_u.flags_s.m_end_of_line ? "false" : "true");
 		return !n.m_segment->flags_u.flags_s.m_end_of_line;
 	}