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
00293 struct GoodsEntry {
00295 enum GoodsEntryStatus {
00296 GES_ACCEPTANCE,
00297 GES_PICKUP,
00298 GES_EVER_ACCEPTED,
00299 GES_LAST_MONTH,
00300 GES_CURRENT_MONTH,
00301 GES_ACCEPTED_BIGTICK,
00302 };
00303
00304 GoodsEntry() :
00305 acceptance_pickup(0),
00306 days_since_pickup(255),
00307 rating(INITIAL_STATION_RATING),
00308 last_speed(0),
00309 last_age(255),
00310 supply(0),
00311 supply_new(0),
00312 last_component(INVALID_LINKGRAPH_COMPONENT),
00313 max_waiting_cargo(0)
00314 {}
00315
00316 byte acceptance_pickup;
00317 byte days_since_pickup;
00318 byte rating;
00319 byte last_speed;
00320 byte last_age;
00321 byte amount_fract;
00322 StationCargoList cargo;
00323 uint supply;
00324 uint supply_new;
00325 FlowStatMap flows;
00326 LinkStatMap link_stats;
00327 LinkGraphComponentID last_component;
00328 uint max_waiting_cargo;
00329 FlowStat GetSumFlowVia(StationID via) const;
00330
00331 void UpdateFlowStats(StationID source, uint count, StationID next);
00332 void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00333 void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00334
00335 StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00336 };
00337
00339 struct Airport : public TileArea {
00340 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00341
00342 uint64 flags;
00343 byte type;
00344 byte layout;
00345 Direction rotation;
00346
00347 PersistentStorage *psa;
00348
00354 const AirportSpec *GetSpec() const
00355 {
00356 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00357 return AirportSpec::Get(this->type);
00358 }
00359
00366 const AirportFTAClass *GetFTA() const
00367 {
00368 return this->GetSpec()->fsm;
00369 }
00370
00372 FORCEINLINE bool HasHangar() const
00373 {
00374 return this->GetSpec()->nof_depots > 0;
00375 }
00376
00385 FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00386 {
00387 const AirportSpec *as = this->GetSpec();
00388 switch (this->rotation) {
00389 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00390
00391 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00392
00393 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00394
00395 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00396
00397 default: NOT_REACHED();
00398 }
00399 }
00400
00407 FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00408 {
00409 const AirportSpec *as = this->GetSpec();
00410 for (uint i = 0; i < as->nof_depots; i++) {
00411 if (as->depot_table[i].hangar_num == hangar_num) {
00412 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00413 }
00414 }
00415 NOT_REACHED();
00416 }
00417
00424 FORCEINLINE Direction GetHangarExitDirection(TileIndex tile) const
00425 {
00426 const AirportSpec *as = this->GetSpec();
00427 const HangarTileTable *htt = GetHangarDataByTile(tile);
00428 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00429 }
00430
00437 FORCEINLINE uint GetHangarNum(TileIndex tile) const
00438 {
00439 const HangarTileTable *htt = GetHangarDataByTile(tile);
00440 return htt->hangar_num;
00441 }
00442
00444 FORCEINLINE uint GetNumHangars() const
00445 {
00446 uint num = 0;
00447 uint counted = 0;
00448 const AirportSpec *as = this->GetSpec();
00449 for (uint i = 0; i < as->nof_depots; i++) {
00450 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00451 num++;
00452 SetBit(counted, as->depot_table[i].hangar_num);
00453 }
00454 }
00455 return num;
00456 }
00457
00458 private:
00465 FORCEINLINE const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00466 {
00467 const AirportSpec *as = this->GetSpec();
00468 for (uint i = 0; i < as->nof_depots; i++) {
00469 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00470 return as->depot_table + i;
00471 }
00472 }
00473 NOT_REACHED();
00474 }
00475 };
00476
00477 typedef SmallVector<Industry *, 2> IndustryVector;
00478
00480 struct Station : SpecializedStation<Station, false> {
00481 public:
00482 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00483 {
00484 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00485 }
00486
00487 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00488
00489 RoadStop *bus_stops;
00490 TileArea bus_station;
00491 RoadStop *truck_stops;
00492 TileArea truck_station;
00493
00494 Airport airport;
00495 TileIndex dock_tile;
00496
00497 IndustryType indtype;
00498
00499 StationHadVehicleOfTypeByte had_vehicle_of_type;
00500
00501 byte time_since_load;
00502 byte time_since_unload;
00503
00504 byte last_vehicle_type;
00505 std::list<Vehicle *> loading_vehicles;
00506 GoodsEntry goods[NUM_CARGO];
00507 uint32 always_accepted;
00508
00509 IndustryVector industries_near;
00510
00511 Station(TileIndex tile = INVALID_TILE);
00512 ~Station();
00513
00514 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00515
00516 void MarkTilesDirty(bool cargo_change) const;
00517
00518 void UpdateVirtCoord();
00519
00520 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00521 uint GetPlatformLength(TileIndex tile) const;
00522 void RecomputeIndustriesNear();
00523 static void RecomputeIndustriesNearForAll();
00524
00525 uint GetCatchmentRadius() const;
00526 Rect GetCatchmentRect() const;
00527
00528 FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00529 {
00530 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00531 }
00532
00533 FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00534 {
00535 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00536 }
00537
00538 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00539
00540 void GetTileArea(TileArea *ta, StationType type) const;
00541
00542 void RunAverages();
00543 };
00544
00545 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00546
00547 #endif