# 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 "base_station_base.h"
    00016 #include "newgrf_airport.h"
    00017 #include "cargopacket.h"
    00018 #include "industry_type.h"
    00019 #include "newgrf_storage.h"
    00020 #include "linkgraph/linkgraph_type.h"
    00021 #include "moving_average.h"
    00022 #include <map>
    00023 #include <set>
    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 frozen;
    00050
    00055   uint usage;
    00056
    00057 public:
    00061   static const uint MIN_AVERAGE_LENGTH = 96;
    00062
    00063   friend const SaveLoad *GetLinkStatDesc();
    00064
    00065   FORCEINLINE LinkStat(uint distance = 1, uint capacity = 0, uint frozen = 0, uint usage = 0) :
    00066     MovingAverage<uint>(distance), capacity(capacity), frozen(frozen), usage(usage) {}
    00067
    00071   FORCEINLINE void Clear()
    00072   {
    00073     this->capacity = 0;
    00074     this->usage = 0;
    00075     this->frozen = 0;
    00076   }
    00077
    00081   FORCEINLINE void Decrease()
    00082   {
    00083     this->MovingAverage<uint>::Decrease(this->usage);
    00084     this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), this->frozen);
    00085   }
    00086
    00091   FORCEINLINE uint Capacity() const
    00092   {
    00093     return this->MovingAverage<uint>::Monthly(this->capacity);
    00094   }
    00095
    00100   FORCEINLINE uint Usage() const
    00101   {
    00102     return this->MovingAverage<uint>::Monthly(this->usage);
    00103   }
    00104
    00109   FORCEINLINE uint Frozen() const
    00110   {
    00111     return this->frozen;
    00112   }
    00113
    00119   FORCEINLINE void Increase(uint capacity, uint usage)
    00120   {
    00121     this->capacity += capacity;
    00122     this->usage += usage;
    00123   }
    00124
    00130   FORCEINLINE void Freeze(uint capacity)
    00131   {
    00132     this->frozen += capacity;
    00133     this->capacity = max(this->frozen, this->capacity);
    00134   }
    00135
    00140   FORCEINLINE void Unfreeze(uint capacity)
    00141   {
    00142     this->frozen -= capacity;
    00143   }
    00144
    00148   FORCEINLINE void Unfreeze()
    00149   {
    00150     this->frozen = 0;
    00151   }
    00152
    00158   FORCEINLINE bool IsNull() const
    00159   {
    00160     return this->capacity == 0;
    00161   }
    00162 };
    00163
    00167 class FlowStat : private MovingAverage<uint> {
    00168 private:
    00169   uint planned;
    00170   uint sent;
    00171   StationID via;
    00172
    00173 public:
    00174   friend const SaveLoad *GetFlowStatDesc();
    00175
    00183   FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
    00184     MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
    00185
    00191   FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
    00192     MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
    00193
    00197   FORCEINLINE FlowStat GetDecreasedCopy() const
    00198   {
    00199     FlowStat ret(this->length, this->via, this->planned, this->sent);
    00200     this->MovingAverage<uint>::Decrease(ret.sent);
    00201     return ret;
    00202   }
    00203
    00208   FORCEINLINE void Increase(uint sent)
    00209   {
    00210     this->sent += sent;
    00211   }
    00212
    00217   FORCEINLINE uint Sent() const
    00218   {
    00219     return this->MovingAverage<uint>::Monthly(sent);
    00220   }
    00221
    00226   FORCEINLINE uint Planned() const
    00227   {
    00228     return this->planned;
    00229   }
    00230
    00235   FORCEINLINE StationID Via() const
    00236   {
    00237     return this->via;
    00238   }
    00239
    00244   struct Comparator {
    00252     bool operator()(const FlowStat &x, const FlowStat &y) const {
    00253       int diff_x = (int)x.Planned() - (int)x.Sent();
    00254       int diff_y = (int)y.Planned() - (int)y.Sent();
    00255       if (diff_x != diff_y) {
    00256         return diff_x > diff_y;
    00257       } else {
    00258         return x.Via() > y.Via();
    00259       }
    00260     }
    00261   };
    00262
    00268   FORCEINLINE FlowStat &operator+=(const FlowStat &other)
    00269   {
    00270     assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
    00271     if (other.via != INVALID_STATION) this->via = other.via;
    00272     this->planned += other.planned;
    00273     uint sent = this->sent + other.sent;
    00274     if (sent > 0) {
    00275       this->length = (this->length * this->sent + other.length * other.sent) / sent;
    00276       assert(this->length > 0);
    00277     }
    00278     this->sent = sent;
    00279     return *this;
    00280   }
    00281
    00285   FORCEINLINE void Clear()
    00286   {
    00287     this->planned = 0;
    00288     this->sent = 0;
    00289     this->via = INVALID_STATION;
    00290   }
    00291 };
    00292
    00293 typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet;
    00294
    00295 typedef std::map<StationID, LinkStat> LinkStatMap;
    00296 typedef std::map<StationID, FlowStatSet> FlowStatMap;
    00297
    00298 uint GetMovingAverageLength(const Station *from, const Station *to);
    00299
    00303 struct GoodsEntry {
    00305   enum GoodsEntryStatus {
    00306     GES_ACCEPTANCE,
    00307     GES_PICKUP,
    00308     GES_EVER_ACCEPTED,
    00309     GES_LAST_MONTH,
    00310     GES_CURRENT_MONTH,
    00311     GES_ACCEPTED_BIGTICK,
    00312   };
    00313
    00314   GoodsEntry() :
    00315     acceptance_pickup(0),
    00316     days_since_pickup(255),
    00317     rating(INITIAL_STATION_RATING),
    00318     last_speed(0),
    00319     last_age(255),
    00320     supply(0),
    00321     supply_new(0),
    00322     last_component(INVALID_LINKGRAPH_COMPONENT),
    00323     max_waiting_cargo(0)
    00324   {}
    00325
    00326   byte acceptance_pickup;
    00327   byte days_since_pickup;
    00328   byte rating;
    00329   byte last_speed;
    00330   byte last_age;
    00331   byte amount_fract;
    00332   StationCargoList cargo;
    00333   uint supply;
    00334   uint supply_new;
    00335   FlowStatMap flows;
    00336   LinkStatMap link_stats;
    00337   LinkGraphComponentID last_component;
    00338   uint max_waiting_cargo;
    00339
    00340   FlowStat GetSumFlowVia(StationID via) const;
    00341
    00342   void UpdateFlowStats(StationID source, uint count, StationID next);
    00343   void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
    00344   void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
    00345
    00346   StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
    00347 };
    00348
    00350 struct Airport : public TileArea {
    00351   typedef PersistentStorageArray<int32, 16> PersistentStorage;
    00352
    00353   Airport() : TileArea(INVALID_TILE, 0, 0) {}
    00354
    00355   uint64 flags;
    00356   byte type;
    00357   byte layout;
    00358   Direction rotation;
    00359   PersistentStorage psa;
    00360
    00366   const AirportSpec *GetSpec() const
    00367   {
    00368     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
    00369     return AirportSpec::Get(this->type);
    00370   }
    00371
    00378   const AirportFTAClass *GetFTA() const
    00379   {
    00380     return this->GetSpec()->fsm;
    00381   }
    00382
    00384   FORCEINLINE bool HasHangar() const
    00385   {
    00386     return this->GetSpec()->nof_depots > 0;
    00387   }
    00388
    00397   FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
    00398   {
    00399     const AirportSpec *as = this->GetSpec();
    00400     switch (this->rotation) {
    00401       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
    00402
    00403       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
    00404
    00405       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
    00406
    00407       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
    00408
    00409       default: NOT_REACHED();
    00410     }
    00411   }
    00412
    00419   FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
    00420   {
    00421     const AirportSpec *as = this->GetSpec();
    00422     for (uint i = 0; i < as->nof_depots; i++) {
    00423       if (as->depot_table[i].hangar_num == hangar_num) {
    00424         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
    00425       }
    00426     }
    00427     NOT_REACHED();
    00428   }
    00429
    00436   FORCEINLINE uint GetHangarNum(TileIndex tile) const
    00437   {
    00438     const AirportSpec *as = this->GetSpec();
    00439     for (uint i = 0; i < as->nof_depots; i++) {
    00440       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
    00441         return as->depot_table[i].hangar_num;
    00442       }
    00443     }
    00444     NOT_REACHED();
    00445   }
    00446
    00448   FORCEINLINE uint GetNumHangars() const
    00449   {
    00450     uint num = 0;
    00451     uint counted = 0;
    00452     const AirportSpec *as = this->GetSpec();
    00453     for (uint i = 0; i < as->nof_depots; i++) {
    00454       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
    00455         num++;
    00456         SetBit(counted, as->depot_table[i].hangar_num);
    00457       }
    00458     }
    00459     return num;
    00460   }
    00461 };
    00462
    00463 typedef SmallVector<Industry *, 2> IndustryVector;
    00464
    00466 struct Station : SpecializedStation<Station, false> {
    00467 public:
    00468   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
    00469   {
    00470     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
    00471   }
    00472
    00473   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
    00474
    00475   RoadStop *bus_stops;
    00476   TileArea bus_station;
    00477   RoadStop *truck_stops;
    00478   TileArea truck_station;
    00479
    00480   Airport airport;
    00481   TileIndex dock_tile;
    00482
    00483   IndustryType indtype;
    00484
    00485   StationHadVehicleOfTypeByte had_vehicle_of_type;
    00486
    00487   byte time_since_load;
    00488   byte time_since_unload;
    00489
    00490   byte last_vehicle_type;
    00491   std::list<Vehicle *> loading_vehicles;
    00492   GoodsEntry goods[NUM_CARGO];
    00493   uint32 always_accepted;
    00494
    00495   IndustryVector industries_near;
    00496
    00497   Station(TileIndex tile = INVALID_TILE);
    00498   ~Station();
    00499
    00500   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
    00501
    00502   void MarkTilesDirty(bool cargo_change) const;
    00503
    00504   void UpdateVirtCoord();
    00505
    00506   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
    00507   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
    00508   void RecomputeIndustriesNear();
    00509   static void RecomputeIndustriesNearForAll();
    00510
    00511   uint GetCatchmentRadius() const;
    00512   Rect GetCatchmentRect() const;
    00513
    00514   /* virtual */ FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
    00515   {
    00516     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
    00517   }
    00518
    00519   FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
    00520   {
    00521     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
    00522   }
    00523
    00524   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
    00525
    00526   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
    00527
    00528   void RunAverages();
    00529 };
    00530
    00531 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
    00532
    00533 #endif /* STATION_BASE_H */