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
00087 class FlowStatMap : public std::map<StationID, FlowStat> {
00088 public:
00089 void AddFlow(StationID origin, StationID via, uint amount);
00090 void PassOnFlow(StationID origin, StationID via, uint amount);
00091 void FinalizeLocalConsumption(StationID self);
00092 };
00093
00097 struct GoodsEntry {
00099 enum GoodsEntryStatus {
00104 GES_ACCEPTANCE,
00105
00113 GES_PICKUP,
00114
00119 GES_EVER_ACCEPTED,
00120
00125 GES_LAST_MONTH,
00126
00131 GES_CURRENT_MONTH,
00132
00137 GES_ACCEPTED_BIGTICK,
00138 };
00139
00140 GoodsEntry() :
00141 acceptance_pickup(0),
00142 time_since_pickup(255),
00143 rating(INITIAL_STATION_RATING),
00144 last_speed(0),
00145 last_age(255),
00146 link_graph(INVALID_LINK_GRAPH),
00147 node(INVALID_NODE),
00148 max_waiting_cargo(0)
00149 {}
00150
00151 byte acceptance_pickup;
00152
00158 byte time_since_pickup;
00159
00160 byte rating;
00161
00171 byte last_speed;
00172
00177 byte last_age;
00178
00179 byte amount_fract;
00180 StationCargoList cargo;
00181
00182 LinkGraphID link_graph;
00183 NodeID node;
00184 FlowStatMap flows;
00185 uint max_waiting_cargo;
00186
00192 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00193 uint GetSumFlowVia(StationID via) const;
00194
00201 inline StationID GetVia(StationID source) const
00202 {
00203 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00204 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00205 }
00206
00215 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00216 {
00217 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00218 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00219 }
00220 };
00221
00223 struct Airport : public TileArea {
00224 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00225
00226 uint64 flags;
00227 byte type;
00228 byte layout;
00229 Direction rotation;
00230
00231 PersistentStorage *psa;
00232
00238 const AirportSpec *GetSpec() const
00239 {
00240 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00241 return AirportSpec::Get(this->type);
00242 }
00243
00250 const AirportFTAClass *GetFTA() const
00251 {
00252 return this->GetSpec()->fsm;
00253 }
00254
00256 inline bool HasHangar() const
00257 {
00258 return this->GetSpec()->nof_depots > 0;
00259 }
00260
00269 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00270 {
00271 const AirportSpec *as = this->GetSpec();
00272 switch (this->rotation) {
00273 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00274
00275 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00276
00277 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00278
00279 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00280
00281 default: NOT_REACHED();
00282 }
00283 }
00284
00291 inline TileIndex GetHangarTile(uint hangar_num) const
00292 {
00293 const AirportSpec *as = this->GetSpec();
00294 for (uint i = 0; i < as->nof_depots; i++) {
00295 if (as->depot_table[i].hangar_num == hangar_num) {
00296 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00297 }
00298 }
00299 NOT_REACHED();
00300 }
00301
00308 inline Direction GetHangarExitDirection(TileIndex tile) const
00309 {
00310 const AirportSpec *as = this->GetSpec();
00311 const HangarTileTable *htt = GetHangarDataByTile(tile);
00312 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00313 }
00314
00321 inline uint GetHangarNum(TileIndex tile) const
00322 {
00323 const HangarTileTable *htt = GetHangarDataByTile(tile);
00324 return htt->hangar_num;
00325 }
00326
00328 inline uint GetNumHangars() const
00329 {
00330 uint num = 0;
00331 uint counted = 0;
00332 const AirportSpec *as = this->GetSpec();
00333 for (uint i = 0; i < as->nof_depots; i++) {
00334 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00335 num++;
00336 SetBit(counted, as->depot_table[i].hangar_num);
00337 }
00338 }
00339 return num;
00340 }
00341
00342 private:
00349 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00350 {
00351 const AirportSpec *as = this->GetSpec();
00352 for (uint i = 0; i < as->nof_depots; i++) {
00353 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00354 return as->depot_table + i;
00355 }
00356 }
00357 NOT_REACHED();
00358 }
00359 };
00360
00361 typedef SmallVector<Industry *, 2> IndustryVector;
00362
00364 struct Station FINAL : SpecializedStation<Station, false> {
00365 public:
00366 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00367 {
00368 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00369 }
00370
00371 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00372
00373 RoadStop *bus_stops;
00374 TileArea bus_station;
00375 RoadStop *truck_stops;
00376 TileArea truck_station;
00377
00378 Airport airport;
00379 TileIndex dock_tile;
00380
00381 IndustryType indtype;
00382
00383 StationHadVehicleOfTypeByte had_vehicle_of_type;
00384
00385 byte time_since_load;
00386 byte time_since_unload;
00387
00388 byte last_vehicle_type;
00389 std::list<Vehicle *> loading_vehicles;
00390 GoodsEntry goods[NUM_CARGO];
00391 uint32 always_accepted;
00392
00393 IndustryVector industries_near;
00394
00395 Station(TileIndex tile = INVALID_TILE);
00396 ~Station();
00397
00398 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00399
00400 void MarkTilesDirty(bool cargo_change) const;
00401
00402 void UpdateVirtCoord();
00403
00404 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00405 uint GetPlatformLength(TileIndex tile) const;
00406 void RecomputeIndustriesNear();
00407 static void RecomputeIndustriesNearForAll();
00408
00409 uint GetCatchmentRadius() const;
00410 Rect GetCatchmentRect() const;
00411
00412 inline bool TileBelongsToRailStation(TileIndex tile) const
00413 {
00414 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00415 }
00416
00417 inline bool TileBelongsToAirport(TileIndex tile) const
00418 {
00419 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00420 }
00421
00422 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00423
00424 void GetTileArea(TileArea *ta, StationType type) const;
00425
00426 void RunAverages();
00427 };
00428
00429 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00430
00432 class AirportTileIterator : public OrthogonalTileIterator {
00433 private:
00434 const Station *st;
00435
00436 public:
00441 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00442 {
00443 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00444 }
00445
00446 inline TileIterator& operator ++()
00447 {
00448 (*this).OrthogonalTileIterator::operator++();
00449 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00450 (*this).OrthogonalTileIterator::operator++();
00451 }
00452 return *this;
00453 }
00454
00455 virtual TileIterator *Clone() const
00456 {
00457 return new AirportTileIterator(*this);
00458 }
00459 };
00460
00461 #endif