(svn r9838) -Fix: make "improved loading" a proper improved loading instead of loading one (semi-)random vehicle at a time:
authorrubidium
Mon, 14 May 2007 20:12:32 +0000
changeset 7114 665294e21ae8
parent 7113 4b0fd37ee609
child 7115 ef36e40739c9
(svn r9838) -Fix: make "improved loading" a proper improved loading instead of loading one (semi-)random vehicle at a time:
- Now it is really FIFO.
- When there is enough cargo to fill the first vehicle in the queue, the next vehicle in the queue start loading (and the next when ....).
src/economy.cpp
--- a/src/economy.cpp	Mon May 14 17:37:34 2007 +0000
+++ b/src/economy.cpp	Mon May 14 20:12:32 2007 +0000
@@ -1323,61 +1323,6 @@
 	return profit;
 }
 
-/*
- * Returns true if Vehicle v should wait loading because other vehicle is
- * already loading the same cargo type
- * v = vehicle to load, u = GetFirstInChain(v)
- */
-static bool LoadWait(const Vehicle* v, const Vehicle* u)
-{
-	const Vehicle *w;
-	bool has_any_cargo = false;
-
-	if (!(u->current_order.flags & OF_FULL_LOAD)) return false;
-
-	for (w = u; w != NULL; w = w->next) {
-		if (w->cargo_count != 0) {
-			if (v->cargo_type == w->cargo_type &&
-					u->last_station_visited == w->cargo_source) {
-				return false;
-			}
-			has_any_cargo = true;
-		}
-	}
-
-	const Station *st = GetStation(u->last_station_visited);
-	std::list<Vehicle *>::const_iterator iter;
-	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
-		const Vehicle *x = *iter;
-		if (!(x->vehstatus & (VS_STOPPED | VS_CRASHED)) && u != x) {
-			bool other_has_any_cargo = false;
-			bool has_space_for_same_type = false;
-			bool other_has_same_type = false;
-
-			for (w = x; w != NULL; w = w->next) {
-				if (w->cargo_count < w->cargo_cap && v->cargo_type == w->cargo_type) {
-					has_space_for_same_type = true;
-				}
-
-				if (w->cargo_count != 0) {
-					if (v->cargo_type == w->cargo_type &&
-							u->last_station_visited == w->cargo_source) {
-						other_has_same_type = true;
-					}
-					other_has_any_cargo = true;
-				}
-			}
-
-			if (has_space_for_same_type) {
-				if (other_has_same_type) return true;
-				if (other_has_any_cargo && !has_any_cargo) return true;
-			}
-		}
-	}
-
-	return false;
-}
-
 /**
  * Performs the vehicle payment _and_ marks the vehicle to be unloaded.
  * @param front_v the vehicle to be unloaded
@@ -1481,13 +1426,25 @@
 /**
  * Loads/unload the vehicle if possible.
  * @param v the vehicle to be (un)loaded
+ * @param cargo_left the amount of each cargo type that is
+ *                   virtually left on the platform to be
+ *                   picked up by another vehicle when all
+ *                   previous vehicles have loaded.
  */
-static void LoadUnloadVehicle(Vehicle *v)
+static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
 {
 	assert(v->current_order.type == OT_LOADING);
 
 	/* We have not waited enough time till the next round of loading/unloading */
-	if (--v->load_unload_time_rem != 0) return;
+	if (--v->load_unload_time_rem != 0) {
+		if (_patches.improved_load && HASBIT(v->current_order.flags, OFB_FULL_LOAD)) {
+			/* 'Reserve' this cargo for this vehicle, because we were first. */
+			for (; v != NULL; v = v->next) {
+				if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+			}
+		}
+		return;
+	}
 
 	int unloading_time = 0;
 	Vehicle *u = v;
@@ -1598,15 +1555,23 @@
 		if (count != 0 &&
 				(cap = v->cargo_cap - v->cargo_count) != 0) {
 
-			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
-
 			/* Skip loading this vehicle if another train/vehicle is already handling
 			 * the same cargo type at this station */
-			if (_patches.improved_load && (u->current_order.flags & OF_FULL_LOAD) && LoadWait(v,u)) {
+			if (_patches.improved_load && cargo_left[v->cargo_type] < 0) {
 				SETBIT(cargo_not_full, v->cargo_type);
 				continue;
 			}
 
+			if (cap > count) cap = count;
+			if (_patches.gradual_loading) cap = min(cap, load_amount);
+			if (_patches.improved_load) {
+				/* Don't load stuff that is already 'reserved' for other vehicles */
+				cap = min(cargo_left[v->cargo_type], cap);
+				cargo_left[v->cargo_type] -= cap;
+			}
+
+			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
+
 			/* TODO: Regarding this, when we do gradual loading, we
 			 * should first unload all vehicles and then start
 			 * loading them. Since this will cause
@@ -1617,9 +1582,6 @@
 			completely_empty = false;
 			anything_loaded = true;
 
-			if (cap > count) cap = count;
-			if (_patches.gradual_loading) cap = min(cap, load_amount);
-
 			/* cargoshare is proportioned by the amount due to unload
 			 * Otherwise, with gradual loading, 100% of credits would be taken immediately,
 			 * even if the cargo volume represents a tiny percent of the whole.
@@ -1652,6 +1614,17 @@
 		}
 	}
 
+	/* We update these variables here, so gradual loading still fills
+	 * all wagons at the same time instead of using the same 'improved'
+	 * loading algorithm for the wagons (only fill wagon when there is
+	 * enough to fill the previous wagons) */
+	if (_patches.improved_load && HASBIT(u->current_order.flags, OFB_FULL_LOAD)) {
+		/* Update left cargo */
+		for (v = u; v != NULL; v = v->next) {
+			if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+		}
+	}
+
 	v = u;
 
 	v->cargo_feeder_share += total_cargo_feeder_share;
@@ -1716,10 +1689,14 @@
  */
 void LoadUnloadStation(Station *st)
 {
+	int cargo_left[NUM_CARGO];
+
+	for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = GB(st->goods[i].waiting_acceptance, 0, 12);
+
 	std::list<Vehicle *>::iterator iter;
 	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
 		Vehicle *v = *iter;
-		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v);
+		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
 	}
 }