mirror of https://github.com/OpenTTD/OpenTTD
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.pull/7507/head
parent
abe8cf4985
commit
3bbd7ea2c1
|
@ -8534,7 +8534,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||||
19693 => 8
|
19693 => 8
|
||||||
|
|
||||||
--TileList_IndustryProducing--
|
--TileList_IndustryProducing--
|
||||||
Count(): 92
|
Count(): 90
|
||||||
Location ListDump:
|
Location ListDump:
|
||||||
46919 => 1
|
46919 => 1
|
||||||
46918 => 1
|
46918 => 1
|
||||||
|
@ -8626,8 +8626,6 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
||||||
44353 => 1
|
44353 => 1
|
||||||
44352 => 1
|
44352 => 1
|
||||||
44351 => 1
|
44351 => 1
|
||||||
46920 => 0
|
|
||||||
46911 => 0
|
|
||||||
|
|
||||||
--TileList_StationType--
|
--TileList_StationType--
|
||||||
Count(): 4
|
Count(): 4
|
||||||
|
|
|
@ -34,6 +34,14 @@ public:
|
||||||
this->h = 0;
|
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.
|
* Reset and clear the BitmapTileArea.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -49,6 +49,32 @@ void ScriptTileList::RemoveTile(TileIndex tile)
|
||||||
this->RemoveItem(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)
|
ScriptTileList_IndustryAccepting::ScriptTileList_IndustryAccepting(IndustryID industry_id, int radius)
|
||||||
{
|
{
|
||||||
if (!ScriptIndustry::IsValidIndustry(industry_id) || radius <= 0) return;
|
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;
|
if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
|
||||||
|
|
||||||
TileArea ta = TileArea(i->location).Expand(radius);
|
BitmapTileArea bta(TileArea(i->location).Expand(radius));
|
||||||
TILE_AREA_LOOP(cur_tile, ta) {
|
FillIndustryCatchment(i, radius, bta);
|
||||||
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;
|
|
||||||
|
|
||||||
|
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
|
/* Only add the tile if it accepts the cargo (sometimes just 1 tile of an
|
||||||
* industry triggers the acceptance). */
|
* industry triggers the acceptance). */
|
||||||
CargoArray acceptance = ::GetAcceptanceAroundTiles(cur_tile, 1, 1, radius);
|
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;
|
if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
|
||||||
|
|
||||||
TileArea ta = TileArea(i->location).Expand(radius);
|
BitmapTileArea bta(TileArea(i->location).Expand(radius));
|
||||||
TILE_AREA_LOOP(cur_tile, ta) {
|
FillIndustryCatchment(i, radius, bta);
|
||||||
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;
|
|
||||||
|
|
||||||
|
BitmapTileIterator it(bta);
|
||||||
|
for (TileIndex cur_tile = it; cur_tile != INVALID_TILE; cur_tile = ++it) {
|
||||||
this->AddTile(cur_tile);
|
this->AddTile(cur_tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue