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 
00290 struct GoodsEntry {
00291   enum AcceptancePickup {
00292     ACCEPTANCE,
00293     PICKUP
00294   };
00295 
00296   GoodsEntry() :
00297     acceptance_pickup(0),
00298     days_since_pickup(255),
00299     rating(INITIAL_STATION_RATING),
00300     last_speed(0),
00301     last_age(255),
00302     supply(0),
00303     supply_new(0),
00304     last_component(INVALID_LINKGRAPH_COMPONENT),
00305     max_waiting_cargo(0)
00306   {}
00307 
00308   byte acceptance_pickup;
00309   byte days_since_pickup;
00310   byte rating;
00311   byte last_speed;
00312   byte last_age;
00313   byte amount_fract;                   
00314   StationCargoList cargo;              
00315   uint supply;                         
00316   uint supply_new;                     
00317   FlowStatMap flows;                   
00318   LinkStatMap link_stats;              
00319   LinkGraphComponentID last_component; 
00320   uint max_waiting_cargo;              
00321   FlowStat GetSumFlowVia(StationID via) const;
00322 
00323   void UpdateFlowStats(StationID source, uint count, StationID next);
00324   void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00325   void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00326 
00327   StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00328 };
00329 
00331 struct Airport : public TileArea {
00332   typedef PersistentStorageArray<int32, 16> PersistentStorage;
00333 
00334   Airport() : TileArea(INVALID_TILE, 0, 0) {}
00335 
00336   uint64 flags;       
00337   byte type;          
00338   byte layout;        
00339   Direction rotation; 
00340   PersistentStorage psa; 
00341 
00347   const AirportSpec *GetSpec() const
00348   {
00349     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00350     return AirportSpec::Get(this->type);
00351   }
00352 
00359   const AirportFTAClass *GetFTA() const
00360   {
00361     return this->GetSpec()->fsm;
00362   }
00363 
00365   FORCEINLINE bool HasHangar() const
00366   {
00367     return this->GetSpec()->nof_depots > 0;
00368   }
00369 
00378   FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00379   {
00380     const AirportSpec *as = this->GetSpec();
00381     switch (this->rotation) {
00382       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00383 
00384       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00385 
00386       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00387 
00388       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00389 
00390       default: NOT_REACHED();
00391     }
00392   }
00393 
00400   FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00401   {
00402     const AirportSpec *as = this->GetSpec();
00403     for (uint i = 0; i < as->nof_depots; i++) {
00404       if (as->depot_table[i].hangar_num == hangar_num) {
00405         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00406       }
00407     }
00408     NOT_REACHED();
00409   }
00410 
00417   FORCEINLINE uint GetHangarNum(TileIndex tile) const
00418   {
00419     const AirportSpec *as = this->GetSpec();
00420     for (uint i = 0; i < as->nof_depots; i++) {
00421       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00422         return as->depot_table[i].hangar_num;
00423       }
00424     }
00425     NOT_REACHED();
00426   }
00427 
00429   FORCEINLINE uint GetNumHangars() const
00430   {
00431     uint num = 0;
00432     uint counted = 0;
00433     const AirportSpec *as = this->GetSpec();
00434     for (uint i = 0; i < as->nof_depots; i++) {
00435       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00436         num++;
00437         SetBit(counted, as->depot_table[i].hangar_num);
00438       }
00439     }
00440     return num;
00441   }
00442 };
00443 
00444 typedef SmallVector<Industry *, 2> IndustryVector;
00445 
00447 struct Station : SpecializedStation<Station, false> {
00448 public:
00449   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00450   {
00451     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00452   }
00453 
00454   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00455 
00456   RoadStop *bus_stops;    
00457   TileArea bus_station;   
00458   RoadStop *truck_stops;  
00459   TileArea truck_station; 
00460 
00461   Airport airport;        
00462   TileIndex dock_tile;    
00463 
00464   IndustryType indtype;   
00465 
00466   StationHadVehicleOfTypeByte had_vehicle_of_type;
00467 
00468   byte time_since_load;
00469   byte time_since_unload;
00470 
00471   byte last_vehicle_type;
00472   std::list<Vehicle *> loading_vehicles;
00473   GoodsEntry goods[NUM_CARGO];  
00474   uint32 always_accepted;       
00475 
00476   IndustryVector industries_near; 
00477 
00478   Station(TileIndex tile = INVALID_TILE);
00479   ~Station();
00480 
00481   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00482 
00483   void MarkTilesDirty(bool cargo_change) const;
00484 
00485   void UpdateVirtCoord();
00486 
00487   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00488   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
00489   void RecomputeIndustriesNear();
00490   static void RecomputeIndustriesNearForAll();
00491 
00492   uint GetCatchmentRadius() const;
00493   Rect GetCatchmentRect() const;
00494 
00495   /* virtual */ FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00496   {
00497     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00498   }
00499 
00500   FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00501   {
00502     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00503   }
00504 
00505   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00506 
00507   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
00508 
00509   void RunAverages();
00510 };
00511 
00512 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00513 
00514 #endif /* STATION_BASE_H */

Generated on Fri May 27 04:19:49 2011 for OpenTTD by  doxygen 1.6.1