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 */