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 void Cleanup(NodeID self, LinkGraphID link_graph);
00082
00083 private:
00084 SharesMap shares;
00085 };
00086
00088 class FlowStatMap : public std::map<StationID, FlowStat> {
00089 public:
00090 void AddFlow(StationID origin, StationID via, uint amount);
00091 void PassOnFlow(StationID origin, StationID via, uint amount);
00092 void DeleteFlows(StationID via);
00093 void FinalizeLocalConsumption(StationID self);
00094 void Cleanup(StationID self, LinkGraphID link_graph);
00095 };
00096
00100 struct GoodsEntry {
00102 enum GoodsEntryStatus {
00107 GES_ACCEPTANCE,
00108
00116 GES_PICKUP,
00117
00122 GES_EVER_ACCEPTED,
00123
00128 GES_LAST_MONTH,
00129
00134 GES_CURRENT_MONTH,
00135
00140 GES_ACCEPTED_BIGTICK,
00141 };
00142
00143 GoodsEntry() :
00144 acceptance_pickup(0),
00145 time_since_pickup(255),
00146 rating(INITIAL_STATION_RATING),
00147 last_speed(0),
00148 last_age(255),
00149 link_graph(INVALID_LINK_GRAPH),
00150 node(INVALID_NODE),
00151 max_waiting_cargo(0)
00152 {}
00153
00154 byte acceptance_pickup;
00155
00161 byte time_since_pickup;
00162
00163 byte rating;
00164
00174 byte last_speed;
00175
00180 byte last_age;
00181
00182 byte amount_fract;
00183 StationCargoList cargo;
00184
00185 LinkGraphID link_graph;
00186 NodeID node;
00187 FlowStatMap flows;
00188 uint max_waiting_cargo;
00189
00195 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00196
00201 inline bool HasRating() const
00202 {
00203 return HasBit(this->acceptance_pickup, GES_PICKUP);
00204 }
00205
00206 uint GetSumFlowVia(StationID via) const;
00207
00214 inline StationID GetVia(StationID source) const
00215 {
00216 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00217 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00218 }
00219
00228 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00229 {
00230 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00231 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00232 }
00233 };
00234
00236 struct Airport : public TileArea {
00237 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00238
00239 uint64 flags;
00240 byte type;
00241 byte layout;
00242 Direction rotation;
00243
00244 PersistentStorage *psa;
00245
00251 const AirportSpec *GetSpec() const
00252 {
00253 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00254 return AirportSpec::Get(this->type);
00255 }
00256
00263 const AirportFTAClass *GetFTA() const
00264 {
00265 return this->GetSpec()->fsm;
00266 }
00267
00269 inline bool HasHangar() const
00270 {
00271 return this->GetSpec()->nof_depots > 0;
00272 }
00273
00282 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00283 {
00284 const AirportSpec *as = this->GetSpec();
00285 switch (this->rotation) {
00286 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00287
00288 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00289
00290 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00291
00292 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00293
00294 default: NOT_REACHED();
00295 }
00296 }
00297
00304 inline TileIndex GetHangarTile(uint hangar_num) const
00305 {
00306 const AirportSpec *as = this->GetSpec();
00307 for (uint i = 0; i < as->nof_depots; i++) {
00308 if (as->depot_table[i].hangar_num == hangar_num) {
00309 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00310 }
00311 }
00312 NOT_REACHED();
00313 }
00314
00321 inline Direction GetHangarExitDirection(TileIndex tile) const
00322 {
00323 const AirportSpec *as = this->GetSpec();
00324 const HangarTileTable *htt = GetHangarDataByTile(tile);
00325 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00326 }
00327
00334 inline uint GetHangarNum(TileIndex tile) const
00335 {
00336 const HangarTileTable *htt = GetHangarDataByTile(tile);
00337 return htt->hangar_num;
00338 }
00339
00341 inline uint GetNumHangars() const
00342 {
00343 uint num = 0;
00344 uint counted = 0;
00345 const AirportSpec *as = this->GetSpec();
00346 for (uint i = 0; i < as->nof_depots; i++) {
00347 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00348 num++;
00349 SetBit(counted, as->depot_table[i].hangar_num);
00350 }
00351 }
00352 return num;
00353 }
00354
00355 private:
00362 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00363 {
00364 const AirportSpec *as = this->GetSpec();
00365 for (uint i = 0; i < as->nof_depots; i++) {
00366 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00367 return as->depot_table + i;
00368 }
00369 }
00370 NOT_REACHED();
00371 }
00372 };
00373
00374 typedef SmallVector<Industry *, 2> IndustryVector;
00375
00377 struct Station FINAL : SpecializedStation<Station, false> {
00378 public:
00379 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00380 {
00381 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00382 }
00383
00384 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00385
00386 RoadStop *bus_stops;
00387 TileArea bus_station;
00388 RoadStop *truck_stops;
00389 TileArea truck_station;
00390
00391 Airport airport;
00392 TileIndex dock_tile;
00393
00394 IndustryType indtype;
00395
00396 StationHadVehicleOfTypeByte had_vehicle_of_type;
00397
00398 byte time_since_load;
00399 byte time_since_unload;
00400
00401 byte last_vehicle_type;
00402 std::list<Vehicle *> loading_vehicles;
00403 GoodsEntry goods[NUM_CARGO];
00404 uint32 always_accepted;
00405
00406 IndustryVector industries_near;
00407
00408 Station(TileIndex tile = INVALID_TILE);
00409 ~Station();
00410
00411 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00412
00413 void MarkTilesDirty(bool cargo_change) const;
00414
00415 void UpdateVirtCoord();
00416
00417 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00418 uint GetPlatformLength(TileIndex tile) const;
00419 void RecomputeIndustriesNear();
00420 static void RecomputeIndustriesNearForAll();
00421
00422 uint GetCatchmentRadius() const;
00423 Rect GetCatchmentRect() const;
00424
00425 inline bool TileBelongsToRailStation(TileIndex tile) const
00426 {
00427 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00428 }
00429
00430 inline bool TileBelongsToAirport(TileIndex tile) const
00431 {
00432 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00433 }
00434
00435 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00436
00437 void GetTileArea(TileArea *ta, StationType type) const;
00438
00439 void RunAverages();
00440 };
00441
00442 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00443
00445 class AirportTileIterator : public OrthogonalTileIterator {
00446 private:
00447 const Station *st;
00448
00449 public:
00454 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00455 {
00456 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00457 }
00458
00459 inline TileIterator& operator ++()
00460 {
00461 (*this).OrthogonalTileIterator::operator++();
00462 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00463 (*this).OrthogonalTileIterator::operator++();
00464 }
00465 return *this;
00466 }
00467
00468 virtual TileIterator *Clone() const
00469 {
00470 return new AirportTileIterator(*this);
00471 }
00472 };
00473
00474 #endif