summaryrefslogtreecommitdiff
path: root/src/industry_cmd.cpp
diff options
context:
space:
mode:
authorErich Eckner <git@eckner.net>2018-10-30 11:13:12 +0100
committerErich Eckner <git@eckner.net>2018-10-30 15:28:03 +0100
commita34d095259409cf1454d9777deabbc00bcdb9407 (patch)
tree9e7c37ed33f5bd6b3c2f41cf248dcb656b2a4afa /src/industry_cmd.cpp
parent6647cb917963c4e0d6d633b7a92af78167050893 (diff)
downloadopenttd-a34d095259409cf1454d9777deabbc00bcdb9407.tar.xz
underground patch appliedunderground-plus-others-original
Diffstat (limited to 'src/industry_cmd.cpp')
-rw-r--r--src/industry_cmd.cpp71
1 files changed, 60 insertions, 11 deletions
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index 69d83ba14..4cead964f 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -14,6 +14,7 @@
#include "industry.h"
#include "station_base.h"
#include "landscape.h"
+#include "layer_func.h"
#include "viewport_func.h"
#include "command_func.h"
#include "town.h"
@@ -193,17 +194,36 @@ void Industry::PostDestructor(size_t index)
/**
- * Return a random valid industry.
- * @return random industry, NULL if there are no industries
+ * Return a random industry that statisfies some criteria
+ * specified with a callback function.
+ *
+ * @param enum_proc Callback function. Return true for a matching industry and false to continue iterating.
+ * @param skip Skip over this industry id when searching.
+ * @param data Optional data passed to the callback function.
+ * @return An industry satisfying the search criteria or NULL if no such industry exists.
*/
-/* static */ Industry *Industry::GetRandom()
+/* static */ Industry *Industry::GetRandom(EnumIndustryProc enum_proc, IndustryID skip, void *data)
{
- if (Industry::GetNumItems() == 0) return NULL;
- int num = RandomRange((uint16)Industry::GetNumItems());
- size_t index = MAX_UVALUE(size_t);
+ assert(skip == INVALID_INDUSTRY || Industry::IsValidID(skip));
+
+ uint16 max_num = 0;
+ if (enum_proc != NULL) {
+ /* A callback was given, count all matching industries. */
+ Industry *ind;
+ FOR_ALL_INDUSTRIES(ind) {
+ if (ind->index != skip && enum_proc(ind, data)) max_num++;
+ }
+ } else {
+ max_num = (uint16)Industry::GetNumItems();
+ /* Subtract one if an industry to skip was given. max_num is at least
+ * one here as otherwise skip could not be valid. */
+ if (skip != INVALID_INDUSTRY) max_num--;
+ }
+ if (max_num == 0) return NULL;
- while (num >= 0) {
- num--;
+ uint num = RandomRange(max_num) + 1;
+ size_t index = MAX_UVALUE(size_t);
+ do {
index++;
/* Make sure we have a valid industry */
@@ -211,7 +231,9 @@ void Industry::PostDestructor(size_t index)
index++;
assert(index < Industry::GetPoolSize());
}
- }
+
+ if (index != skip && (enum_proc == NULL || enum_proc(Industry::Get(index), data))) num--;
+ } while (num > 0);
return Industry::Get(index);
}
@@ -506,7 +528,7 @@ static void TransportIndustryGoods(TileIndex tile)
i->this_month_production[j] += cw;
- uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
+ uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations(), tile);
i->this_month_transported[j] += am;
moved_cargo |= (am != 0);
@@ -1380,7 +1402,7 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
- if (!IsValidTile(cur_tile)) {
+ if (!IsValidTile(cur_tile) || IsUnderground(cur_tile)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
@@ -1583,6 +1605,28 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int t
return CommandCost();
}
+/** Update the mask of always accepted cargoes that are also produced. */
+void UpdateIndustryAcceptance(Industry *ind)
+{
+ CargoArray accepted;
+ uint32 always_accepted = 0;
+
+ /* Gather always accepted cargoes for all tiles of this industry. */
+ TILE_AREA_LOOP(tile, ind->location) {
+ if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) {
+ AddAcceptedCargo_Industry(tile, accepted, &always_accepted);
+ }
+ }
+
+ /* Create mask of produced cargoes. */
+ uint32 produced = 0;
+ for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
+ if (ind->produced_cargo[i] != CT_INVALID) SetBit(produced, ind->produced_cargo[i]);
+ }
+
+ ind->produced_accepted_mask = always_accepted & produced;
+}
+
/**
* Advertise about a new industry opening.
* @param ind Industry being opened.
@@ -1756,6 +1800,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
}
InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
+ UpdateIndustryAcceptance(i);
Station::RecomputeIndustriesNearForAll();
}
@@ -2153,6 +2198,9 @@ static void UpdateIndustryStatistics(Industry *i)
i->last_month_transported[j] = i->this_month_transported[j];
i->this_month_transported[j] = 0;
+
+ /* Average production over the last eight months. */
+ i->average_production[j] = (i->average_production[j] * 7 + i->last_month_production[j]) / 8;
}
}
}
@@ -2697,6 +2745,7 @@ void IndustryMonthlyLoop()
Industry *i;
FOR_ALL_INDUSTRIES(i) {
UpdateIndustryStatistics(i);
+ UpdateIndustryAcceptance(i);
if (i->prod_level == PRODLEVEL_CLOSURE) {
delete i;
} else {