# station_base.h

Go to the documentation of this file.

    00001 /* $Id$ */
    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 "moving_average.h"
    00023 #include <map>
    00024
    00025 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
    00026 extern StationPool _station_pool;
    00027
    00028 static const byte INITIAL_STATION_RATING = 175;
    00029
    00038 class LinkStat : private MovingAverage<uint> {
    00039 private:
    00044   uint capacity;
    00045
    00049   uint timeout;
    00050
    00055   uint usage;
    00056
    00057 public:
    00061   static const uint MIN_AVERAGE_LENGTH = 48;
    00062
    00063   friend const SaveLoad *GetLinkStatDesc();
    00064
    00068   LinkStat() : MovingAverage<uint>(0) {NOT_REACHED();}
    00069
    00076   inline LinkStat(uint distance, uint capacity = 1, uint usage = 0) :
    00077     MovingAverage<uint>(distance), capacity(capacity), timeout(distance), usage(usage)
    00078   {
    00079     assert(this->usage <= this->capacity);
    00080   }
    00081
    00085   inline void Clear()
    00086   {
    00087     this->capacity = 1;
    00088     this->usage = 0;
    00089     this->timeout = this->length;
    00090   }
    00091
    00095   inline void Decrease()
    00096   {
    00097     this->MovingAverage<uint>::Decrease(this->usage);
    00098     this->timeout = this->timeout * MIN_AVERAGE_LENGTH / (MIN_AVERAGE_LENGTH + 1);
    00099     this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), (uint)1);
    00100     assert(this->usage <= this->capacity);
    00101   }
    00102
    00107   inline uint Capacity() const
    00108   {
    00109     return this->MovingAverage<uint>::Monthly(this->capacity);
    00110   }
    00111
    00116   inline uint Usage() const
    00117   {
    00118     return this->MovingAverage<uint>::Monthly(this->usage);
    00119   }
    00120
    00126   inline void Increase(uint capacity, uint usage)
    00127   {
    00128     this->timeout = this->length;
    00129     this->capacity += capacity;
    00130     this->usage += usage;
    00131     assert(this->usage <= this->capacity);
    00132   }
    00133
    00137   inline void Refresh(uint min_capacity)
    00138   {
    00139     this->capacity = max(this->capacity, min_capacity);
    00140     this->timeout = this->length;
    00141   }
    00142
    00147   inline bool IsValid() const
    00148   {
    00149     return this->timeout > 0;
    00150   }
    00151 };
    00152
    00160 class FlowStat {
    00161 public:
    00162   typedef std::map<uint32, StationID> SharesMap;
    00163
    00164   inline FlowStat() {NOT_REACHED();}
    00165
    00166   inline FlowStat(StationID st, uint flow)
    00167   {
    00168     assert(flow > 0);
    00169     this->shares[flow] = st;
    00170   }
    00171
    00177   inline void AddShare(StationID st, uint flow)
    00178   {
    00179     assert(flow > 0);
    00180     this->shares[(--this->shares.end())->first + flow] = st;
    00181   }
    00182
    00183   uint GetShare(StationID st) const;
    00184
    00185   void EraseShare(StationID st);
    00186
    00187   inline const SharesMap *GetShares() const {return &this->shares;}
    00188
    00196   inline StationID GetVia() const
    00197   {
    00198     assert(!this->shares.empty());
    00199     return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
    00200   }
    00201
    00202   StationID GetVia(StationID excluded) const;
    00203
    00204 private:
    00205   SharesMap shares;
    00206 };
    00207
    00208 typedef std::map<StationID, LinkStat> LinkStatMap;
    00209 typedef std::map<StationID, FlowStat> FlowStatMap;
    00210
    00211 uint GetMovingAverageLength(const Station *from, const Station *to);
    00212
    00216 struct GoodsEntry {
    00218   enum GoodsEntryStatus {
    00219     GES_ACCEPTANCE,
    00220     GES_PICKUP,
    00221     GES_EVER_ACCEPTED,
    00222     GES_LAST_MONTH,
    00223     GES_CURRENT_MONTH,
    00224     GES_ACCEPTED_BIGTICK,
    00225   };
    00226
    00227   GoodsEntry() :
    00228     acceptance_pickup(0),
    00229     days_since_pickup(255),
    00230     rating(INITIAL_STATION_RATING),
    00231     last_speed(0),
    00232     last_age(255),
    00233     supply(0),
    00234     supply_new(0),
    00235     last_component(INVALID_LINKGRAPH_COMPONENT),
    00236     max_waiting_cargo(0)
    00237   {}
    00238
    00239   byte acceptance_pickup;
    00240   byte days_since_pickup;
    00241   byte rating;
    00242   byte last_speed;
    00243   byte last_age;
    00244   byte amount_fract;
    00245   StationCargoList cargo;
    00246   uint supply;
    00247   uint supply_new;
    00248   FlowStatMap flows;
    00249   LinkStatMap link_stats;
    00250   LinkGraphComponentID last_component;
    00251   uint max_waiting_cargo;
    00252
    00253   uint GetSumFlowVia(StationID via) const;
    00254
    00255   inline StationID GetVia(StationID source, StationID excluded = INVALID_STATION) const
    00256   {
    00257     FlowStatMap::const_iterator flow_it(this->flows.find(source));
    00258     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded) : INVALID_STATION;
    00259   }
    00260 };
    00261
    00263 struct Airport : public TileArea {
    00264   Airport() : TileArea(INVALID_TILE, 0, 0) {}
    00265
    00266   uint64 flags;
    00267   byte type;
    00268   byte layout;
    00269   Direction rotation;
    00270
    00271   PersistentStorage *psa;
    00272
    00278   const AirportSpec *GetSpec() const
    00279   {
    00280     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
    00281     return AirportSpec::Get(this->type);
    00282   }
    00283
    00290   const AirportFTAClass *GetFTA() const
    00291   {
    00292     return this->GetSpec()->fsm;
    00293   }
    00294
    00296   inline bool HasHangar() const
    00297   {
    00298     return this->GetSpec()->nof_depots > 0;
    00299   }
    00300
    00309   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
    00310   {
    00311     const AirportSpec *as = this->GetSpec();
    00312     switch (this->rotation) {
    00313       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
    00314
    00315       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
    00316
    00317       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
    00318
    00319       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
    00320
    00321       default: NOT_REACHED();
    00322     }
    00323   }
    00324
    00331   inline TileIndex GetHangarTile(uint hangar_num) const
    00332   {
    00333     const AirportSpec *as = this->GetSpec();
    00334     for (uint i = 0; i < as->nof_depots; i++) {
    00335       if (as->depot_table[i].hangar_num == hangar_num) {
    00336         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
    00337       }
    00338     }
    00339     NOT_REACHED();
    00340   }
    00341
    00348   inline Direction GetHangarExitDirection(TileIndex tile) const
    00349   {
    00350     const AirportSpec *as = this->GetSpec();
    00351     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00352     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
    00353   }
    00354
    00361   inline uint GetHangarNum(TileIndex tile) const
    00362   {
    00363     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00364     return htt->hangar_num;
    00365   }
    00366
    00368   inline uint GetNumHangars() const
    00369   {
    00370     uint num = 0;
    00371     uint counted = 0;
    00372     const AirportSpec *as = this->GetSpec();
    00373     for (uint i = 0; i < as->nof_depots; i++) {
    00374       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
    00375         num++;
    00376         SetBit(counted, as->depot_table[i].hangar_num);
    00377       }
    00378     }
    00379     return num;
    00380   }
    00381
    00382 private:
    00389   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
    00390   {
    00391     const AirportSpec *as = this->GetSpec();
    00392     for (uint i = 0; i < as->nof_depots; i++) {
    00393       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
    00394         return as->depot_table + i;
    00395       }
    00396     }
    00397     NOT_REACHED();
    00398   }
    00399 };
    00400
    00401 typedef SmallVector<Industry *, 2> IndustryVector;
    00402
    00404 struct Station FINAL : SpecializedStation<Station, false> {
    00405 public:
    00406   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
    00407   {
    00408     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
    00409   }
    00410
    00411   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
    00412
    00413   RoadStop *bus_stops;
    00414   TileArea bus_station;
    00415   RoadStop *truck_stops;
    00416   TileArea truck_station;
    00417
    00418   Airport airport;
    00419   TileIndex dock_tile;
    00420
    00421   IndustryType indtype;
    00422
    00423   StationHadVehicleOfTypeByte had_vehicle_of_type;
    00424
    00425   byte time_since_load;
    00426   byte time_since_unload;
    00427
    00428   byte last_vehicle_type;
    00429   std::list<Vehicle *> loading_vehicles;
    00430   GoodsEntry goods[NUM_CARGO];
    00431   uint32 always_accepted;
    00432
    00433   IndustryVector industries_near;
    00434
    00435   Station(TileIndex tile = INVALID_TILE);
    00436   ~Station();
    00437
    00438   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
    00439
    00440   void MarkTilesDirty(bool cargo_change) const;
    00441
    00442   void UpdateVirtCoord();
    00443
    00444   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
    00445   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
    00446   void RecomputeIndustriesNear();
    00447   static void RecomputeIndustriesNearForAll();
    00448
    00449   uint GetCatchmentRadius() const;
    00450   Rect GetCatchmentRect() const;
    00451
    00452   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
    00453   {
    00454     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
    00455   }
    00456
    00457   inline bool TileBelongsToAirport(TileIndex tile) const
    00458   {
    00459     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
    00460   }
    00461
    00462   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
    00463
    00464   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
    00465
    00466   void RunAverages();
    00467 };
    00468
    00469 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
    00470
    00472 class AirportTileIterator : public OrthogonalTileIterator {
    00473 private:
    00474   const Station *st;
    00475
    00476 public:
    00481   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
    00482   {
    00483     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
    00484   }
    00485
    00486   inline TileIterator& operator ++()
    00487   {
    00488     (*this).OrthogonalTileIterator::operator++();
    00489     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
    00490       (*this).OrthogonalTileIterator::operator++();
    00491     }
    00492     return *this;
    00493   }
    00494
    00495   virtual TileIterator *Clone() const
    00496   {
    00497     return new AirportTileIterator(*this);
    00498   }
    00499 };
    00500
    00501 #endif /* STATION_BASE_H */