(svn r14482) -Codechange: Use a class for saving the current train order when extending the reserved path beyond the current destination during pathfinding.
authormichi_cc
Sat, 18 Oct 2008 13:13:27 +0000
changeset 10251 1f6cc1c5c8b0
parent 10250 da7d3c53747d
child 10252 3ae02dea2fda
(svn r14482) -Codechange: Use a class for saving the current train order when extending the reserved path beyond the current destination during pathfinding.
The class' destructor will make sure that the order is restored on function exit in all cases.
src/train_cmd.cpp
--- a/src/train_cmd.cpp	Fri Oct 17 17:47:42 2008 +0000
+++ b/src/train_cmd.cpp	Sat Oct 18 13:13:27 2008 +0000
@@ -2809,49 +2809,66 @@
 	}
 }
 
-/**
- * Query the next order after a certain order index.
- *
- * @param v The vehicle
- * @param order_index [in/out] Index of the current order, returns index of the chosen order
- * @return Pointer to the order or NULL if the order chain was completely followed
- *          without finding a suitable order.
- */
-static const Order* GetNextTrainOrder(const Vehicle *v, VehicleOrderID *order_index)
+/** This class will save the current order of a vehicle and restore it on destruction. */
+class VehicleOrderSaver
 {
-	++(*order_index);
-
-	do {
-		/* Wrap around. */
-		if (*order_index >= v->num_orders) *order_index = 0;
-
-		Order *order = GetVehicleOrder(v, *order_index);
-		assert(order != NULL);
-
-		switch (order->GetType()) {
-			case OT_GOTO_DEPOT:
-				/* Skip service in depot orders when the train doesn't need service. */
-				if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) break;
-			case OT_GOTO_STATION:
-			case OT_GOTO_WAYPOINT:
-				return order;
-			case OT_CONDITIONAL: {
-				VehicleOrderID next = ProcessConditionalOrder(order, v);
-				if (next != INVALID_VEH_ORDER_ID) {
-					*order_index = next;
-					continue;
+private:
+	Vehicle        *v;
+	Order          old_order;
+	TileIndex      old_dest_tile;
+	VehicleOrderID index;
+
+public:
+	VehicleOrderSaver(Vehicle *_v) : v(_v), old_order(_v->current_order), old_dest_tile(_v->dest_tile), index(_v->cur_order_index)
+	{
+	}
+
+	~VehicleOrderSaver()
+	{
+		this->v->current_order = this->old_order;
+		this->v->dest_tile = this->old_dest_tile;
+	}
+
+	/**
+	 * Set the current vehicle order to the next order in the order list.
+	 * @return True if a suitable next order could be found.
+	 */
+	bool SwitchToNextOrder()
+	{
+		++this->index;
+
+		do {
+			/* Wrap around. */
+			if (this->index >= this->v->num_orders) this->index = 0;
+
+			Order *order = GetVehicleOrder(this->v, this->index);
+			assert(order != NULL);
+
+			switch (order->GetType()) {
+				case OT_GOTO_DEPOT:
+					/* Skip service in depot orders when the train doesn't need service. */
+					if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !this->v->NeedsServicing()) break;
+				case OT_GOTO_STATION:
+				case OT_GOTO_WAYPOINT:
+					this->v->current_order = *order;
+					UpdateOrderDest(this->v, order);
+					return true;
+				case OT_CONDITIONAL: {
+					VehicleOrderID next = ProcessConditionalOrder(order, this->v);
+					if (next != INVALID_VEH_ORDER_ID) {
+						this->index = next;
+						continue;
+					}
+					break;
 				}
-				break;
+				default:
+					break;
 			}
-			default:
-				break;
-		}
-
-		++(*order_index);
-	} while (*order_index != v->cur_order_index);
-
-	return NULL;
-}
+		} while (++this->index != this->v->cur_order_index);
+
+		return false;
+	}
+};
 
 /* choose a track */
 static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
@@ -2964,10 +2981,9 @@
 
 	if (got_reservation != NULL) *got_reservation = true;
 
+	/* Save the current train order. The destructor will restore the old order on function exit. */
+	VehicleOrderSaver orders(v);
 	/* Reservation target found and free, check if it is safe. */
-	Order          cur_order = v->current_order;
-	TileIndex      cur_dest_tile = v->dest_tile;
-	VehicleOrderID order_index = v->cur_order_index;
 	while (!IsSafeWaitingPosition(v, res_dest.tile, res_dest.trackdir, true, _settings_game.pf.forbid_90_deg)) {
 		/* Extend reservation until we have found a safe position. */
 		DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
@@ -2978,10 +2994,7 @@
 		}
 
 		/* Get next order with destination. */
-		const Order *order = GetNextTrainOrder(v, &order_index);
-		if (order != NULL) {
-			v->current_order = *order;
-			UpdateOrderDest(v, order);
+		if (orders.SwitchToNextOrder()) {
 			PBSTileInfo cur_dest;
 			DoTrainPathfind(v, next_tile, exitdir, reachable, NULL, true, &cur_dest);
 			if (cur_dest.tile != INVALID_TILE) {
@@ -3004,8 +3017,6 @@
 		}
 		break;
 	}
-	v->current_order = cur_order;
-	v->dest_tile = cur_dest_tile;
 
 	TryReserveRailTrack(v->tile, TrackdirToTrack(GetVehicleTrackdir(v)));