Changeset - r14158:56944d690621
[Not reviewed]
master
0 4 0
rubidium - 14 years ago 2010-01-04 18:16:32
rubidium@openttd.org
(svn r18716) -Codechange: pass a TileArea to FindStationsAroundTiles
4 files changed with 10 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/ai/api/ai_industry.cpp
Show inline comments
 
@@ -79,97 +79,97 @@
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] == cargo_id) return i->last_month_production[j];
 
	}
 

	
 
	return -1;
 
}
 

	
 
/* static */ int32 AIIndustry::GetLastMonthTransported(IndustryID industry_id, CargoID cargo_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return -1;
 
	if (!AICargo::IsValidCargo(cargo_id)) return -1;
 

	
 
	const Industry *i = ::Industry::Get(industry_id);
 

	
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] == cargo_id) return i->last_month_transported[j];
 
	}
 

	
 
	return -1;
 
}
 

	
 
/* static */ int32 AIIndustry::GetLastMonthTransportedPercentage(IndustryID industry_id, CargoID cargo_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return -1;
 
	if (!AICargo::IsValidCargo(cargo_id)) return -1;
 

	
 
	const Industry *i = ::Industry::Get(industry_id);
 

	
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] == cargo_id) return ::ToPercent8(i->last_month_pct_transported[j]);
 
	}
 

	
 
	return -1;
 
}
 

	
 
/* static */ TileIndex AIIndustry::GetLocation(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return INVALID_TILE;
 

	
 
	return ::Industry::Get(industry_id)->xy;
 
}
 

	
 
/* static */ int32 AIIndustry::GetAmountOfStationsAround(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return -1;
 

	
 
	Industry *ind = ::Industry::Get(industry_id);
 
	StationList stations;
 
	::FindStationsAroundTiles(ind->xy, ind->width, ind->height, &stations);
 
	::FindStationsAroundTiles(TileArea(ind->xy, ind->width, ind->height), &stations);
 
	return (int32)stations.Length();
 
}
 

	
 
/* static */ int32 AIIndustry::GetDistanceManhattanToTile(IndustryID industry_id, TileIndex tile)
 
{
 
	if (!IsValidIndustry(industry_id)) return -1;
 

	
 
	return AIMap::DistanceManhattan(tile, GetLocation(industry_id));
 
}
 

	
 
/* static */ int32 AIIndustry::GetDistanceSquareToTile(IndustryID industry_id, TileIndex tile)
 
{
 
	if (!IsValidIndustry(industry_id)) return -1;
 

	
 
	return AIMap::DistanceSquare(tile, GetLocation(industry_id));
 
}
 

	
 
/* static */ bool AIIndustry::IsBuiltOnWater(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return false;
 

	
 
	return (::GetIndustrySpec(::Industry::Get(industry_id)->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
 
}
 

	
 
/* static */ bool AIIndustry::HasHeliport(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return false;
 

	
 
	return (::GetIndustrySpec(::Industry::Get(industry_id)->type)->behaviour & INDUSTRYBEH_AI_AIRSHIP_ROUTES) != 0;
 
}
 

	
 
/* static */ TileIndex AIIndustry::GetHeliportLocation(IndustryID industry_id)
 
{
 
	if (!IsValidIndustry(industry_id)) return INVALID_TILE;
 
	if (!HasHeliport(industry_id)) return INVALID_TILE;
 

	
 
	const Industry *ind = ::Industry::Get(industry_id);
 
	TILE_LOOP(tile_cur, ind->width, ind->height, ind->xy) {
 
		if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
 
			return tile_cur;
 
		}
 
	}
 

	
 
	return INVALID_TILE;
 
}
 

	
 
/* static */ bool AIIndustry::HasDock(IndustryID industry_id)
 
{
src/industry_cmd.cpp
Show inline comments
 
@@ -2021,97 +2021,97 @@ static bool CheckIndustryCloseDownProtec
 
 *          \c *c_produces is set when the industry produces the cargo type
 
 */
 
static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(ind->type);
 

	
 
	/* Check for acceptance of cargo */
 
	for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
 
		if (ind->accepts_cargo[j] == CT_INVALID) continue;
 
		if (cargo == ind->accepts_cargo[j]) {
 
			if (HasBit(indspec->callback_mask, CBM_IND_REFUSE_CARGO)) {
 
				uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO,
 
						0, GetReverseCargoTranslation(cargo, indspec->grf_prop.grffile),
 
						ind, ind->type, ind->xy);
 
				if (res == 0) continue;
 
			}
 
			*c_accepts = true;
 
			break;
 
		}
 
	}
 

	
 
	/* Check for produced cargo */
 
	for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
 
		if (ind->produced_cargo[j] == CT_INVALID) continue;
 
		if (cargo == ind->produced_cargo[j]) {
 
			*c_produces = true;
 
			break;
 
		}
 
	}
 
}
 

	
 
