(svn r18726) -Fix [FS#3463]: with non-uniform industries the 'supplies' text when building a station could be incorrect (missing a cargo)

-Change [NoAI]: AITile::GetCargoProduction now returns the number of producers and not the number of tiles of producers.
-Fix [NoAI]: AITileList_IndustryProducing would omit some tiles for at which a station would get cargo.
This commit is contained in:
rubidium
2010-01-04 21:10:20 +00:00
parent 1ed599f5cf
commit 28fc7b47bd
8 changed files with 151 additions and 122 deletions

View File

@@ -91,6 +91,12 @@
* vehicle of that type in your company, regardless if it's still buildable
* or not. AIEngine::IsBuildable returns only true when you can actually
* build an engine.
* \li AITile::GetCargoProduction will now return the number of producers,
* including houses instead the number of producing tiles. This means that
* also industries that do not have a tile within the radius, but where
* the search bounding box and the industry's bounding box intersect, are
* counted. Previously these industries (and their cargos), although they
* produced cargo for a station at the given location, were not returned.
*
* \b 0.7.5
*

View File

@@ -309,9 +309,8 @@ public:
static int32 GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int radius);
/**
* Checks how many tiles in the radius produces this cargo.
* It creates a radius around the tile, and adds up all tiles that produce
* this cargo.
* Checks how many producers in the radius produces this cargo.
* It creates a radius around the tile, and counts all producer of this cargo.
* @param tile The tile to check on.
* @param cargo_type The cargo to check the production of.
* @param width The width of the station.
@@ -321,8 +320,7 @@ public:
* @pre width > 0.
* @pre height > 0.
* @pre radius >= 0.
* @return The tiles that produce this cargo within radius of the tile.
* @note Town(houses) are not included in the value.
* @return The number of producers that produce this cargo within radius of the tile.
*/
static int32 GetCargoProduction(TileIndex tile, CargoID cargo_type, int width, int height, int radius);

View File

@@ -90,13 +90,11 @@ AITileList_IndustryProducing::AITileList_IndustryProducing(IndustryID industry_i
const Industry *i = ::Industry::Get(industry_id);
/* Check if this industry produces anything */
{
bool cargo_produces = false;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] != CT_INVALID) cargo_produces = true;
}
if (!cargo_produces) return;
bool cargo_produces = false;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] != CT_INVALID) cargo_produces = true;
}
if (!cargo_produces) return;
if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
@@ -105,17 +103,6 @@ AITileList_IndustryProducing::AITileList_IndustryProducing(IndustryID industry_i
/* Exclude all tiles that belong to this industry */
if (::IsTileType(cur_tile, MP_INDUSTRY) && ::GetIndustryIndex(cur_tile) == industry_id) continue;
/* Only add the tile if it produces the cargo (a bug in OpenTTD makes this
* inconsitance). */
CargoArray produced = ::GetProductionAroundTiles(cur_tile, 1, 1, radius);
{
bool cargo_produces = false;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] != CT_INVALID && produced[i->produced_cargo[j]] != 0) cargo_produces = true;
}
if (!cargo_produces) continue;
}
this->AddTile(cur_tile);
}
}

View File

@@ -924,16 +924,6 @@ static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mod
return 0;
}
static void AddProducedCargo_Industry(TileIndex tile, CargoArray &produced)
{
const Industry *i = Industry::GetByTile(tile);
for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
CargoID cargo = i->produced_cargo[j];
if (cargo != CT_INVALID) produced[cargo]++;
}
}
static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
{
/* If the founder merges, the industry was created by the merged company */
@@ -2468,7 +2458,7 @@ extern const TileTypeProcs _tile_type_industry_procs = {
AnimateTile_Industry, // animate_tile_proc
TileLoop_Industry, // tile_loop_proc
ChangeTileOwner_Industry, // change_tile_owner_proc
AddProducedCargo_Industry, // add_produced_cargo_proc
NULL, // add_produced_cargo_proc
NULL, // vehicle_enter_tile_proc
GetFoundation_Industry, // get_foundation_proc
TerraformTile_Industry, // terraform_tile_proc

View File

@@ -539,6 +539,30 @@ void TileArea::Add(TileIndex to_add)
this->h = ey - sy + 1;
}
bool TileArea::Intersects(const TileArea &ta) const
{
if (ta.w == 0 || this->w == 0) return false;
assert(ta.w != 0 && ta.h != 0 && this->w != 0 && this->h != 0);
uint left1 = TileX(this->tile);
uint top1 = TileY(this->tile);
uint right1 = left1 + this->w - 1;
uint bottom1 = top1 + this->h - 1;
uint left2 = TileX(ta.tile);
uint top2 = TileY(ta.tile);
uint right2 = left2 + ta.w - 1;
uint bottom2 = top2 + ta.h - 1;
return !(
left2 > right1 ||
right2 < left1 ||
top2 > bottom1 ||
bottom2 < top1
);
}
void InitializeStations()
{

View File

@@ -485,10 +485,25 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
assert(w > 0);
assert(h > 0);
for (int yc = y1; yc != y2; yc++) {
for (int xc = x1; xc != x2; xc++) {
TileIndex tile = TileXY(xc, yc);
AddProducedCargo(tile, produced);
TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1));
/* Loop over all tiles to get the produced cargo of
* everything except industries */
TILE_AREA_LOOP(tile, ta) AddProducedCargo(tile, produced);
/* Loop over the industries. They produce cargo for
* anything that is within 'rad' from their bounding
* box. As such if you have e.g. a oil well the tile
* area loop might not hit an industry tile while
* the industry would produce cargo for the station.
*/
const Industry *i;
FOR_ALL_INDUSTRIES(i) {
if (!ta.Intersects(i->location)) continue;
for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
CargoID cargo = i->produced_cargo[j];
if (cargo != CT_INVALID) produced[cargo]++;
}
}

View File

@@ -53,6 +53,13 @@ struct TileArea {
this->w = 0;
this->h = 0;
}
/**
* Does this tile area intersect with another?
* @param ta the other tile area to check against.
* @return true if they intersect.
*/
bool Intersects(const TileArea &ta) const;
};
#endif /* TILEAREA_TYPE_H */