# station_base.h

Go to the documentation of this file.

    00001 /* $Id: station_base.h 26596 2014-05-18 11:26:09Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    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
    00045   inline FlowStat() {NOT_REACHED();}
    00046
    00052   inline FlowStat(StationID st, uint flow)
    00053   {
    00054     assert(flow > 0);
    00055     this->shares[flow] = st;
    00056     this->unrestricted = flow;
    00057   }
    00058
    00067   inline void AppendShare(StationID st, uint flow, bool restricted = false)
    00068   {
    00069     assert(flow > 0);
    00070     this->shares[(--this->shares.end())->first + flow] = st;
    00071     if (!restricted) this->unrestricted += flow;
    00072   }
    00073
    00074   uint GetShare(StationID st) const;
    00075
    00076   void ChangeShare(StationID st, int flow);
    00077
    00078   void RestrictShare(StationID st);
    00079
    00080   void ReleaseShare(StationID st);
    00081
    00082   void ScaleToMonthly(uint runtime);
    00083
    00089   inline const SharesMap *GetShares() const { return &this->shares; }
    00090
    00095   inline uint GetUnrestricted() const { return this->unrestricted; }
    00096
    00102   inline void SwapShares(FlowStat &other)
    00103   {
    00104     this->shares.swap(other.shares);
    00105     Swap(this->unrestricted, other.unrestricted);
    00106   }
    00107
    00116   inline StationID GetViaWithRestricted(bool &is_restricted) const
    00117   {
    00118     assert(!this->shares.empty());
    00119     uint rand = RandomRange((--this->shares.end())->first);
    00120     is_restricted = rand >= this->unrestricted;
    00121     return this->shares.upper_bound(rand)->second;
    00122   }
    00123
    00131   inline StationID GetVia() const
    00132   {
    00133     assert(!this->shares.empty());
    00134     return this->unrestricted > 0 ?
    00135         this->shares.upper_bound(RandomRange(this->unrestricted))->second :
    00136         INVALID_STATION;
    00137   }
    00138
    00139   StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
    00140
    00141   void Invalidate();
    00142
    00143 private:
    00144   SharesMap shares;
    00145   uint unrestricted;
    00146 };
    00147
    00149 class FlowStatMap : public std::map<StationID, FlowStat> {
    00150 public:
    00151   void AddFlow(StationID origin, StationID via, uint amount);
    00152   void PassOnFlow(StationID origin, StationID via, uint amount);
    00153   StationIDStack DeleteFlows(StationID via);
    00154   void RestrictFlows(StationID via);
    00155   void ReleaseFlows(StationID via);
    00156   void FinalizeLocalConsumption(StationID self);
    00157 };
    00158
    00162 struct GoodsEntry {
    00164   enum GoodsEntryStatus {
    00169     GES_ACCEPTANCE,
    00170
    00178     GES_RATING,
    00179
    00184     GES_EVER_ACCEPTED,
    00185
    00190     GES_LAST_MONTH,
    00191
    00196     GES_CURRENT_MONTH,
    00197
    00202     GES_ACCEPTED_BIGTICK,
    00203   };
    00204
    00205   GoodsEntry() :
    00206     status(0),
    00207     time_since_pickup(255),
    00208     rating(INITIAL_STATION_RATING),
    00209     last_speed(0),
    00210     last_age(255),
    00211     amount_fract(0),
    00212     link_graph(INVALID_LINK_GRAPH),
    00213     node(INVALID_NODE),
    00214     max_waiting_cargo(0)
    00215   {}
    00216
    00217   byte status;
    00218
    00224   byte time_since_pickup;
    00225
    00226   byte rating;
    00227
    00237   byte last_speed;
    00238
    00243   byte last_age;
    00244
    00245   byte amount_fract;
    00246   StationCargoList cargo;
    00247
    00248   LinkGraphID link_graph;
    00249   NodeID node;
    00250   FlowStatMap flows;
    00251   uint max_waiting_cargo;
    00252
    00258   bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
    00259
    00264   inline bool HasRating() const
    00265   {
    00266     return HasBit(this->status, GES_RATING);
    00267   }
    00268
    00269   uint GetSumFlowVia(StationID via) const;
    00270
    00276   inline StationID GetVia(StationID source) const
    00277   {
    00278     FlowStatMap::const_iterator flow_it(this->flows.find(source));
    00279     return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
    00280   }
    00281
    00290   inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
    00291   {
    00292     FlowStatMap::const_iterator flow_it(this->flows.find(source));
    00293     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
    00294   }
    00295 };
    00296
    00298 struct Airport : public TileArea {
    00299   Airport() : TileArea(INVALID_TILE, 0, 0) {}
    00300
    00301   uint64 flags;
    00302   byte type;
    00303   byte layout;
    00304   DirectionByte rotation;
    00305
    00306   PersistentStorage *psa;
    00307
    00313   const AirportSpec *GetSpec() const
    00314   {
    00315     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
    00316     return AirportSpec::Get(this->type);
    00317   }
    00318
    00325   const AirportFTAClass *GetFTA() const
    00326   {
    00327     return this->GetSpec()->fsm;
    00328   }
    00329
    00331   inline bool HasHangar() const
    00332   {
    00333     return this->GetSpec()->nof_depots > 0;
    00334   }
    00335
    00344   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
    00345   {
    00346     const AirportSpec *as = this->GetSpec();
    00347     switch (this->rotation) {
    00348       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
    00349
    00350       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
    00351
    00352       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
    00353
    00354       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
    00355
    00356       default: NOT_REACHED();
    00357     }
    00358   }
    00359
    00366   inline TileIndex GetHangarTile(uint hangar_num) const
    00367   {
    00368     const AirportSpec *as = this->GetSpec();
    00369     for (uint i = 0; i < as->nof_depots; i++) {
    00370       if (as->depot_table[i].hangar_num == hangar_num) {
    00371         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
    00372       }
    00373     }
    00374     NOT_REACHED();
    00375   }
    00376
    00383   inline Direction GetHangarExitDirection(TileIndex tile) const
    00384   {
    00385     const AirportSpec *as = this->GetSpec();
    00386     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00387     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
    00388   }
    00389
    00396   inline uint GetHangarNum(TileIndex tile) const
    00397   {
    00398     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00399     return htt->hangar_num;
    00400   }
    00401
    00403   inline uint GetNumHangars() const
    00404   {
    00405     uint num = 0;
    00406     uint counted = 0;
    00407     const AirportSpec *as = this->GetSpec();
    00408     for (uint i = 0; i < as->nof_depots; i++) {
    00409       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
    00410         num++;
    00411         SetBit(counted, as->depot_table[i].hangar_num);
    00412       }
    00413     }
    00414     return num;
    00415   }
    00416
    00417 private:
    00424   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
    00425   {
    00426     const AirportSpec *as = this->GetSpec();
    00427     for (uint i = 0; i < as->nof_depots; i++) {
    00428       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
    00429         return as->depot_table + i;
    00430       }
    00431     }
    00432     NOT_REACHED();
    00433   }
    00434 };
    00435
    00436 typedef SmallVector<Industry *, 2> IndustryVector;
    00437
    00439 struct Station FINAL : SpecializedStation<Station, false> {
    00440 public:
    00441   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
    00442   {
    00443     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
    00444   }
    00445
    00446   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
    00447
    00448   RoadStop *bus_stops;
    00449   TileArea bus_station;
    00450   RoadStop *truck_stops;
    00451   TileArea truck_station;
    00452
    00453   Airport airport;
    00454   TileIndex dock_tile;
    00455
    00456   IndustryType indtype;
    00457
    00458   StationHadVehicleOfTypeByte had_vehicle_of_type;
    00459
    00460   byte time_since_load;
    00461   byte time_since_unload;
    00462
    00463   byte last_vehicle_type;
    00464   std::list<Vehicle *> loading_vehicles;
    00465   GoodsEntry goods[NUM_CARGO];
    00466   uint32 always_accepted;
    00467
    00468   IndustryVector industries_near;
    00469
    00470   Station(TileIndex tile = INVALID_TILE);
    00471   ~Station();
    00472
    00473   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
    00474
    00475   void MarkTilesDirty(bool cargo_change) const;
    00476
    00477   void UpdateVirtCoord();
    00478
    00479   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
    00480   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
    00481   void RecomputeIndustriesNear();
    00482   static void RecomputeIndustriesNearForAll();
    00483
    00484   uint GetCatchmentRadius() const;
    00485   Rect GetCatchmentRect() const;
    00486
    00487   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
    00488   {
    00489     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
    00490   }
    00491
    00492   inline bool TileBelongsToAirport(TileIndex tile) const
    00493   {
    00494     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
    00495   }
    00496
    00497   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
    00498
    00499   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
    00500 };
    00501
    00502 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
    00503
    00505 class AirportTileIterator : public OrthogonalTileIterator {
    00506 private:
    00507   const Station *st;
    00508
    00509 public:
    00514   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
    00515   {
    00516     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
    00517   }
    00518
    00519   inline TileIterator& operator ++()
    00520   {
    00521     (*this).OrthogonalTileIterator::operator++();
    00522     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
    00523       (*this).OrthogonalTileIterator::operator++();
    00524     }
    00525     return *this;
    00526   }
    00527
    00528   virtual TileIterator *Clone() const
    00529   {
    00530     return new AirportTileIterator(*this);
    00531   }
    00532 };
    00533
    00534 #endif /* STATION_BASE_H */