# 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 */