summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeterN <peter@fuzzle.org>2019-04-13 14:27:57 +0100
committerGitHub <noreply@github.com>2019-04-13 14:27:57 +0100
commit3bbd7ea2c1a7f3631362805da76848112f7a606d (patch)
tree844aa787fc1043c392a20ec800d49b907f3f7580
parentabe8cf4985da211ad70c6232a3c737f15574f5de (diff)
downloadopenttd-3bbd7ea2c1a7f3631362805da76848112f7a606d.tar.xz
Fix: Industry coverage area is no longer rectangular. (#7464)
AIs test station catchment in reverse to how players see station catchment. This did not take account of non-rectangular station catchment areas, so AIs could end up placing stations in locations that did not accept/deliver cargo.
-rw-r--r--bin/ai/regression/tst_regression/result.txt4
-rw-r--r--src/bitmap_type.h8
-rw-r--r--src/script/api/script_tilelist.cpp44
3 files changed, 43 insertions, 13 deletions
diff --git a/bin/ai/regression/tst_regression/result.txt b/bin/ai/regression/tst_regression/result.txt
index 58736c68b..18ae14cb7 100644
--- a/bin/ai/regression/tst_regression/result.txt
+++ b/bin/ai/regression/tst_regression/result.txt
@@ -8534,7 +8534,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
19693 => 8
--TileList_IndustryProducing--
- Count(): 92
+ Count(): 90
Location ListDump:
46919 => 1
46918 => 1
@@ -8626,8 +8626,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
44353 => 1
44352 => 1
44351 => 1
- 46920 => 0
- 46911 => 0
--TileList_StationType--
Count(): 4
diff --git a/src/bitmap_type.h b/src/bitmap_type.h
index 11a419093..3c9c4afbd 100644
--- a/src/bitmap_type.h
+++ b/src/bitmap_type.h
@@ -34,6 +34,14 @@ public:
this->h = 0;
}
+ BitmapTileArea(const TileArea &ta)
+ {
+ this->tile = ta.tile;
+ this->w = ta.w;
+ this->h = ta.h;
+ this->data.resize(Index(this->w, this->h));
+ }
+
/**
* Reset and clear the BitmapTileArea.
*/
diff --git a/src/script/api/script_tilelist.cpp b/src/script/api/script_tilelist.cpp
index adddb989c..fcee67d96 100644
--- a/src/script/api/script_tilelist.cpp
+++ b/src/script/api/script_tilelist.cpp
@@ -49,6 +49,32 @@ void ScriptTileList::RemoveTile(TileIndex tile)
this->RemoveItem(tile);
}
+/**
+ * Helper to get list of tiles that will cover an industry's production or acceptance.
+ * @param i Industry in question
+ * @param radius Catchment radius to test
+ * @param bta BitmapTileArea to fill
+ */
+static void FillIndustryCatchment(const Industry *i, int radius, BitmapTileArea &bta)
+{
+ TILE_AREA_LOOP(cur_tile, i->location) {
+ if (!::IsTileType(cur_tile, MP_INDUSTRY) || ::GetIndustryIndex(cur_tile) != i->index) continue;
+
+ int tx = TileX(cur_tile);
+ int ty = TileY(cur_tile);
+ for (int y = -radius; y <= radius; y++) {
+ if (ty + y < 0 || ty + y > (int)MapMaxY()) continue;
+ for (int x = -radius; x <= radius; x++) {
+ if (tx + x < 0 || tx + x > (int)MapMaxX()) continue;
+ TileIndex tile = TileXY(tx + x, ty + y);
+ if (!IsValidTile(tile)) continue;
+ if (::IsTileType(tile, MP_INDUSTRY) && ::GetIndustryIndex(tile) == i->index) continue;
+ bta.SetTile(tile);
+ }
+ }
+ }
+}
+
ScriptTileList_IndustryAccepting::ScriptTileList_IndustryAccepting(IndustryID industry_id, int radius)
{
if (!ScriptIndustry::IsValidIndustry(industry_id) || radius <= 0) return;
@@ -66,12 +92,11 @@ ScriptTileList_IndustryAccepting::ScriptTileList_IndustryAccepting(IndustryID in
if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
- TileArea ta = TileArea(i->location).Expand(radius);
- TILE_AREA_LOOP(cur_tile, ta) {
- if (!::IsValidTile(cur_tile)) continue;
- /* Exclude all tiles that belong to this industry */
- if (::IsTileType(cur_tile, MP_INDUSTRY) && ::GetIndustryIndex(cur_tile) == industry_id) continue;
+ BitmapTileArea bta(TileArea(i->location).Expand(radius));
+ FillIndustryCatchment(i, radius, bta);
+ BitmapTileIterator it(bta);
+ for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
/* Only add the tile if it accepts the cargo (sometimes just 1 tile of an
* industry triggers the acceptance). */
CargoArray acceptance = ::GetAcceptanceAroundTiles(cur_tile, 1, 1, radius);
@@ -102,12 +127,11 @@ ScriptTileList_IndustryProducing::ScriptTileList_IndustryProducing(IndustryID in
if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
- TileArea ta = TileArea(i->location).Expand(radius);
- TILE_AREA_LOOP(cur_tile, ta) {
- if (!::IsValidTile(cur_tile)) continue;
- /* Exclude all tiles that belong to this industry */
- if (::IsTileType(cur_tile, MP_INDUSTRY) && ::GetIndustryIndex(cur_tile) == industry_id) continue;
+ BitmapTileArea bta(TileArea(i->location).Expand(radius));
+ FillIndustryCatchment(i, radius, bta);
+ BitmapTileIterator it(bta);
+ for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
this->AddTile(cur_tile);
}
}