/**
 
 * Compute who can service the industry.
 
 *
 
 * Here, 'can service' means that he/she has trains and stations close enough
 
 * to the industry with the right cargo type and the right orders (ie has the
 
 * technical means).
 
 *
 
 * @param ind: Industry being investigated.
 
 *
 
 * @return: 0 if nobody can service the industry, 2 if the local company can
 
 * service the industry, and 1 otherwise (only competitors can service the
 
 * industry)
 
 */
 
static int WhoCanServiceIndustry(Industry *ind)
 
{
 
	/* Find all stations within reach of the industry */
 
	StationList stations;
 
	FindStationsAroundTiles(ind->xy, ind->width, ind->height, &stations);
 
	FindStationsAroundTiles(TileArea(ind->xy, ind->width, ind->height), &stations);
 

	
 
	if (stations.Length() == 0) return 0; // No stations found at all => nobody services
 

	
 
	const Vehicle *v;
 
	int result = 0;
 
	FOR_ALL_VEHICLES(v) {
 
		/* Is it worthwhile to try this vehicle? */
 
		if (v->owner != _local_company && result != 0) continue;
 

	
 
		/* Check whether it accepts the right kind of cargo */
 
		bool c_accepts = false;
 
		bool c_produces = false;
 
		if (v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
 
			for (const Vehicle *u = v; u != NULL; u = u->Next()) {
 
				CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
 
			}
 
		} else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
 
			CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
 
		} else {
 
			continue;
 
		}
 
		if (!c_accepts && !c_produces) continue; // Wrong cargo
 

	
 
		/* Check orders of the vehicle.
 
		 * We cannot check the first of shared orders only, since the first vehicle in such a chain
 
		 * may have a different cargo type.
 
		 */
 
		const Order *o;
 
		FOR_VEHICLE_ORDERS(v, o) {
 
			if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
 
				/* Vehicle visits a station to load or unload */
 
				Station *st = Station::Get(o->GetDestination());
 
				assert(st != NULL);
 

	
 
				/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
 
				if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
 

	
 
				if (stations.Contains(st)) {
 
					if (v->owner == _local_company) return 2; // Company services industry
 
					result = 1; // Competitor services industry
 
				}
 
			}
 
		}
 
	}
 
	return result;
 
}
 

	
 
/**
src/station_cmd.cpp
Show inline comments
 
@@ -2952,135 +2952,133 @@ static void UpdateStationWaiting(Station
 
	st->MarkTilesDirty(true);
 
}
 

	
 
static bool IsUniqueStationName(const char *name)
 
{
 
	const Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->name != NULL && strcmp(st->name, name) == 0) return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
/** Rename a station
 
 * @param tile unused
 
 * @param flags operation to perform
 
 * @param p1 station ID that is to be renamed
 
 * @param p2 unused
 
 * @param text the new name or an empty string when resetting to the default
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Station *st = Station::GetIfValid(p1);
 
	if (st == NULL || !CheckOwnership(st->owner)) return CMD_ERROR;
 

	
 
	bool reset = StrEmpty(text);
 

	
 
	if (!reset) {
 
		if (strlen(text) >= MAX_LENGTH_STATION_NAME_BYTES) return CMD_ERROR;
 
		if (!IsUniqueStationName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		free(st->name);
 
		st->name = reset ? NULL : strdup(text);
 

	
 
		st->UpdateVirtCoord();
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 1);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Find all stations around a rectangular producer (industry, house, headquarter, ...)
 
 *
 
 * @param tile North tile of producer
 
 * @param w_prod X extent of producer
 
 * @param h_prod Y extent of producer
 
 * @param location The location/area of the producer
 
 * @param stations The list to store the stations in
 
 */
 
void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList *stations)
 
void FindStationsAroundTiles(const TileArea &location, StationList *stations)
 
