station_base.h

Go to the documentation of this file.
00001 /* $Id: station_base.h 26166 2013-12-20 14:57:44Z fonsinchen $ */
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     this->unrestricted = flow;
00057   }
00058 
00067   inline void AppendShare(StationID st, uint flow, bool restricted = false)
00068   {
00069     assert(flow > 0);
00070     this->shares[(--this->shares.end())->first + flow] = st;
00071     if (!restricted) this->unrestricted += flow;
00072   }
00073 
00074   uint GetShare(StationID st) const;
00075 
00076   void ChangeShare(StationID st, int flow);
00077 
00078   void RestrictShare(StationID st);
00079 
00080   void ReleaseShare(StationID st);
00081 
00082   void ScaleToMonthly(uint runtime);
00083 
00089   inline const SharesMap *GetShares() const { return &this->shares; }
00090 
00095   inline uint GetUnrestricted() const { return this->unrestricted; }
00096 
00102   inline void SwapShares(FlowStat &other)
00103   {
00104     this->shares.swap(other.shares);
00105     Swap(this->unrestricted, other.unrestricted);
00106   }
00107 
00116   inline StationID GetViaWithRestricted(bool &is_restricted) const
00117   {
00118     assert(!this->shares.empty());
00119     uint rand = RandomRange((--this->shares.end())->first);
00120     is_restricted = rand >= this->unrestricted;
00121     return this->shares.upper_bound(rand)->second;
00122   }
00123 
00131   inline StationID GetVia() const
00132   {
00133     assert(!this->shares.empty());
00134     return this->unrestricted > 0 ?
00135         this->shares.upper_bound(RandomRange(this->unrestricted))->second :
00136         INVALID_STATION;
00137   }
00138 
00139   StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00140 
00141   void Invalidate();
00142 
00143 private:
00144   SharesMap shares;  
00145   uint unrestricted; 
00146 };
00147 
00149 class FlowStatMap : public std::map<StationID, FlowStat> {
00150 public:
00151   void AddFlow(StationID origin, StationID via, uint amount);
00152   void PassOnFlow(StationID origin, StationID via, uint amount);
00153   StationIDStack DeleteFlows(StationID via);
00154   void RestrictFlows(StationID via);
00155   void ReleaseFlows(StationID via);
00156   void FinalizeLocalConsumption(StationID self);
00157 };
00158 
00162 struct GoodsEntry {
00164   enum GoodsEntryStatus {
00169     GES_ACCEPTANCE,
00170 
00178     GES_PICKUP,
00179 
00184     GES_EVER_ACCEPTED,
00185 
00190     GES_LAST_MONTH,
00191 
00196     GES_CURRENT_MONTH,
00197 
00202     GES_ACCEPTED_BIGTICK,
00203   };
00204 
00205   GoodsEntry() :
00206     acceptance_pickup(0),
00207     time_since_pickup(255),
00208     rating(INITIAL_STATION_RATING),
00209     last_speed(0),
00210     last_age(255),
00211     amount_fract(0),
00212     link_graph(INVALID_LINK_GRAPH),
00213     node(INVALID_NODE),
00214     max_waiting_cargo(0)
00215   {}
00216 
00217   byte acceptance_pickup; 
00218 
00224   byte time_since_pickup;
00225 
00226   byte rating;            
00227 
00237   byte last_speed;
00238 
00243   byte last_age;
00244 
00245   byte amount_fract;      
00246   StationCargoList cargo; 
00247 
00248   LinkGraphID link_graph; 
00249   NodeID node;            
00250   FlowStatMap flows;      
00251   uint max_waiting_cargo; 
00252 
00258   bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00259 
00264   inline bool HasRating() const
00265   {
00266     return HasBit(this->acceptance_pickup, GES_PICKUP);
00267   }
00268 
00269   uint GetSumFlowVia(StationID via) const;
00270 
00276   inline StationID GetVia(StationID source) const
00277   {
00278     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00279     return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00280   }
00281 
00290   inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00291   {
00292     FlowStatMap::const_iterator flow_it(this->flows.find(source));
00293     return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00294   }
00295 };
00296 
00298 struct Airport : public TileArea {
00299   Airport() : TileArea(INVALID_TILE, 0, 0) {}
00300 
00301   uint64 flags;       
00302   byte type;          
00303   byte layout;        
00304   Direction rotation; 
00305 
00306   PersistentStorage *psa; 
00307 
00313   const AirportSpec *GetSpec() const
00314   {
00315     if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00316     return AirportSpec::Get(this->type);
00317   }
00318 
00325   const AirportFTAClass *GetFTA() const
00326   {
00327     return this->GetSpec()->fsm;
00328   }
00329 
00331   inline bool HasHangar() const
00332   {
00333     return this->GetSpec()->nof_depots > 0;
00334   }
00335 
00344   inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00345   {
00346     const AirportSpec *as = this->GetSpec();
00347     switch (this->rotation) {
00348       case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00349 
00350       case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00351 
00352       case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00353 
00354       case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00355 
00356       default: NOT_REACHED();
00357     }
00358   }
00359 
00366   inline TileIndex GetHangarTile(uint hangar_num) const
00367   {
00368     const AirportSpec *as = this->GetSpec();
00369     for (uint i = 0; i < as->nof_depots; i++) {
00370       if (as->depot_table[i].hangar_num == hangar_num) {
00371         return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00372       }
00373     }
00374     NOT_REACHED();
00375   }
00376 
00383   inline Direction GetHangarExitDirection(TileIndex tile) const
00384   {
00385     const AirportSpec *as = this->GetSpec();
00386     const HangarTileTable *htt = GetHangarDataByTile(tile);
00387     return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00388   }
00389 
00396   inline uint GetHangarNum(TileIndex tile) const
00397   {
00398     const HangarTileTable *htt = GetHangarDataByTile(tile);
00399     return htt->hangar_num;
00400   }
00401 
00403   inline uint GetNumHangars() const
00404   {
00405     uint num = 0;
00406     uint counted = 0;
00407     const AirportSpec *as = this->GetSpec();
00408     for (uint i = 0; i < as->nof_depots; i++) {
00409       if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00410         num++;
00411         SetBit(counted, as->depot_table[i].hangar_num);
00412       }
00413     }
00414     return num;
00415   }
00416 
00417 private:
00424   inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00425   {
00426     const AirportSpec *as = this->GetSpec();
00427     for (uint i = 0; i < as->nof_depots; i++) {
00428       if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00429         return as->depot_table + i;
00430       }
00431     }
00432     NOT_REACHED();
00433   }
00434 };
00435 
00436 typedef SmallVector<Industry *, 2> IndustryVector;
00437 
00439 struct Station FINAL : SpecializedStation<Station, false> {
00440 public:
00441   RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00442   {
00443     return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00444   }
00445 
00446   RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00447 
00448   RoadStop *bus_stops;    
00449   TileArea bus_station;   
00450   RoadStop *truck_stops;  
00451   TileArea truck_station; 
00452 
00453   Airport airport;        
00454   TileIndex dock_tile;    
00455 
00456   IndustryType indtype;   
00457 
00458   StationHadVehicleOfTypeByte had_vehicle_of_type;
00459 
00460   byte time_since_load;
00461   byte time_since_unload;
00462 
00463   byte last_vehicle_type;
00464   std::list<Vehicle *> loading_vehicles;
00465   GoodsEntry goods[NUM_CARGO];  
00466   uint32 always_accepted;       
00467 
00468   IndustryVector industries_near; 
00469 
00470   Station(TileIndex tile = INVALID_TILE);
00471   ~Station();
00472 
00473   void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00474 
00475   void MarkTilesDirty(bool cargo_change) const;
00476 
00477   void UpdateVirtCoord();
00478 
00479   /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00480   /* virtual */ uint GetPlatformLength(TileIndex tile) const;
00481   void RecomputeIndustriesNear();
00482   static void RecomputeIndustriesNearForAll();
00483 
00484   uint GetCatchmentRadius() const;
00485   Rect GetCatchmentRect() const;
00486 
00487   /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
00488   {
00489     return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00490   }
00491 
00492   inline bool TileBelongsToAirport(TileIndex tile) const
00493   {
00494     return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00495   }
00496 
00497   /* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
00498 
00499   /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
00500 };
00501 
00502 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00503 
00505 class AirportTileIterator : public OrthogonalTileIterator {
00506 private:
00507   const Station *st; 
00508 
00509 public:
00514   AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00515   {
00516     if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00517   }
00518 
00519   inline TileIterator& operator ++()
00520   {
00521     (*this).OrthogonalTileIterator::operator++();
00522     while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00523       (*this).OrthogonalTileIterator::operator++();
00524     }
00525     return *this;
00526   }
00527 
00528   virtual TileIterator *Clone() const
00529   {
00530     return new AirportTileIterator(*this);
00531   }
00532 };
00533 
00534 #endif /* STATION_BASE_H */