Changeset - r9816:2ec7cf9ecbc4
[Not reviewed]
master
0 1 0
rubidium - 16 years ago 2008-08-02 22:55:23
rubidium@openttd.org
(svn r13958) -Add [YAPP]: Implement look-ahead for trains so they extend their reservation before reaching the end. (michi_cc)
1 file changed with 59 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/train_cmd.cpp
Show inline comments
 
@@ -2327,6 +2327,44 @@ void Train::PlayLeaveStationSound() cons
 
	SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
 
}
 

	
 
/** Check if the train is on the last reserved tile and try to extend the path then. */
 
static void CheckNextTrainTile(Vehicle *v)
 
{
 
	/* Don't do any look-ahead if path_backoff_interval is 255. */
 
	if (_settings_game.pf.path_backoff_interval == 255) return;
 

	
 
	/* Exit if we reached our destination or are inside a depot. */
 
	if ((v->tile == v->dest_tile && !v->current_order.IsType(OT_GOTO_STATION)) || v->u.rail.track & TRACK_BIT_DEPOT) return;
 
	/* Exit if we are on a station tile and are going to stop. */
 
	if (IsRailwayStationTile(v->tile) && v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile))) return;
 
	/* Exit if the current order doesn't have a destination, but the train has orders. */
 
	if ((v->current_order.IsType(OT_NOTHING) || v->current_order.IsType(OT_LEAVESTATION)) && v->num_orders > 0) return;
 

	
 
	Trackdir td = GetVehicleTrackdir(v);
 

	
 
	/* On a tile with a red non-pbs signal, don't look ahead. */
 
	if (IsTileType(v->tile, MP_RAILWAY) && HasSignalOnTrackdir(v->tile, td) &&
 
			!IsPbsSignal(GetSignalType(v->tile, TrackdirToTrack(td))) &&
 
			GetSignalStateByTrackdir(v->tile, td) == SIGNAL_STATE_RED) return;
 

	
 
	CFollowTrackRail ft(v);
 
	if (!ft.Follow(v->tile, td)) return;
 

	
 
	if (!HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits))) {
 
		/* Next tile is not reserved. */
 
		if (KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
 
			if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) {
 
				/* If the next tile is a PBS signal, try to make a reservation. */
 
				TrackBits tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
 
				if (_settings_game.pf.pathfinder_for_trains != VPF_NTP && _settings_game.pf.forbid_90_deg) {
 
					tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.m_old_td));
 
				}
 
				ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false);
 
			}
 
		}
 
	}
 
}
 

	
 
static bool CheckTrainStayInDepot(Vehicle *v)
 
{
 
	/* bail out if not all wagons are in the same depot or not in a depot at all */
 
@@ -3503,8 +3541,6 @@ static void TrainController(Vehicle *v, 
 
					goto invalid_rail;
 
				}
 

	
 
				if (IsFrontEngine(v)) v->load_unload_time_rem = 0;
 

	
 
				if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
 
					Track track = FindFirstTrack(chosen_track);
 
					Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
 
@@ -3533,6 +3569,13 @@ static void TrainController(Vehicle *v, 
 
				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
 

	
 
				v->direction = chosen_dir;
 

	
 
				if (IsFrontEngine(v)) {
 
					v->load_unload_time_rem = 0;
 

	
 
					/* Always try to extend the reservation when entering a tile. */
 
					CheckNextTrainTile(v);
 
				}
 
			}
 
		} else {
 
			/* In a tunnel or on a bridge
 
@@ -3543,7 +3586,10 @@ static void TrainController(Vehicle *v, 
 
					min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed);
 
			}
 

	
 
			if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
 
			if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
 
				/* Perform look-ahead on tunnel exit. */
 
				if (IsFrontEngine(v)) CheckNextTrainTile(v);
 
			} else {
 
				v->x_pos = gp.x;
 
				v->y_pos = gp.y;
 
				VehiclePositionChanged(v);
 
@@ -3577,6 +3623,9 @@ static void TrainController(Vehicle *v, 
 
				if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile);
 
			}
 
		}
 

	
 
		/* Do not check on every tick to save some computing time. */
 
		if (IsFrontEngine(v) && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v);
 
	}
 
	return;
 

	
 
@@ -3930,6 +3979,7 @@ static void TrainLocoHandler(Vehicle *v,
 
	/* exit if train is stopped */
 
	if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return;
 

	
 
	bool valid_order = v->current_order.IsValid() && v->current_order.GetType() != OT_CONDITIONAL;
 
	if (ProcessOrders(v) && CheckReverseTrain(v)) {
 
		v->load_unload_time_rem = 0;
 
		v->cur_speed = 0;
 
@@ -3946,6 +3996,11 @@ static void TrainLocoHandler(Vehicle *v,
 

	
 
	if (!mode) HandleLocomotiveSmokeCloud(v);
 

	
 
	/* We had no order but have an order now, do look ahead. */
 
	if (!valid_order && v->current_order.IsValid()) {
 
		CheckNextTrainTile(v);
 
	}
 

	
 
	/* Handle stuck trains. */
 
	if (!mode && HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) {
 
		++v->load_unload_time_rem;
 
@@ -3953,7 +4008,7 @@ static void TrainLocoHandler(Vehicle *v,
 
		/* Should we try reversing this tick if still stuck? */
 
		bool turn_around = v->load_unload_time_rem % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.wait_for_pbs_path < 255;
 

	
 
		if (!turn_around && v->u.rail.force_proceed == 0) return;
 
		if (!turn_around && v->load_unload_time_rem % _settings_game.pf.path_backoff_interval != 0 && v->u.rail.force_proceed == 0) return;
 
		if (!TryPathReserve(v)) {
 
			/* Still stuck. */
 
			if (turn_around) ReverseTrainDirection(v);
0 comments (0 inline, 0 general)