station_base.h

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