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 "newgrf_storage.h"
00020 #include "linkgraph/linkgraph_type.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 frozen;
00050
00055 uint usage;
00056
00057 public:
00061 static const uint MIN_AVERAGE_LENGTH = 96;
00062
00063 friend const SaveLoad *GetLinkStatDesc();
00064
00065 FORCEINLINE LinkStat(uint distance = 1, uint capacity = 0, uint frozen = 0, uint usage = 0) :
00066 MovingAverage<uint>(distance), capacity(capacity), frozen(frozen), usage(usage) {}
00067
00071 FORCEINLINE void Clear()
00072 {
00073 this->capacity = 0;
00074 this->usage = 0;
00075 this->frozen = 0;
00076 }
00077
00081 FORCEINLINE void Decrease()
00082 {
00083 this->MovingAverage<uint>::Decrease(this->usage);
00084 this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), this->frozen);
00085 }
00086
00091 FORCEINLINE uint Capacity() const
00092 {
00093 return this->MovingAverage<uint>::Monthly(this->capacity);
00094 }
00095
00100 FORCEINLINE uint Usage() const
00101 {
00102 return this->MovingAverage<uint>::Monthly(this->usage);
00103 }
00104
00109 FORCEINLINE uint Frozen() const
00110 {
00111 return this->frozen;
00112 }
00113
00119 FORCEINLINE void Increase(uint capacity, uint usage)
00120 {
00121 this->capacity += capacity;
00122 this->usage += usage;
00123 }
00124
00130 FORCEINLINE void Freeze(uint capacity)
00131 {
00132 this->frozen += capacity;
00133 this->capacity = max(this->frozen, this->capacity);
00134 }
00135
00140 FORCEINLINE void Unfreeze(uint capacity)
00141 {
00142 this->frozen -= capacity;
00143 }
00144
00148 FORCEINLINE void Unfreeze()
00149 {
00150 this->frozen = 0;
00151 }
00152
00158 FORCEINLINE bool IsNull() const
00159 {
00160 return this->capacity == 0;
00161 }
00162 };
00163
00167 class FlowStat : private MovingAverage<uint> {
00168 private:
00169 uint planned;
00170 uint sent;
00171 StationID via;
00172
00173 public:
00174 friend const SaveLoad *GetFlowStatDesc();
00175
00183 FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
00184 MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
00185
00191 FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
00192 MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
00193
00197 FORCEINLINE FlowStat GetDecreasedCopy() const
00198 {
00199 FlowStat ret(this->length, this->via, this->planned, this->sent);
00200 this->MovingAverage<uint>::Decrease(ret.sent);
00201 return ret;
00202 }
00203
00208 FORCEINLINE void Increase(uint sent)
00209 {
00210 this->sent += sent;
00211 }
00212
00217 FORCEINLINE uint Sent() const
00218 {
00219 return this->MovingAverage<uint>::Monthly(sent);
00220 }
00221
00226 FORCEINLINE uint Planned() const
00227 {
00228 return this->planned;
00229 }
00230
00235 FORCEINLINE StationID Via() const
00236 {
00237 return this->via;
00238 }
00239
00244 struct Comparator {
00252 bool operator()(const FlowStat &x, const FlowStat &y) const {
00253 int diff_x = (int)x.Planned() - (int)x.Sent();
00254 int diff_y = (int)y.Planned() - (int)y.Sent();
00255 if (diff_x != diff_y) {
00256 return diff_x > diff_y;
00257 } else {
00258 return x.Via() > y.Via();
00259 }
00260 }
00261 };
00262
00268 FORCEINLINE FlowStat &operator+=(const FlowStat &other)
00269 {
00270 assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
00271 if (other.via != INVALID_STATION) this->via = other.via;
00272 this->planned += other.planned;
00273 uint sent = this->sent + other.sent;
00274 if (sent > 0) {
00275 this->length = (this->length * this->sent + other.length * other.sent) / sent;
00276 assert(this->length > 0);
00277 }
00278 this->sent = sent;
00279 return *this;
00280 }
00281
00285 FORCEINLINE void Clear()
00286 {
00287 this->planned = 0;
00288 this->sent = 0;
00289 this->via = INVALID_STATION;
00290 }
00291 };
00292
00293 typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet;
00294
00295 typedef std::map<StationID, LinkStat> LinkStatMap;
00296 typedef std::map<StationID, FlowStatSet> FlowStatMap;
00297
00298 uint GetMovingAverageLength(const Station *from, const Station *to);
00299
00303 struct GoodsEntry {
00305 enum GoodsEntryStatus {
00306 GES_ACCEPTANCE,
00307 GES_PICKUP,
00308 GES_EVER_ACCEPTED,
00309 GES_LAST_MONTH,
00310 GES_CURRENT_MONTH,
00311 GES_ACCEPTED_BIGTICK,
00312 };
00313
00314 GoodsEntry() :
00315 acceptance_pickup(0),
00316 days_since_pickup(255),
00317 rating(INITIAL_STATION_RATING),
00318 last_speed(0),
00319 last_age(255),
00320 supply(0),
00321 supply_new(0),
00322 last_component(INVALID_LINKGRAPH_COMPONENT),
00323 max_waiting_cargo(0)
00324 {}
00325
00326 byte acceptance_pickup;
00327 byte days_since_pickup;
00328 byte rating;
00329 byte last_speed;
00330 byte last_age;
00331 byte amount_fract;
00332 StationCargoList cargo;
00333 uint supply;
00334 uint supply_new;
00335 FlowStatMap flows;
00336 LinkStatMap link_stats;
00337 LinkGraphComponentID last_component;
00338 uint max_waiting_cargo;
00339
00340 FlowStat GetSumFlowVia(StationID via) const;
00341
00342 void UpdateFlowStats(StationID source, uint count, StationID next);
00343 void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00344 void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00345
00346 StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00347 };
00348
00350 struct Airport : public TileArea {
00351 typedef PersistentStorageArray<int32, 16> PersistentStorage;
00352
00353 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00354
00355 uint64 flags;
00356 byte type;
00357 byte layout;
00358 Direction rotation;
00359 PersistentStorage psa;
00360
00366 const AirportSpec *GetSpec() const
00367 {
00368 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00369 return AirportSpec::Get(this->type);
00370 }
00371
00378 const AirportFTAClass *GetFTA() const
00379 {
00380 return this->GetSpec()->fsm;
00381 }
00382
00384 FORCEINLINE bool HasHangar() const
00385 {
00386 return this->GetSpec()->nof_depots > 0;
00387 }
00388
00397 FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00398 {
00399 const AirportSpec *as = this->GetSpec();
00400 switch (this->rotation) {
00401 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00402
00403 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00404
00405 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00406
00407 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00408
00409 default: NOT_REACHED();
00410 }
00411 }
00412
00419 FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00420 {
00421 const AirportSpec *as = this->GetSpec();
00422 for (uint i = 0; i < as->nof_depots; i++) {
00423 if (as->depot_table[i].hangar_num == hangar_num) {
00424 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00425 }
00426 }
00427 NOT_REACHED();
00428 }
00429
00436 FORCEINLINE uint GetHangarNum(TileIndex tile) const
00437 {
00438 const AirportSpec *as = this->GetSpec();
00439 for (uint i = 0; i < as->nof_depots; i++) {
00440 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00441 return as->depot_table[i].hangar_num;
00442 }
00443 }
00444 NOT_REACHED();
00445 }
00446
00448 FORCEINLINE uint GetNumHangars() const
00449 {
00450 uint num = 0;
00451 uint counted = 0;
00452 const AirportSpec *as = this->GetSpec();
00453 for (uint i = 0; i < as->nof_depots; i++) {
00454 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00455 num++;
00456 SetBit(counted, as->depot_table[i].hangar_num);
00457 }
00458 }
00459 return num;
00460 }
00461 };
00462
00463 typedef SmallVector<Industry *, 2> IndustryVector;
00464
00466 struct Station : SpecializedStation<Station, false> {
00467 public:
00468 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00469 {
00470 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00471 }
00472
00473 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00474
00475 RoadStop *bus_stops;
00476 TileArea bus_station;
00477 RoadStop *truck_stops;
00478 TileArea truck_station;
00479
00480 Airport airport;
00481 TileIndex dock_tile;
00482
00483 IndustryType indtype;
00484
00485 StationHadVehicleOfTypeByte had_vehicle_of_type;
00486
00487 byte time_since_load;
00488 byte time_since_unload;
00489
00490 byte last_vehicle_type;
00491 std::list<Vehicle *> loading_vehicles;
00492 GoodsEntry goods[NUM_CARGO];
00493 uint32 always_accepted;
00494
00495 IndustryVector industries_near;
00496
00497 Station(TileIndex tile = INVALID_TILE);
00498 ~Station();
00499
00500 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00501
00502 void MarkTilesDirty(bool cargo_change) const;
00503
00504 void UpdateVirtCoord();
00505
00506 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00507 uint GetPlatformLength(TileIndex tile) const;
00508 void RecomputeIndustriesNear();
00509 static void RecomputeIndustriesNearForAll();
00510
00511 uint GetCatchmentRadius() const;
00512 Rect GetCatchmentRect() const;
00513
00514 FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00515 {
00516 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00517 }
00518
00519 FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00520 {
00521 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00522 }
00523
00524 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00525
00526 void GetTileArea(TileArea *ta, StationType type) const;
00527
00528 void RunAverages();
00529 };
00530
00531 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00532
00533 #endif