changeset 18560:488cc0d0b505 draft

(svn r23405) -Codechange: Keep a matrix of cargos accepted by houses for each town (michi_cc).
author terkhen <terkhen@openttd.org>
date Sat, 03 Dec 2011 22:21:27 +0000
parents 820b3ec0b86d
children 05ffde57e1fe
files src/saveload/afterload.cpp src/saveload/town_sl.cpp src/town.h src/town_cmd.cpp
diffstat 4 files changed, 133 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -2700,6 +2700,19 @@
 	 * which is done by StartupEngines(). */
 	if (gcf_res != GLC_ALL_GOOD) StartupEngines();
 
+	if (IsSavegameVersionBefore(166)) {
+		/* Update cargo acceptance map of towns. */
+		for (TileIndex t = 0; t < map_size; t++) {
+			if (!IsTileType(t, MP_HOUSE)) continue;
+			Town::Get(GetTownIndex(t))->cargo_accepted.Add(t);
+		}
+
+		Town *town;
+		FOR_ALL_TOWNS(town) {
+			UpdateTownCargos(town);
+		}
+	}
+
 	/* Road stops is 'only' updating some caches */
 	AfterLoadRoadStops();
 	AfterLoadLabelMaps();
--- a/src/saveload/town_sl.cpp
+++ b/src/saveload/town_sl.cpp
@@ -97,6 +97,7 @@
 	/* Update the population and num_house dependant values */
 	FOR_ALL_TOWNS(town) {
 		UpdateTownRadius(town);
+		UpdateTownCargos(town);
 	}
 }
 
@@ -176,6 +177,8 @@
 
 	SLE_CONDLST(Town, psa_list,            REF_STORAGE,                161, SL_MAX_VERSION),
 
+	SLE_CONDVAR(Town, cargo_produced,       SLE_UINT32,                166, SL_MAX_VERSION),
+
 	/* reserve extra space in savegame here. (currently 30 bytes) */
 	SLE_CONDNULL(30, 2, SL_MAX_VERSION),
 
@@ -210,6 +213,19 @@
 	Load_NewGRFMapping(_house_mngr);
 }
 
+const SaveLoad *GetTileMatrixDesc()
+{
+	/* Here due to private member vars. */
+	static const SaveLoad _tilematrix_desc[] = {
+		SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
+		SLE_VAR(AcceptanceMatrix, area.w,    SLE_UINT16),
+		SLE_VAR(AcceptanceMatrix, area.h,    SLE_UINT16),
+		SLE_END()
+	};
+
+	return _tilematrix_desc;
+}
+
 static void RealSave_Town(Town *t)
 {
 	SlObject(t, _town_desc);
@@ -220,6 +236,14 @@
 	for (int i = TE_BEGIN; i < NUM_TE; i++) {
 		SlObject(&t->received[i], _town_received_desc);
 	}
+
+	if (IsSavegameVersionBefore(166)) return;
+
+	SlObject(&t->cargo_accepted, GetTileMatrixDesc());
+	if (t->cargo_accepted.area.w != 0) {
+		uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
+		SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
+	}
 }
 
 static void Save_TOWN()
@@ -250,6 +274,18 @@
 		if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST)) {
 			SlErrorCorrupt("Invalid town name generator");
 		}
+
+		if (IsSavegameVersionBefore(166)) continue;
+
+		SlObject(&t->cargo_accepted, GetTileMatrixDesc());
+		if (t->cargo_accepted.area.w != 0) {
+			uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
+			t->cargo_accepted.data = MallocT<uint32>(arr_len);
+			SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32);
+
+			/* Rebuild total cargo acceptance. */
+			UpdateTownCargoTotal(t);
+		}
 	}
 }
 
--- a/src/town.h
+++ b/src/town.h
@@ -19,6 +19,7 @@
 #include "subsidy_type.h"
 #include "newgrf_storage.h"
 #include "cargotype.h"
+#include "tilematrix_type.hpp"
 #include <list>
 
 template <typename T>
@@ -27,6 +28,8 @@
 	T class_count[HOUSE_CLASS_MAX];
 };
 
+typedef TileMatrix<uint32, 4> AcceptanceMatrix;
+
 static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY  = 4; ///< value for custom town number in difficulty settings
 static const uint CUSTOM_TOWN_MAX_NUMBER = 5000;  ///< this is the maximum number of towns a user can specify in customisation
 
@@ -76,6 +79,11 @@
 
 	inline byte GetPercentTransported(CargoID cid) const { return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1); }
 
