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 
00045   inline FlowStat() {NOT_REACHED();}
00046 
00052   inline FlowStat(StationID st, uint flow)
00053   {
00054     assert(flow > 0);
00055     this->shares[flow] = st;
00056   }
00057 
00065   inline void AppendShare(StationID st, uint flow)
00066   {
00067     assert(flow > 0);
00068     this->shares[(--this->shares.end())->first + flow] = st;
00069   }
00070 
00071   uint GetShare(StationID st) const;
00072 
00073   void ChangeShare(StationID st, int flow);
00074 
00080   inline const SharesMap *GetShares() const { return &this->shares; }
00081 
00089   inline StationID GetVia() const
00090   {
00091     assert(!this->shares.empty());
00092     return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
00093   }
00094 
00095   StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00096 
00097 private:
00098   SharesMap shares;  
00099 };
00100 
00102 class FlowStatMap : public std::map<StationID, FlowStat> {
00103 public:
00104   void AddFlow(StationID origin, StationID via, uint amount);
00105   void PassOnFlow(StationID origin, StationID via, uint amount);
00106   void DeleteFlows(StationID via);
00107   void FinalizeLocalConsumption(StationID self);
00108 };
00109 
00113 struct GoodsEntry {
00115   enum GoodsEntryStatus {
00120     GES_ACCEPTANCE,
00121 
00129     GES_PICKUP,
00130 
00135     GES_EVER_ACCEPTED,
00136 
00141     GES_LAST_MONTH,
00142 
00147     GES_CURRENT_MONTH,
00148 
00153     GES_ACCEPTED_BIGTICK,
00154   };
00155 
00156   GoodsEntry() :
00157     acceptance_pickup(0),
00158     time_since_pickup(255),
00159     rating(INITIAL_STATION_RATING),
00160     last_speed(0),
00161     last_age(255),
00162     link_graph(INVALID_LINK_GRAPH),
00163     node(INVALID_NODE),
00164     max_waiting_cargo(0)
00165   {}
00166 
00167   byte acceptance_pickup; 
00168 
00174   byte time_since_pickup;
00175 
00176   byte rating;            
00177 
00187   byte last_speed;
00188 
00193   byte last_age;
00194 
00195   byte amount_fract;      
00196   StationCargoList cargo; 
00197 
00198   LinkGraphID link_graph; 
00199   NodeID node;            
00200   FlowStatMap flows;      
00201   uint max_waiting_cargo; 
00202 
00208   bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00209 
00214   inline bool HasRating() const
00215   {
00216     return HasBit(this->acceptance_pickup, GES_PICKUP);
00217   }
00218 
00219   uint GetSumFlowVia(StationID via) const;
00220 
00226   inline StationID GetVia(StationID source) const
00227   {
00228     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00229     return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00230   }
00231 
00240   inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00241   {
00242     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00243     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00244   }
00245 };
00246 
00248 struct Airport : public TileArea {
00249   Airport() : TileArea(INVALID_TILE, 0, 0) {}
00250 
00251   uint64 flags;       
00252   byte type;          
00253   byte layout;        
00254   Direction rotation; 
00255 
00256   PersistentStorage *psa; 
00257 
00263   const AirportSpec *GetSpec() const
00264   {
00265     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00266     return AirportSpec::Get(this->type);
00267   }
00268 
00275   const AirportFTAClass *GetFTA() const
00276   {
00277     return this->GetSpec()->fsm;
00278   }
00279 
00281   inline bool HasHangar() const
00282   {
00283     return this->GetSpec()->nof_depots > 0;
00284   }
00285 
00294   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00295   {
00296     const AirportSpec *as = this->GetSpec();
00297     switch (this->rotation) {
00298       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00299 
00300       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00301 
00302       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00303 
00304       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00305 
00306       default: NOT_REACHED();
00307     }
00308   }
00309 
00316   inline TileIndex GetHangarTile(uint hangar_num) const
00317   {
00318     const AirportSpec *as = this->GetSpec();
00319     for (uint i = 0; i < as->nof_depots; i++) {
00320       if (as->depot_table[i].hangar_num == hangar_num) {
00321         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00322       }
00323     }
00324     NOT_REACHED();
00325   }
00326 
00333   inline Direction GetHangarExitDirection(TileIndex tile) const
00334   {
00335     const AirportSpec *as = this->GetSpec();
00336     const HangarTileTable *htt = GetHangarDataByTile(tile);
00337     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00338   }
00339 
00346   inline uint GetHangarNum(TileIndex tile) const
00347   {
00348     const HangarTileTable *htt = GetHangarDataByTile(tile);
00349     return htt->hangar_num;
00350   }
00351 
00353   inline uint GetNumHangars() const
00354   {
00355     uint num = 0;
00356     uint counted = 0;
00357     const AirportSpec *as = this->GetSpec();
00358     for (uint i = 0; i < as->nof_depots; i++) {
00359       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00360         num++;
00361         SetBit(counted, as->depot_table[i].hangar_num);
00362       }
00363     }
00364     return num;
00365   }
00366 
00367 private:
00374   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00375   {
00376     const AirportSpec *as = this->GetSpec();
00377     for (uint i = 0; i < as->nof_depots; i++) {
00378       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00379         return as->depot_table + i;
00380       }
00381     }
00382     NOT_REACHED();
00383   }
00384 };
00385 
00386 typedef SmallVector<Industry *, 2> IndustryVector;
00387 
00389 struct Station FINAL : SpecializedStation<Station, false> {
00390 public:
00391   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00392   {
00393     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00394   }
00395 
00396   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00397 
00398   RoadStop *bus_stops;    
00399   TileArea bus_station;   
00400   RoadStop *truck_stops;  
00401   TileArea truck_station; 
00402 
00403   Airport airport;        
00404   TileIndex dock_tile;    
00405 
00406   IndustryType indtype;   
00407 
00408   StationHadVehicleOfTypeByte had_vehicle_of_type;
00409 
00410   byte time_since_load;
00411   byte time_since_unload;
00412 
00413   byte last_vehicle_type;
00414   std::list<Vehicle *> loading_vehicles;
00415   GoodsEntry goods[NUM_CARGO];  
00416   uint32 always_accepted;       
00417 
00418   IndustryVector industries_near; 
00419 
00420   Station(TileIndex tile = INVALID_TILE);
00421   ~Station();
00422 
00423   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00424 
00425   void MarkTilesDirty(bool cargo_change) const;
00426 
00427   void UpdateVirtCoord();
00428 
00429   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00430   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
00431   void RecomputeIndustriesNear();
00432   static void RecomputeIndustriesNearForAll();
00433 
00434   uint GetCatchmentRadius() const;
00435   Rect GetCatchmentRect() const;
00436 
00437   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
00438   {
00439     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00440   }
00441 
00442   inline bool TileBelongsToAirport(TileIndex tile) const
00443   {
00444     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00445   }
00446 
00447   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00448 
00449   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
00450 
00451   void RunAverages();
00452 };
00453 
00454 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00455 
00457 class AirportTileIterator : public OrthogonalTileIterator {
00458 private:
00459   const Station *st; 
00460 
00461 public:
00466   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00467   {
00468     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00469   }
00470 
00471   inline TileIterator& operator ++()
00472   {
00473     (*this).OrthogonalTileIterator::operator++();
00474     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00475       (*this).OrthogonalTileIterator::operator++();
00476     }
00477     return *this;
00478   }
00479 
00480   virtual TileIterator *Clone() const
00481   {
00482     return new AirportTileIterator(*this);
00483   }
00484 };
00485 
00486 #endif /* STATION_BASE_H */