00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef STATION_BASE_H
00013 #define STATION_BASE_H
00014
00015 #include "base_station_base.h"
00016 #include "newgrf_airport.h"
00017 #include "cargopacket.h"
00018 #include "industry_type.h"
00019 #include "linkgraph/linkgraph_type.h"
00020 #include "newgrf_storage.h"
00021 #include "moving_average.h"
00022 #include <map>
00023 #include <set>
00024
00025 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
00026 extern StationPool _station_pool;
00027
00028 static const byte INITIAL_STATION_RATING = 175;
00029
00038 class LinkStat : private MovingAverage<uint> {
00039 private:
00044 uint capacity;
00045
00049 uint timeout;
00050
00055 uint usage;
00056
00057 public:
00061 static const uint MIN_AVERAGE_LENGTH = 48;
00062
00063 friend const SaveLoad *GetLinkStatDesc();
00064
00068 LinkStat() : MovingAverage<uint>(0) {NOT_REACHED();}
00069
00076 FORCEINLINE LinkStat(uint distance, uint capacity = 1, uint usage = 0) :
00077 MovingAverage<uint>(distance), capacity(capacity), timeout(distance), usage(usage)
00078 {
00079 assert(this->usage <= this->capacity);
00080 }
00081
00085 FORCEINLINE void Clear()
00086 {
00087 this->capacity = 1;
00088 this->usage = 0;
00089 this->timeout = this->length;
00090 }
00091
00095 FORCEINLINE void Decrease()
00096 {
00097 this->MovingAverage<uint>::Decrease(this->usage);
00098 this->timeout = this->timeout * MIN_AVERAGE_LENGTH / (MIN_AVERAGE_LENGTH + 1);
00099 this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), (uint)1);
00100 assert(this->usage <= this->capacity);
00101 }
00102
00107 FORCEINLINE uint Capacity() const
00108 {
00109 return this->MovingAverage<uint>::Monthly(this->capacity);
00110 }
00111
00116 FORCEINLINE uint Usage() const
00117 {
00118 return this->MovingAverage<uint>::Monthly(this->usage);
00119 }
00120
00126 FORCEINLINE void Increase(uint capacity, uint usage)
00127 {
00128 this->timeout = this->length;
00129 this->capacity += capacity;
00130 this->usage += usage;
00131 assert(this->usage <= this->capacity);
00132 }
00133
00137 FORCEINLINE void Refresh(uint min_capacity)
00138 {
00139 this->capacity = max(this->capacity, min_capacity);
00140 this->timeout = this->length;
00141 }
00142
00147 FORCEINLINE bool IsValid() const
00148 {
00149 return this->timeout > 0;
00150 }
00151 };
00152
00156 class FlowStat : private MovingAverage<uint> {
00157 private:
00158 uint planned;
00159 uint sent;
00160 StationID via;
00161
00162 public:
00163 friend const SaveLoad *GetFlowStatDesc();
00164
00172 FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
00173 MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
00174
00180 FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
00181 MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
00182
00186 FORCEINLINE FlowStat GetDecreasedCopy() const
00187 {
00188 FlowStat ret(this->length, this->via, this->planned, this->sent);
00189 this->MovingAverage<uint>::Decrease(ret.sent);
00190 return ret;
00191 }
00192
00197 FORCEINLINE void Increase(uint sent)
00198 {
00199 this->sent += sent;
00200 }
00201
00206 FORCEINLINE uint Sent() const
00207 {
00208 return this->MovingAverage<uint>::Monthly(sent);
00209 }
00210
00215 FORCEINLINE uint Planned() const
00216 {
00217 return this->planned;
00218 }
00219
00224 FORCEINLINE StationID Via() const
00225 {
00226 return this->via;
00227 }
00228
00233 struct Comparator {
00241 bool operator()(const FlowStat &x, const FlowStat &y) const
00242 {
00243 int diff_x = (int)x.Planned() - (int)x.Sent();
00244 int diff_y = (int)y.Planned() - (int)y.Sent();
00245 if (diff_x != diff_y) {
00246 return diff_x > diff_y;
00247 } else {
00248 return x.Via() > y.Via();
00249 }
00250 }
00251 };
00252
00258 FORCEINLINE FlowStat &operator+=(const FlowStat &other)
00259 {
00260 assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
00261 if (other.via != INVALID_STATION) this->via = other.via;
00262 this->planned += other.planned;
00263 uint sent = this->sent + other.sent;
00264 if (sent > 0) {
00265 this->length = (this->length * this->sent + other.length * other.sent) / sent;
00266 assert(this->length > 0);
00267 }
00268 this->sent = sent;
00269 return *this;
00270 }
00271
00275 FORCEINLINE void Clear()
00276 {
00277 this->planned = 0;
00278 this->sent = 0;
00279 this->via = INVALID_STATION;
00280 }
00281 };
00282
00283 typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet;
00284
00285 typedef std::map<StationID, LinkStat> LinkStatMap;
00286 typedef std::map<StationID, FlowStatSet> FlowStatMap;
00287
00288 uint GetMovingAverageLength(const Station *from, const Station *to);
00289
00290 struct GoodsEntry {
00291 enum AcceptancePickup {
00292 ACCEPTANCE,
00293 PICKUP
00294 };
00295
00296 GoodsEntry() :
00297 acceptance_pickup(0),
00298 days_since_pickup(255),
00299 rating(INITIAL_STATION_RATING),
00300 last_speed(0),
00301 last_age(255),
00302 supply(0),
00303 supply_new(0),
00304 last_component(INVALID_LINKGRAPH_COMPONENT),
00305 max_waiting_cargo(0)
00306 {}
00307
00308 byte acceptance_pickup;
00309 byte days_since_pickup;
00310 byte rating;
00311 byte last_speed;
00312 byte last_age;
00313 byte amount_fract;
00314 StationCargoList cargo;
00315 uint supply;
00316 uint supply_new;
00317 FlowStatMap flows;
00318 LinkStatMap link_stats;
00319 LinkGraphComponentID last_component;
00320 uint max_waiting_cargo;
00321 FlowStat GetSumFlowVia(StationID via) const;
00322
00323 void UpdateFlowStats(StationID source, uint count, StationID next);
00324 void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00325 void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00326
00327 StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00328 };
00329
00331 struct Airport : public TileArea {
00332 typedef PersistentStorageArray<int32, 16> PersistentStorage;
00333
00334 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00335
00336 uint64 flags;
00337 byte type;
00338 byte layout;
00339 Direction rotation;
00340 PersistentStorage psa;
00341
00347 const AirportSpec *GetSpec() const
00348 {
00349 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00350 return AirportSpec::Get(this->type);
00351 }
00352
00359 const AirportFTAClass *GetFTA() const
00360 {
00361 return this->GetSpec()->fsm;
00362 }
00363
00365 FORCEINLINE bool HasHangar() const
00366 {
00367 return this->GetSpec()->nof_depots > 0;
00368 }
00369
00378 FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00379 {
00380 const AirportSpec *as = this->GetSpec();
00381 switch (this->rotation) {
00382 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00383
00384 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00385
00386 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00387
00388 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00389
00390 default: NOT_REACHED();
00391 }
00392 }
00393
00400 FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00401 {
00402 const AirportSpec *as = this->GetSpec();
00403 for (uint i = 0; i < as->nof_depots; i++) {
00404 if (as->depot_table[i].hangar_num == hangar_num) {
00405 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00406 }
00407 }
00408 NOT_REACHED();
00409 }
00410
00417 FORCEINLINE uint GetHangarNum(TileIndex tile) const
00418 {
00419 const AirportSpec *as = this->GetSpec();
00420 for (uint i = 0; i < as->nof_depots; i++) {
00421 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00422 return as->depot_table[i].hangar_num;
00423 }
00424 }
00425 NOT_REACHED();
00426 }
00427
00429 FORCEINLINE uint GetNumHangars() const
00430 {
00431 uint num = 0;
00432 uint counted = 0;
00433 const AirportSpec *as = this->GetSpec();
00434 for (uint i = 0; i < as->nof_depots; i++) {
00435 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00436 num++;
00437 SetBit(counted, as->depot_table[i].hangar_num);
00438 }
00439 }
00440 return num;
00441 }
00442 };
00443
00444 typedef SmallVector<Industry *, 2> IndustryVector;
00445
00447 struct Station : SpecializedStation<Station, false> {
00448 public:
00449 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00450 {
00451 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00452 }
00453
00454 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00455
00456 RoadStop *bus_stops;
00457 TileArea bus_station;
00458 RoadStop *truck_stops;
00459 TileArea truck_station;
00460
00461 Airport airport;
00462 TileIndex dock_tile;
00463
00464 IndustryType indtype;
00465
00466 StationHadVehicleOfTypeByte had_vehicle_of_type;
00467
00468 byte time_since_load;
00469 byte time_since_unload;
00470
00471 byte last_vehicle_type;
00472 std::list<Vehicle *> loading_vehicles;
00473 GoodsEntry goods[NUM_CARGO];
00474 uint32 always_accepted;
00475
00476 IndustryVector industries_near;
00477
00478 Station(TileIndex tile = INVALID_TILE);
00479 ~Station();
00480
00481 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00482
00483 void MarkTilesDirty(bool cargo_change) const;
00484
00485 void UpdateVirtCoord();
00486
00487 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00488 uint GetPlatformLength(TileIndex tile) const;
00489 void RecomputeIndustriesNear();
00490 static void RecomputeIndustriesNearForAll();
00491
00492 uint GetCatchmentRadius() const;
00493 Rect GetCatchmentRect() const;
00494
00495 FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00496 {
00497 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00498 }
00499
00500 FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00501 {
00502 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00503 }
00504
00505 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00506
00507 void GetTileArea(TileArea *ta, StationType type) const;
00508
00509 void RunAverages();
00510 };
00511
00512 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00513
00514 #endif