{
 
	/* area to search = producer plus station catchment radius */
 
	int max_rad = (_settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED);
 

	
 
	for (int dy = -max_rad; dy < h_prod + max_rad; dy++) {
 
		for (int dx = -max_rad; dx < w_prod + max_rad; dx++) {
 
			TileIndex cur_tile = TileAddWrap(tile, dx, dy);
 
	for (int dy = -max_rad; dy < location.h + max_rad; dy++) {
 
		for (int dx = -max_rad; dx < location.w + max_rad; dx++) {
 
			TileIndex cur_tile = TileAddWrap(location.tile, dx, dy);
 
			if (cur_tile == INVALID_TILE || !IsTileType(cur_tile, MP_STATION)) continue;
 

	
 
			Station *st = Station::GetByTile(cur_tile);
 
			if (st == NULL) continue;
 

	
 
			if (_settings_game.station.modified_catchment) {
 
				int rad = st->GetCatchmentRadius();
 
				if (dx < -rad || dx >= rad + w_prod || dy < -rad || dy >= rad + h_prod) continue;
 
				if (dx < -rad || dx >= rad + location.w || dy < -rad || dy >= rad + location.h) continue;
 
			}
 

	
 
			/* Insert the station in the set. This will fail if it has
 
			 * already been added.
 
			 */
 
			stations->Include(st);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Run a tile loop to find stations around a tile, on demand. Cache the result for further requests
 
 * @return pointer to a StationList containing all stations found
 
 */
 
const StationList *StationFinder::GetStations()
 
{
 
	if (this->tile != INVALID_TILE) {
 
		FindStationsAroundTiles(this->tile, this->w, this->h, &this->stations);
 
		FindStationsAroundTiles(*this, &this->stations);
 
		this->tile = INVALID_TILE;
 
	}
 
	return &this->stations;
 
}
 

	
 
uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
 
{
 
	/* Return if nothing to do. Also the rounding below fails for 0. */
 
	if (amount == 0) return 0;
 

	
 
	Station *st1 = NULL;   // Station with best rating
 
	Station *st2 = NULL;   // Second best station
 
	uint best_rating1 = 0; // rating of st1
 
	uint best_rating2 = 0; // rating of st2
 

	
 
	for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
 
		Station *st = *st_iter;
 

	
 
		/* Is the station reserved exclusively for somebody else? */
 
		if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
 

	
 
		if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
 

	
 
		if (_settings_game.order.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
 

	
 
		if (IsCargoInClass(type, CC_PASSENGERS)) {
 
			if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
 
		} else {
 
			if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
 
		}
 

	
 
		/* This station can be used, add it to st1/st2 */
 
		if (st1 == NULL || st->goods[type].rating >= best_rating1) {
 
			st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
 
		} else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
 
			st2 = st; best_rating2 = st->goods[type].rating;
 
		}
 
	}
 

	
 
	/* no stations around at all? */
 
	if (st1 == NULL) return 0;
 

	
 
	if (st2 == NULL) {
 
		/* only one station around */
 
		uint moved = amount * best_rating1 / 256 + 1;
 
		UpdateStationWaiting(st1, type, moved, source_type, source_id);
 
		return moved;
 
	}
src/station_func.h
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file station_func.h Functions related to stations. */
 

	
 
#ifndef STATION_FUNC_H
 
#define STATION_FUNC_H
 

	
 
#include "station_type.h"
 
#include "sprite.h"
 
#include "rail_type.h"
 
#include "road_type.h"
 
#include "tile_type.h"
 
#include "cargo_type.h"
 
#include "vehicle_type.h"
 

	
 
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
 

	
 
void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList *stations);
 
void FindStationsAroundTiles(const TileArea &location, StationList *stations);
 

	
 
void ShowStationViewWindow(StationID station);
 
void UpdateAllStationVirtCoords();
 

	
 
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad);
 
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint32 *always_accepted = NULL);
 

	
 
void UpdateStationAcceptance(Station *st, bool show_msg);
 

	
 
const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx);
 
void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image);
 

	
 
bool HasStationInUse(StationID station, CompanyID company);
 

	
 
RoadStop *GetRoadStopByTile(TileIndex tile, RoadStopType type);
 
uint GetNumRoadStops(const Station *st, RoadStopType type);
 

	
 
void DeleteOilRig(TileIndex t);
 

	
 
/* Check if a rail station tile is traversable. */
 
bool IsStationTileBlocked(TileIndex tile);
 

	
 
/* Check if a rail station tile is electrifiable. */
 
bool IsStationTileElectrifiable(TileIndex tile);
 

	
 
void UpdateAirportsNoise();
 

	
 
#endif /* STATION_FUNC_H */
0 comments (0 inline, 0 general)