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