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 
00036 class FlowStat {
00037 public:
00038   typedef std::map<uint32, StationID> SharesMap;
00039 
00040   inline FlowStat() {NOT_REACHED();}
00041 
00042   inline FlowStat(StationID st, uint flow)
00043   {
00044     assert(flow > 0);
00045     this->shares[flow] = st;
00046   }
00047 
00055   inline void AppendShare(StationID st, uint flow)
00056   {
00057     assert(flow > 0);
00058     this->shares[(--this->shares.end())->first + flow] = st;
00059   }
00060 
00061   uint GetShare(StationID st) const;
00062 
00063   void ChangeShare(StationID st, int flow);
00064 
00065   inline const SharesMap *GetShares() const { return &this->shares; }
00066 
00074   inline StationID GetVia() const
00075   {
00076     assert(!this->shares.empty());
00077     return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
00078   }
00079 
00080   StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00081   void Cleanup(NodeID self, LinkGraphID link_graph);
00082 
00083 private:
00084   SharesMap shares;  
00085 };
00086 
00088 class FlowStatMap : public std::map<StationID, FlowStat> {
00089 public:
00090   void AddFlow(StationID origin, StationID via, uint amount);
00091   void PassOnFlow(StationID origin, StationID via, uint amount);
00092   void DeleteFlows(StationID via);
00093   void FinalizeLocalConsumption(StationID self);
00094   void Cleanup(StationID self, LinkGraphID link_graph);
00095 };
00096 
00100 struct GoodsEntry {
00102   enum GoodsEntryStatus {
00107     GES_ACCEPTANCE,
00108 
00116     GES_PICKUP,
00117 
00122     GES_EVER_ACCEPTED,
00123 
00128     GES_LAST_MONTH,
00129 
00134     GES_CURRENT_MONTH,
00135 
00140     GES_ACCEPTED_BIGTICK,
00141   };
00142 
00143   GoodsEntry() :
00144     acceptance_pickup(0),
00145     time_since_pickup(255),
00146     rating(INITIAL_STATION_RATING),
00147     last_speed(0),
00148     last_age(255),
00149     link_graph(INVALID_LINK_GRAPH),
00150     node(INVALID_NODE),
00151     max_waiting_cargo(0)
00152   {}
00153 
00154   byte acceptance_pickup; 
00155 
00161   byte time_since_pickup;
00162 
00163   byte rating;            
00164 
00174   byte last_speed;
00175 
00180   byte last_age;
00181 
00182   byte amount_fract;      
00183   StationCargoList cargo; 
00184 
00185   LinkGraphID link_graph; 
00186   NodeID node;            
00187   FlowStatMap flows;      
00188   uint max_waiting_cargo; 
00189 
00195   bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00196 
00201   inline bool HasRating() const
00202   {
00203     return HasBit(this->acceptance_pickup, GES_PICKUP);
00204   }
00205 
00206   uint GetSumFlowVia(StationID via) const;
00207 
00214   inline StationID GetVia(StationID source) const
00215   {
00216     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00217     return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00218   }
00219 
00228   inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00229   {
00230     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00231     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00232   }
00233 };
00234 
00236 struct Airport : public TileArea {
00237   Airport() : TileArea(INVALID_TILE, 0, 0) {}
00238 
00239   uint64 flags;       
00240   byte type;          
00241   byte layout;        
00242   Direction rotation; 
00243 
00244   PersistentStorage *psa; 
00245 
00251   const AirportSpec *GetSpec() const
00252   {
00253     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00254     return AirportSpec::Get(this->type);
00255   }
00256 
00263   const AirportFTAClass *GetFTA() const
00264   {
00265     return this->GetSpec()->fsm;
00266   }
00267 
00269   inline bool HasHangar() const
00270   {
00271     return this->GetSpec()->nof_depots > 0;
00272   }
00273 
00282   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00283   {
00284     const AirportSpec *as = this->GetSpec();
00285     switch (this->rotation) {
00286       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00287 
00288       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00289 
00290       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00291 
00292       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00293 
00294       default: NOT_REACHED();
00295     }
00296   }
00297 
00304   inline TileIndex GetHangarTile(uint hangar_num) const
00305   {
00306     const AirportSpec *as = this->GetSpec();
00307     for (uint i = 0; i < as->nof_depots; i++) {
00308       if (as->depot_table[i].hangar_num == hangar_num) {
00309         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00310       }
00311     }
00312     NOT_REACHED();
00313   }
00314 
00321   inline Direction GetHangarExitDirection(TileIndex tile) const
00322   {
00323     const AirportSpec *as = this->GetSpec();
00324     const HangarTileTable *htt = GetHangarDataByTile(tile);
00325     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00326   }
00327 
00334   inline uint GetHangarNum(TileIndex tile) const
00335   {
00336     const HangarTileTable *htt = GetHangarDataByTile(tile);
00337     return htt->hangar_num;
00338   }
00339 
00341   inline uint GetNumHangars() const
00342   {
00343     uint num = 0;
00344     uint counted = 0;
00345     const AirportSpec *as = this->GetSpec();
00346     for (uint i = 0; i < as->nof_depots; i++) {
00347       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00348         num++;
00349         SetBit(counted, as->depot_table[i].hangar_num);
00350       }
00351     }
00352     return num;
00353   }
00354 
00355 private:
00362   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00363   {
00364     const AirportSpec *as = this->GetSpec();
00365     for (uint i = 0; i < as->nof_depots; i++) {
00366       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00367         return as->depot_table + i;
00368       }
00369     }
00370     NOT_REACHED();
00371   }
00372 };
00373 
00374 typedef SmallVector<Industry *, 2> IndustryVector;
00375 
00377 struct Station FINAL : SpecializedStation<Station, false> {
00378 public:
00379   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00380   {
00381     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00382   }
00383 
00384   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00385 
00386   RoadStop *bus_stops;    
00387   TileArea bus_station;   
00388   RoadStop *truck_stops;  
00389   TileArea truck_station; 
00390 
00391   Airport airport;        
00392   TileIndex dock_tile;    
00393 
00394   IndustryType indtype;   
00395 
00396   StationHadVehicleOfTypeByte had_vehicle_of_type;
00397 
00398   byte time_since_load;
00399   byte time_since_unload;
00400 
00401   byte last_vehicle_type;
00402   std::list<Vehicle *> loading_vehicles;
00403   GoodsEntry goods[NUM_CARGO];  
00404   uint32 always_accepted;       
00405 
00406   IndustryVector industries_near; 
00407 
00408   Station(TileIndex tile = INVALID_TILE);
00409   ~Station();
00410 
00411   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00412 
00413   void MarkTilesDirty(bool cargo_change) const;
00414 
00415   void UpdateVirtCoord();
00416 
00417   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00418   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
00419   void RecomputeIndustriesNear();
00420   static void RecomputeIndustriesNearForAll();
00421 
00422   uint GetCatchmentRadius() const;
00423   Rect GetCatchmentRect() const;
00424 
00425   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
00426   {
00427     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00428   }
00429 
00430   inline bool TileBelongsToAirport(TileIndex tile) const
00431   {
00432     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00433   }
00434 
00435   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00436 
00437   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
00438 
00439   void RunAverages();
00440 };
00441 
00442 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00443 
00445 class AirportTileIterator : public OrthogonalTileIterator {
00446 private:
00447   const Station *st; 
00448 
00449 public:
00454   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00455   {
00456     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00457   }
00458 
00459   inline TileIterator& operator ++()
00460   {
00461     (*this).OrthogonalTileIterator::operator++();
00462     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00463       (*this).OrthogonalTileIterator::operator++();
00464     }
00465     return *this;
00466   }
00467 
00468   virtual TileIterator *Clone() const
00469   {
00470     return new AirportTileIterator(*this);
00471   }
00472 };
00473 
00474 #endif /* STATION_BASE_H */