diff options
author | PeterN <peter@fuzzle.org> | 2019-04-13 14:27:57 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-13 14:27:57 +0100 |
commit | 3bbd7ea2c1a7f3631362805da76848112f7a606d (patch) | |
tree | 844aa787fc1043c392a20ec800d49b907f3f7580 | |
parent | abe8cf4985da211ad70c6232a3c737f15574f5de (diff) | |
download | openttd-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.txt | 4 | ||||
-rw-r--r-- | src/bitmap_type.h | 8 | ||||
-rw-r--r-- | src/script/api/script_tilelist.cpp | 44 |
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); } } |