# 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 <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
    00044 class LinkStat {
    00045 private:
    00049   uint distance;
    00050
    00055   uint capacity;
    00056
    00060   uint timeout;
    00061
    00066   uint usage;
    00067
    00068 public:
    00069   static const uint MIN_DISTANCE = 48;
    00070   static const uint MOVING_AVERAGE_LENGTH = 30;
    00071
    00072   friend const SaveLoad *GetLinkStatDesc();
    00073
    00077   LinkStat() {NOT_REACHED();}
    00078
    00085   inline LinkStat(uint distance, uint capacity = 1, uint usage = 0) :
    00086     distance(distance), capacity(capacity), timeout(distance), usage(usage)
    00087   {
    00088     assert(this->distance > 0);
    00089     assert(this->usage <= this->capacity);
    00090   }
    00091
    00095   inline void Clear()
    00096   {
    00097     this->capacity = 1;
    00098     this->usage = 0;
    00099     this->timeout = this->distance;
    00100   }
    00101
    00105   inline void Decrease()
    00106   {
    00107     this->usage = this->usage * this->distance / (this->distance + 1);
    00108     this->timeout = this->timeout * MIN_DISTANCE / (MIN_DISTANCE + 1);
    00109     this->capacity = max(this->capacity * this->distance / (this->distance + 1), (uint)1);
    00110     assert(this->usage <= this->capacity);
    00111   }
    00112
    00117   inline uint Capacity() const
    00118   {
    00119     return this->capacity * LinkStat::MOVING_AVERAGE_LENGTH / this->distance;
    00120   }
    00121
    00126   inline uint Usage() const
    00127   {
    00128     return this->usage * LinkStat::MOVING_AVERAGE_LENGTH / this->distance;
    00129   }
    00130
    00136   inline void Increase(uint capacity, uint usage)
    00137   {
    00138     this->timeout = this->distance;
    00139     this->capacity += capacity;
    00140     this->usage += usage;
    00141     assert(this->usage <= this->capacity);
    00142   }
    00143
    00147   inline void Refresh(uint min_capacity)
    00148   {
    00149     this->capacity = max(this->capacity, min_capacity);
    00150     this->timeout = this->distance;
    00151   }
    00152
    00157   inline bool IsValid() const
    00158   {
    00159     return this->timeout > 0;
    00160   }
    00161 };
    00162
    00170 class FlowStat {
    00171 public:
    00172   typedef std::map<uint32, StationID> SharesMap;
    00173
    00174   inline FlowStat() {NOT_REACHED();}
    00175
    00176   inline FlowStat(StationID st, uint flow)
    00177   {
    00178     assert(flow > 0);
    00179     this->shares[flow] = st;
    00180   }
    00181
    00187   inline void AddShare(StationID st, uint flow)
    00188   {
    00189     assert(flow > 0);
    00190     this->shares[(--this->shares.end())->first + flow] = st;
    00191   }
    00192
    00193   uint GetShare(StationID st) const;
    00194
    00195   void EraseShare(StationID st);
    00196
    00197   inline const SharesMap *GetShares() const {return &this->shares;}
    00198
    00206   inline StationID GetVia() const
    00207   {
    00208     assert(!this->shares.empty());
    00209     return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
    00210   }
    00211
    00212   StationID GetVia(StationID excluded) const;
    00213
    00214 private:
    00215   SharesMap shares;
    00216 };
    00217
    00218 typedef std::map<StationID, LinkStat> LinkStatMap;
    00219 typedef std::map<StationID, FlowStat> FlowStatMap;
    00220
    00221 uint GetMovingAverageLength(const Station *from, const Station *to);
    00222
    00226 struct GoodsEntry {
    00228   enum GoodsEntryStatus {
    00233     GES_ACCEPTANCE,
    00234
    00242     GES_PICKUP,
    00243
    00248     GES_EVER_ACCEPTED,
    00249
    00254     GES_LAST_MONTH,
    00255
    00260     GES_CURRENT_MONTH,
    00261
    00266     GES_ACCEPTED_BIGTICK,
    00267   };
    00268
    00269   GoodsEntry() :
    00270     acceptance_pickup(0),
    00271     time_since_pickup(255),
    00272     rating(INITIAL_STATION_RATING),
    00273     last_speed(0),
    00274     last_age(255),
    00275     supply(0),
    00276     supply_new(0),
    00277     last_component(INVALID_LINKGRAPH_COMPONENT),
    00278     max_waiting_cargo(0)
    00279   {}
    00280
    00281   byte acceptance_pickup;
    00282
    00288   byte time_since_pickup;
    00289
    00290   byte rating;
    00291
    00301   byte last_speed;
    00302
    00307   byte last_age;
    00308
    00309   byte amount_fract;
    00310   StationCargoList cargo;
    00311
    00312   uint supply;
    00313   uint supply_new;
    00314   FlowStatMap flows;
    00315   LinkStatMap link_stats;
    00316
    00317   LinkGraphComponentID last_component;
    00318   uint max_waiting_cargo;
    00319
    00325   bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
    00326   uint GetSumFlowVia(StationID via) const;
    00327
    00336   inline StationID GetVia(StationID source, StationID excluded = INVALID_STATION) const
    00337   {
    00338     FlowStatMap::const_iterator flow_it(this->flows.find(source));
    00339     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded) : INVALID_STATION;
    00340   }
    00341 };
    00342
    00344 struct Airport : public TileArea {
    00345   Airport() : TileArea(INVALID_TILE, 0, 0) {}
    00346
    00347   uint64 flags;
    00348   byte type;
    00349   byte layout;
    00350   Direction rotation;
    00351
    00352   PersistentStorage *psa;
    00353
    00359   const AirportSpec *GetSpec() const
    00360   {
    00361     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
    00362     return AirportSpec::Get(this->type);
    00363   }
    00364
    00371   const AirportFTAClass *GetFTA() const
    00372   {
    00373     return this->GetSpec()->fsm;
    00374   }
    00375
    00377   inline bool HasHangar() const
    00378   {
    00379     return this->GetSpec()->nof_depots > 0;
    00380   }
    00381
    00390   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
    00391   {
    00392     const AirportSpec *as = this->GetSpec();
    00393     switch (this->rotation) {
    00394       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
    00395
    00396       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
    00397
    00398       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
    00399
    00400       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
    00401
    00402       default: NOT_REACHED();
    00403     }
    00404   }
    00405
    00412   inline TileIndex GetHangarTile(uint hangar_num) const
    00413   {
    00414     const AirportSpec *as = this->GetSpec();
    00415     for (uint i = 0; i < as->nof_depots; i++) {
    00416       if (as->depot_table[i].hangar_num == hangar_num) {
    00417         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
    00418       }
    00419     }
    00420     NOT_REACHED();
    00421   }
    00422
    00429   inline Direction GetHangarExitDirection(TileIndex tile) const
    00430   {
    00431     const AirportSpec *as = this->GetSpec();
    00432     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00433     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
    00434   }
    00435
    00442   inline uint GetHangarNum(TileIndex tile) const
    00443   {
    00444     const HangarTileTable *htt = GetHangarDataByTile(tile);
    00445     return htt->hangar_num;
    00446   }
    00447
    00449   inline uint GetNumHangars() const
    00450   {
    00451     uint num = 0;
    00452     uint counted = 0;
    00453     const AirportSpec *as = this->GetSpec();
    00454     for (uint i = 0; i < as->nof_depots; i++) {
    00455       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
    00456         num++;
    00457         SetBit(counted, as->depot_table[i].hangar_num);
    00458       }
    00459     }
    00460     return num;
    00461   }
    00462
    00463 private:
    00470   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
    00471   {
    00472     const AirportSpec *as = this->GetSpec();
    00473     for (uint i = 0; i < as->nof_depots; i++) {
    00474       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
    00475         return as->depot_table + i;
    00476       }
    00477     }
    00478     NOT_REACHED();
    00479   }
    00480 };
    00481
    00482 typedef SmallVector<Industry *, 2> IndustryVector;
    00483
    00485 struct Station FINAL : SpecializedStation<Station, false> {
    00486 public:
    00487   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
    00488   {
    00489     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
    00490   }
    00491
    00492   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
    00493
    00494   RoadStop *bus_stops;
    00495   TileArea bus_station;
    00496   RoadStop *truck_stops;
    00497   TileArea truck_station;
    00498
    00499   Airport airport;
    00500   TileIndex dock_tile;
    00501
    00502   IndustryType indtype;
    00503
    00504   StationHadVehicleOfTypeByte had_vehicle_of_type;
    00505
    00506   byte time_since_load;
    00507   byte time_since_unload;
    00508
    00509   byte last_vehicle_type;
    00510   std::list<Vehicle *> loading_vehicles;
    00511   GoodsEntry goods[NUM_CARGO];
    00512   uint32 always_accepted;
    00513
    00514   IndustryVector industries_near;
    00515
    00516   Station(TileIndex tile = INVALID_TILE);
    00517   ~Station();
    00518
    00519   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
    00520
    00521   void MarkTilesDirty(bool cargo_change) const;
    00522
    00523   void UpdateVirtCoord();
    00524
    00525   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
    00526   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
    00527   void RecomputeIndustriesNear();
    00528   static void RecomputeIndustriesNearForAll();
    00529
    00530   uint GetCatchmentRadius() const;
    00531   Rect GetCatchmentRect() const;
    00532
    00533   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
    00534   {
    00535     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
    00536   }
    00537
    00538   inline bool TileBelongsToAirport(TileIndex tile) const
    00539   {
    00540     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
    00541   }
    00542
    00543   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
    00544
    00545   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
    00546
    00547   void RunAverages();
    00548 };
    00549
    00550 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
    00551
    00553 class AirportTileIterator : public OrthogonalTileIterator {
    00554 private:
    00555   const Station *st;
    00556
    00557 public:
    00562   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
    00563   {
    00564     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
    00565   }
    00566
    00567   inline TileIterator& operator ++()
    00568   {
    00569     (*this).OrthogonalTileIterator::operator++();
    00570     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
    00571       (*this).OrthogonalTileIterator::operator++();
    00572     }
    00573     return *this;
    00574   }
    00575
    00576   virtual TileIterator *Clone() const
    00577   {
    00578     return new AirportTileIterator(*this);
    00579   }
    00580 };
    00581
    00582 #endif /* STATION_BASE_H */