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 "linkgraph/linkgraph_type.h"
00020 #include "newgrf_storage.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 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   FORCEINLINE 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   FORCEINLINE void Clear()
00086   {
00087     this->capacity = 1;
00088     this->usage = 0;
00089     this->timeout = this->length;
00090   }
00091 
00095   FORCEINLINE 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   FORCEINLINE uint Capacity() const
00108   {
00109     return this->MovingAverage<uint>::Monthly(this->capacity);
00110   }
00111 
00116   FORCEINLINE uint Usage() const
00117   {
00118     return this->MovingAverage<uint>::Monthly(this->usage);
00119   }
00120 
00126   FORCEINLINE 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   FORCEINLINE void Refresh(uint min_capacity)
00138   {
00139     this->capacity = max(this->capacity, min_capacity);
00140     this->timeout = this->length;
00141   }
00142 
00147   FORCEINLINE bool IsValid() const
00148   {
00149     return this->timeout > 0;
00150   }
00151 };
00152 
00156 class FlowStat : private MovingAverage<uint> {
00157 private:
00158   uint planned;  
00159   uint sent;     
00160   StationID via; 
00161 
00162 public:
00163   friend const SaveLoad *GetFlowStatDesc();
00164 
00172   FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
00173     MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
00174 
00180   FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
00181     MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
00182 
00186   FORCEINLINE FlowStat GetDecreasedCopy() const
00187   {
00188     FlowStat ret(this->length, this->via, this->planned, this->sent);
00189     this->MovingAverage<uint>::Decrease(ret.sent);
00190     return ret;
00191   }
00192 
00197   FORCEINLINE void Increase(uint sent)
00198   {
00199     this->sent += sent;
00200   }
00201 
00206   FORCEINLINE uint Sent() const
00207   {
00208     return this->MovingAverage<uint>::Monthly(sent);
00209   }
00210 
00215   FORCEINLINE uint Planned() const
00216   {
00217     return this->planned;
00218   }
00219 
00224   FORCEINLINE StationID Via() const
00225   {
00226     return this->via;
00227   }
00228 
00233   struct Comparator {
00241     bool operator()(const FlowStat &x, const FlowStat &y) const
00242     {
00243       int diff_x = (int)x.Planned() - (int)x.Sent();
00244       int diff_y = (int)y.Planned() - (int)y.Sent();
00245       if (diff_x != diff_y) {
00246         return diff_x > diff_y;
00247       } else {
00248         return x.Via() > y.Via();
00249       }
00250     }
00251   };
00252 
00258   FORCEINLINE FlowStat &operator+=(const FlowStat &other)
00259   {
00260     assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
00261     if (other.via != INVALID_STATION) this->via = other.via;
00262     this->planned += other.planned;
00263     uint sent = this->sent + other.sent;
00264     if (sent > 0) {
00265       this->length = (this->length * this->sent + other.length * other.sent) / sent;
00266       assert(this->length > 0);
00267     }
00268     this->sent = sent;
00269     return *this;
00270   }
00271 
00275   FORCEINLINE void Clear()
00276   {
00277     this->planned = 0;
00278     this->sent = 0;
00279     this->via = INVALID_STATION;
00280   }
00281 };
00282 
00283 typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet; 
00284 
00285 typedef std::map<StationID, LinkStat> LinkStatMap;
00286 typedef std::map<StationID, FlowStatSet> FlowStatMap; 
00287 
00288 uint GetMovingAverageLength(const Station *from, const Station *to);
00289 
00293 struct GoodsEntry {
00295   enum GoodsEntryStatus {
00296     GES_ACCEPTANCE,       
00297     GES_PICKUP,           
00298     GES_EVER_ACCEPTED,    
00299     GES_LAST_MONTH,       
00300     GES_CURRENT_MONTH,    
00301     GES_ACCEPTED_BIGTICK, 
00302   };
00303 
00304   GoodsEntry() :
00305     acceptance_pickup(0),
00306     days_since_pickup(255),
00307     rating(INITIAL_STATION_RATING),
00308     last_speed(0),
00309     last_age(255),
00310     supply(0),
00311     supply_new(0),
00312     last_component(INVALID_LINKGRAPH_COMPONENT),
00313     max_waiting_cargo(0)
00314   {}
00315 
00316   byte acceptance_pickup; 
00317   byte days_since_pickup; 
00318   byte rating;            
00319   byte last_speed;        
00320   byte last_age;          
00321   byte amount_fract;      
00322   StationCargoList cargo; 
00323   uint supply;            
00324   uint supply_new;        
00325   FlowStatMap flows;      
00326   LinkStatMap link_stats; 
00327   LinkGraphComponentID last_component; 
00328   uint max_waiting_cargo;              
00329   FlowStat GetSumFlowVia(StationID via) const;
00330 
00331   void UpdateFlowStats(StationID source, uint count, StationID next);
00332   void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00333   void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00334 
00335   StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00336 };
00337 
00339 struct Airport : public TileArea {
00340   Airport() : TileArea(INVALID_TILE, 0, 0) {}
00341 
00342   uint64 flags;       
00343   byte type;          
00344   byte layout;        
00345   Direction rotation; 
00346 
00347   PersistentStorage *psa; 
00348 
00354   const AirportSpec *GetSpec() const
00355   {
00356     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00357     return AirportSpec::Get(this->type);
00358   }
00359 
00366   const AirportFTAClass *GetFTA() const
00367   {
00368     return this->GetSpec()->fsm;
00369   }
00370 
00372   FORCEINLINE bool HasHangar() const
00373   {
00374     return this->GetSpec()->nof_depots > 0;
00375   }
00376 
00385   FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00386   {
00387     const AirportSpec *as = this->GetSpec();
00388     switch (this->rotation) {
00389       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00390 
00391       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00392 
00393       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00394 
00395       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00396 
00397       default: NOT_REACHED();
00398     }
00399   }
00400 
00407   FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00408   {
00409     const AirportSpec *as = this->GetSpec();
00410     for (uint i = 0; i < as->nof_depots; i++) {
00411       if (as->depot_table[i].hangar_num == hangar_num) {
00412         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00413       }
00414     }
00415     NOT_REACHED();
00416   }
00417 
00424   FORCEINLINE Direction GetHangarExitDirection(TileIndex tile) const
00425   {
00426     const AirportSpec *as = this->GetSpec();
00427     const HangarTileTable *htt = GetHangarDataByTile(tile);
00428     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00429   }
00430 
00437   FORCEINLINE uint GetHangarNum(TileIndex tile) const
00438   {
00439     const HangarTileTable *htt = GetHangarDataByTile(tile);
00440     return htt->hangar_num;
00441   }
00442 
00444   FORCEINLINE uint GetNumHangars() const
00445   {
00446     uint num = 0;
00447     uint counted = 0;
00448     const AirportSpec *as = this->GetSpec();
00449     for (uint i = 0; i < as->nof_depots; i++) {
00450       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00451         num++;
00452         SetBit(counted, as->depot_table[i].hangar_num);
00453       }
00454     }
00455     return num;
00456   }
00457 
00458 private:
00465   FORCEINLINE const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00466   {
00467     const AirportSpec *as = this->GetSpec();
00468     for (uint i = 0; i < as->nof_depots; i++) {
00469       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00470         return as->depot_table + i;
00471       }
00472     }
00473     NOT_REACHED();
00474   }
00475 };
00476 
00477 typedef SmallVector<Industry *, 2> IndustryVector;
00478 
00480 struct Station : SpecializedStation<Station, false> {
00481 public:
00482   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00483   {
00484     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00485   }
00486 
00487   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00488 
00489   RoadStop *bus_stops;    
00490   TileArea bus_station;   
00491   RoadStop *truck_stops;  
00492   TileArea truck_station; 
00493 
00494   Airport airport;        
00495   TileIndex dock_tile;    
00496 
00497   IndustryType indtype;   
00498 
00499   StationHadVehicleOfTypeByte had_vehicle_of_type;
00500 
00501   byte time_since_load;
00502   byte time_since_unload;
00503 
00504   byte last_vehicle_type;
00505   std::list<Vehicle *> loading_vehicles;
00506   GoodsEntry goods[NUM_CARGO];  
00507   uint32 always_accepted;       
00508 
00509   IndustryVector industries_near; 
00510 
00511   Station(TileIndex tile = INVALID_TILE);
00512   ~Station();
00513 
00514   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00515 
00516   void MarkTilesDirty(bool cargo_change) const;
00517 
00518   void UpdateVirtCoord();
00519 
00520   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00521   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
00522   void RecomputeIndustriesNear();
00523   static void RecomputeIndustriesNearForAll();
00524 
00525   uint GetCatchmentRadius() const;
00526   Rect GetCatchmentRect() const;
00527 
00528   /* virtual */ FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00529   {
00530     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00531   }
00532 
00533   FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00534   {
00535     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00536   }
00537 
00538   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00539 
00540   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
00541 
00542   void RunAverages();
00543 };
00544 
00545 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00546 
00547 #endif /* STATION_BASE_H */