Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef STATION_BASE_H
00013 #define STATION_BASE_H
00014
00015 #include "core/random_func.hpp"
00016 #include "base_station_base.h"
00017 #include "newgrf_airport.h"
00018 #include "cargopacket.h"
00019 #include "industry_type.h"
00020 #include "linkgraph/linkgraph_type.h"
00021 #include "newgrf_storage.h"
00022 #include <map>
00023
00024 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
00025 extern StationPool _station_pool;
00026
00027 static const byte INITIAL_STATION_RATING = 175;
00028
00036 class FlowStat {
00037 public:
00038 typedef std::map<uint32, StationID> SharesMap;
00039
00040 inline FlowStat() {NOT_REACHED();}
00041
00042 inline FlowStat(StationID st, uint flow)
00043 {
00044 assert(flow > 0);
00045 this->shares[flow] = st;
00046 }
00047
00055 inline void AppendShare(StationID st, uint flow)
00056 {
00057 assert(flow > 0);
00058 this->shares[(--this->shares.end())->first + flow] = st;
00059 }
00060
00061 uint GetShare(StationID st) const;
00062
00063 void ChangeShare(StationID st, int flow);
00064
00065 inline const SharesMap *GetShares() const { return &this->shares; }
00066
00074 inline StationID GetVia() const
00075 {
00076 assert(!this->shares.empty());
00077 return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
00078 }
00079
00080 StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00081
00082 private:
00083 SharesMap shares;
00084 };
00085
00086 typedef std::map<StationID, FlowStat> FlowStatMap;
00087
00091 struct GoodsEntry {
00093 enum GoodsEntryStatus {
00098 GES_ACCEPTANCE,
00099
00107 GES_PICKUP,
00108
00113 GES_EVER_ACCEPTED,
00114
00119 GES_LAST_MONTH,
00120
00125 GES_CURRENT_MONTH,
00126
00131 GES_ACCEPTED_BIGTICK,
00132 };
00133
00134 GoodsEntry() :
00135 acceptance_pickup(0),
00136 time_since_pickup(255),
00137 rating(INITIAL_STATION_RATING),
00138 last_speed(0),
00139 last_age(255),
00140 link_graph(INVALID_LINK_GRAPH),
00141 node(INVALID_NODE),
00142 max_waiting_cargo(0)
00143 {}
00144
00145 byte acceptance_pickup;
00146
00152 byte time_since_pickup;
00153
00154 byte rating;
00155
00165 byte last_speed;
00166
00171 byte last_age;
00172
00173 byte amount_fract;
00174 StationCargoList cargo;
00175
00176 LinkGraphID link_graph;
00177 NodeID node;
00178 FlowStatMap flows;
00179 uint max_waiting_cargo;
00180
00186 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00187 uint GetSumFlowVia(StationID via) const;
00188
00195 inline StationID GetVia(StationID source) const
00196 {
00197 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00198 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00199 }
00200
00209 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00210 {
00211 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00212 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00213 }
00214 };
00215
00217 struct Airport : public TileArea {
00218 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00219
00220 uint64 flags;
00221 byte type;
00222 byte layout;
00223 Direction rotation;
00224
00225 PersistentStorage *psa;
00226
00232 const AirportSpec *GetSpec() const
00233 {
00234 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00235 return AirportSpec::Get(this->type);
00236 }
00237
00244 const AirportFTAClass *GetFTA() const
00245 {
00246 return this->GetSpec()->fsm;
00247 }
00248
00250 inline bool HasHangar() const
00251 {
00252 return this->GetSpec()->nof_depots > 0;
00253 }
00254
00263 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00264 {
00265 const AirportSpec *as = this->GetSpec();
00266 switch (this->rotation) {
00267 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00268
00269 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00270
00271 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00272
00273 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00274
00275 default: NOT_REACHED();
00276 }
00277 }
00278
00285 inline TileIndex GetHangarTile(uint hangar_num) const
00286 {
00287 const AirportSpec *as = this->GetSpec();
00288 for (uint i = 0; i < as->nof_depots; i++) {
00289 if (as->depot_table[i].hangar_num == hangar_num) {
00290 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00291 }
00292 }
00293 NOT_REACHED();
00294 }
00295
00302 inline Direction GetHangarExitDirection(TileIndex tile) const
00303 {
00304 const AirportSpec *as = this->GetSpec();
00305 const HangarTileTable *htt = GetHangarDataByTile(tile);
00306 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00307 }
00308
00315 inline uint GetHangarNum(TileIndex tile) const
00316 {
00317 const HangarTileTable *htt = GetHangarDataByTile(tile);
00318 return htt->hangar_num;
00319 }
00320
00322 inline uint GetNumHangars() const
00323 {
00324 uint num = 0;
00325 uint counted = 0;
00326 const AirportSpec *as = this->GetSpec();
00327 for (uint i = 0; i < as->nof_depots; i++) {
00328 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00329 num++;
00330 SetBit(counted, as->depot_table[i].hangar_num);
00331 }
00332 }
00333 return num;
00334 }
00335
00336 private:
00343 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00344 {
00345 const AirportSpec *as = this->GetSpec();
00346 for (uint i = 0; i < as->nof_depots; i++) {
00347 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00348 return as->depot_table + i;
00349 }
00350 }
00351 NOT_REACHED();
00352 }
00353 };
00354
00355 typedef SmallVector<Industry *, 2> IndustryVector;
00356
00358 struct Station FINAL : SpecializedStation<Station, false> {
00359 public:
00360 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00361 {
00362 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00363 }
00364
00365 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00366
00367 RoadStop *bus_stops;
00368 TileArea bus_station;
00369 RoadStop *truck_stops;
00370 TileArea truck_station;
00371
00372 Airport airport;
00373 TileIndex dock_tile;
00374
00375 IndustryType indtype;
00376
00377 StationHadVehicleOfTypeByte had_vehicle_of_type;
00378
00379 byte time_since_load;
00380 byte time_since_unload;
00381
00382 byte last_vehicle_type;
00383 std::list<Vehicle *> loading_vehicles;
00384 GoodsEntry goods[NUM_CARGO];
00385 uint32 always_accepted;
00386
00387 IndustryVector industries_near;
00388
00389 Station(TileIndex tile = INVALID_TILE);
00390 ~Station();
00391
00392 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00393
00394 void MarkTilesDirty(bool cargo_change) const;
00395
00396 void UpdateVirtCoord();
00397
00398 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00399 uint GetPlatformLength(TileIndex tile) const;
00400 void RecomputeIndustriesNear();
00401 static void RecomputeIndustriesNearForAll();
00402
00403 uint GetCatchmentRadius() const;
00404 Rect GetCatchmentRect() const;
00405
00406 inline bool TileBelongsToRailStation(TileIndex tile) const
00407 {
00408 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00409 }
00410
00411 inline bool TileBelongsToAirport(TileIndex tile) const
00412 {
00413 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00414 }
00415
00416 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00417
00418 void GetTileArea(TileArea *ta, StationType type) const;
00419
00420 void RunAverages();
00421 };
00422
00423 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00424
00426 class AirportTileIterator : public OrthogonalTileIterator {
00427 private:
00428 const Station *st;
00429
00430 public:
00435 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00436 {
00437 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00438 }
00439
00440 inline TileIterator& operator ++()
00441 {
00442 (*this).OrthogonalTileIterator::operator++();
00443 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00444 (*this).OrthogonalTileIterator::operator++();
00445 }
00446 return *this;
00447 }
00448
00449 virtual TileIterator *Clone() const
00450 {
00451 return new AirportTileIterator(*this);
00452 }
00453 };
00454
00455 #endif