+	/* Cargo production and acceptance stats. */
+	uint32 cargo_produced;           ///< Bitmap of all cargos produced by houses in this town.
+	AcceptanceMatrix cargo_accepted; ///< Bitmap of cargos accepted by houses for each 4*4 map square of the town.
+	uint32 cargo_accepted_total;     ///< NOSAVE: Bitmap of all cargos accepted by houses in this town.
+
 	uint16 time_until_rebuild;     ///< time until we rebuild a house
 
 	uint16 grow_counter;           ///< counter to count when to grow
@@ -175,6 +183,8 @@
 void ClearTownHouse(Town *t, TileIndex tile);
 void UpdateTownMaxPass(Town *t);
 void UpdateTownRadius(Town *t);
+void UpdateTownCargos(Town *t);
+void UpdateTownCargoTotal(Town *t);
 CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags);
 Town *ClosestTownFromTile(TileIndex tile, uint threshold);
 void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags);
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -673,6 +673,75 @@
 	/* not used */
 }
 
+/** Update the total cargo acceptance of the whole town.
+ * @param t The town to update.
+ */
+void UpdateTownCargoTotal(Town *t)
+{
+	t->cargo_accepted_total = 0;
+
+	const TileArea &area = t->cargo_accepted.GetArea();
+	TILE_AREA_LOOP(tile, area) {
+		if (TileX(tile) % AcceptanceMatrix::GRID == 0 && TileY(tile) % AcceptanceMatrix::GRID == 0) {
+			t->cargo_accepted_total |= t->cargo_accepted[tile];
+		}
+	}
+}
+
+/**
+ * Update accepted town cargos around a specific tile.
+ * @param t The town to update.
+ * @param start Update the values around this tile.
+ * @param update_total Set to true if the total cargo acceptance should be updated.
+ */
+static void UpdateTownCargos(Town *t, TileIndex start, bool update_total = true)
+{
+	CargoArray accepted, produced;
+	uint32 dummy;
+
+	/* Gather acceptance for all houses in an area around the start tile.
+	 * The area is composed of the square the tile is in, extended one square in all
+	 * directions as the coverage area of a single station is bigger than just one square. */
+	TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1);
+	TILE_AREA_LOOP(tile, area) {
+		if (!IsTileType(tile, MP_HOUSE) || GetTownIndex(tile) != t->index) continue;
+
+		AddAcceptedCargo_Town(tile, accepted, &dummy);
+		AddProducedCargo_Town(tile, produced);
+	}
+
+	/* Create bitmap of produced and accepted cargos. */
+	uint32 acc = 0;
+	for (uint cid = 0; cid < NUM_CARGO; cid++) {
+		if (accepted[cid] >= 8) SetBit(acc, cid);
+		if (produced[cid] > 0) SetBit(t->cargo_produced, cid);
+	}
+	t->cargo_accepted[start] = acc;
+
+	if (update_total) UpdateTownCargoTotal(t);
+}
+
+/** Update cargo acceptance for the complete town.
+ * @param t The town to update.
+ */
+void UpdateTownCargos(Town *t)
+{
+	t->cargo_produced = 0;
+
+	const TileArea &area = t->cargo_accepted.GetArea();
+	if (area.tile == INVALID_TILE) return;
+
+	/* Update acceptance for each grid square. */
+	TILE_AREA_LOOP(tile, area) {
+		if (TileX(tile) % AcceptanceMatrix::GRID == 0 && TileY(tile) % AcceptanceMatrix::GRID == 0) {
+			UpdateTownCargos(t, tile, false);
+		}
+	}
+
+	/* Update the total acceptance. */
+	UpdateTownCargoTotal(t);
+}
+
 static bool GrowTown(Town *t);
 
 static void TownTickHandler(Town *t)
@@ -2221,6 +2290,7 @@
 		}
 
 		MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
+		UpdateTownCargos(t, tile);
 
 		return true;
 	}
@@ -2302,6 +2372,9 @@
 	if (eflags & BUILDING_2_TILES_Y)   DoClearTownHouseHelper(tile + TileDiffXY(0, 1), t, ++house);
 	if (eflags & BUILDING_2_TILES_X)   DoClearTownHouseHelper(tile + TileDiffXY(1, 0), t, ++house);
 	if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1), t, ++house);
+
+	/* Update cargo acceptance. */
+	UpdateTownCargos(t, tile);
 }
 
 /**
@@ -3068,6 +3141,7 @@
 		UpdateTownRating(t);
 		UpdateTownGrowRate(t);
 		UpdateTownUnwanted(t);
+		UpdateTownCargos(t);
 	}
 }