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 "town.h"
00023 #include <map>
00024 #include <set>
00025
00026 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
00027 extern StationPool _station_pool;
00028
00029 static const byte INITIAL_STATION_RATING = 175;
00030
00039 class LinkStat : private MovingAverage<uint> {
00040 private:
00045 uint capacity;
00046
00050 uint timeout;
00051
00056 uint usage;
00057
00058 public:
00062 static const uint MIN_AVERAGE_LENGTH = 48;
00063
00064 friend const SaveLoad *GetLinkStatDesc();
00065
00069 LinkStat() : MovingAverage<uint>(0) {NOT_REACHED();}
00070
00077 FORCEINLINE LinkStat(uint distance, uint capacity = 1, uint usage = 0) :
00078 MovingAverage<uint>(distance), capacity(capacity), timeout(distance), usage(usage)
00079 {
00080 assert(this->usage <= this->capacity);
00081 }
00082
00086 FORCEINLINE void Clear()
00087 {
00088 this->capacity = 1;
00089 this->usage = 0;
00090 this->timeout = this->length;
00091 }
00092
00096 FORCEINLINE void Decrease()
00097 {
00098 this->MovingAverage<uint>::Decrease(this->usage);
00099 this->timeout = this->timeout * MIN_AVERAGE_LENGTH / (MIN_AVERAGE_LENGTH + 1);
00100 this->capacity = max(this->MovingAverage<uint>::Decrease(this->capacity), (uint)1);
00101 assert(this->usage <= this->capacity);
00102 }
00103
00108 FORCEINLINE uint Capacity() const
00109 {
00110 return this->MovingAverage<uint>::Monthly(this->capacity);
00111 }
00112
00117 FORCEINLINE uint Usage() const
00118 {
00119 return this->MovingAverage<uint>::Monthly(this->usage);
00120 }
00121
00127 FORCEINLINE void Increase(uint capacity, uint usage)
00128 {
00129 this->timeout = this->length;
00130 this->capacity += capacity;
00131 this->usage += usage;
00132 assert(this->usage <= this->capacity);
00133 }
00134
00138 FORCEINLINE void Refresh(uint min_capacity)
00139 {
00140 this->capacity = max(this->capacity, min_capacity);
00141 this->timeout = this->length;
00142 }
00143
00148 FORCEINLINE bool IsValid() const
00149 {
00150 return this->timeout > 0;
00151 }
00152 };
00153
00157 class FlowStat : private MovingAverage<uint> {
00158 private:
00159 uint planned;
00160 uint sent;
00161 StationID via;
00162
00163 public:
00164 friend const SaveLoad *GetFlowStatDesc();
00165
00173 FORCEINLINE FlowStat(uint distance = 1, StationID st = INVALID_STATION, uint planned = 0, uint sent = 0) :
00174 MovingAverage<uint>(distance), planned(planned), sent(sent), via(st) {}
00175
00181 FORCEINLINE FlowStat(const FlowStat &prev, uint new_plan) :
00182 MovingAverage<uint>(prev.length), planned(new_plan), sent(prev.sent), via(prev.via) {}
00183
00187 FORCEINLINE FlowStat GetDecreasedCopy() const
00188 {
00189 FlowStat ret(this->length, this->via, this->planned, this->sent);
00190 this->MovingAverage<uint>::Decrease(ret.sent);
00191 return ret;
00192 }
00193
00198 FORCEINLINE void Increase(uint sent)
00199 {
00200 this->sent += sent;
00201 }
00202
00207 FORCEINLINE uint Sent() const
00208 {
00209 return this->MovingAverage<uint>::Monthly(sent);
00210 }
00211
00216 FORCEINLINE uint Planned() const
00217 {
00218 return this->planned;
00219 }
00220
00225 FORCEINLINE StationID Via() const
00226 {
00227 return this->via;
00228 }
00229
00234 struct Comparator {
00242 bool operator()(const FlowStat &x, const FlowStat &y) const
00243 {
00244 int diff_x = (int)x.Planned() - (int)x.Sent();
00245 int diff_y = (int)y.Planned() - (int)y.Sent();
00246 if (diff_x != diff_y) {
00247 return diff_x > diff_y;
00248 } else {
00249 return x.Via() > y.Via();
00250 }
00251 }
00252 };
00253
00259 FORCEINLINE FlowStat &operator+=(const FlowStat &other)
00260 {
00261 assert(this->via == INVALID_STATION || other.via == INVALID_STATION || this->via == other.via);
00262 if (other.via != INVALID_STATION) this->via = other.via;
00263 this->planned += other.planned;
00264 uint sent = this->sent + other.sent;
00265 if (sent > 0) {
00266 this->length = (this->length * this->sent + other.length * other.sent) / sent;
00267 assert(this->length > 0);
00268 }
00269 this->sent = sent;
00270 return *this;
00271 }
00272
00276 FORCEINLINE void Clear()
00277 {
00278 this->planned = 0;
00279 this->sent = 0;
00280 this->via = INVALID_STATION;
00281 }
00282 };
00283
00284 typedef std::set<FlowStat, FlowStat::Comparator> FlowStatSet;
00285
00286 typedef std::map<StationID, LinkStat> LinkStatMap;
00287 typedef std::map<StationID, FlowStatSet> FlowStatMap;
00288
00289 uint GetMovingAverageLength(const Station *from, const Station *to);
00290
00294 struct GoodsEntry {
00296 enum GoodsEntryStatus {
00297 GES_ACCEPTANCE,
00298 GES_PICKUP,
00299 GES_EVER_ACCEPTED,
00300 GES_LAST_MONTH,
00301 GES_CURRENT_MONTH,
00302 GES_ACCEPTED_BIGTICK,
00303 };
00304
00305 GoodsEntry() :
00306 acceptance_pickup(0),
00307 days_since_pickup(255),
00308 rating(INITIAL_STATION_RATING),
00309 last_speed(0),
00310 last_age(255),
00311 supply(0),
00312 supply_new(0),
00313 last_component(INVALID_LINKGRAPH_COMPONENT),
00314 max_waiting_cargo(0)
00315 {}
00316
00317 byte acceptance_pickup;
00318 byte days_since_pickup;
00319 byte rating;
00320 byte last_speed;
00321 byte last_age;
00322 byte amount_fract;
00323 StationCargoList cargo;
00324 uint supply;
00325 uint supply_new;
00326 FlowStatMap flows;
00327 LinkStatMap link_stats;
00328 LinkGraphComponentID last_component;
00329 uint max_waiting_cargo;
00330 FlowStat GetSumFlowVia(StationID via) const;
00331
00332 void UpdateFlowStats(StationID source, uint count, StationID next);
00333 void UpdateFlowStats(FlowStatSet &flow_stats, uint count, StationID next);
00334 void UpdateFlowStats(FlowStatSet &flow_stats, FlowStatSet::iterator flow_it, uint count);
00335
00336 StationID UpdateFlowStatsTransfer(StationID source, uint count, StationID curr);
00337 };
00338
00340 struct Airport : public TileArea {
00341 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00342
00343 uint64 flags;
00344 byte type;
00345 byte layout;
00346 Direction rotation;
00347
00348 PersistentStorage *psa;
00349
00355 const AirportSpec *GetSpec() const
00356 {
00357 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00358 return AirportSpec::Get(this->type);
00359 }
00360
00367 const AirportFTAClass *GetFTA() const
00368 {
00369 return this->GetSpec()->fsm;
00370 }
00371
00373 FORCEINLINE bool HasHangar() const
00374 {
00375 return this->GetSpec()->nof_depots > 0;
00376 }
00377
00386 FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00387 {
00388 const AirportSpec *as = this->GetSpec();
00389 switch (this->rotation) {
00390 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00391
00392 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00393
00394 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00395
00396 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00397
00398 default: NOT_REACHED();
00399 }
00400 }
00401
00408 FORCEINLINE TileIndex GetHangarTile(uint hangar_num) const
00409 {
00410 const AirportSpec *as = this->GetSpec();
00411 for (uint i = 0; i < as->nof_depots; i++) {
00412 if (as->depot_table[i].hangar_num == hangar_num) {
00413 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00414 }
00415 }
00416 NOT_REACHED();
00417 }
00418
00425 FORCEINLINE Direction GetHangarExitDirection(TileIndex tile) const
00426 {
00427 const AirportSpec *as = this->GetSpec();
00428 const HangarTileTable *htt = GetHangarDataByTile(tile);
00429 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00430 }
00431
00438 FORCEINLINE uint GetHangarNum(TileIndex tile) const
00439 {
00440 const HangarTileTable *htt = GetHangarDataByTile(tile);
00441 return htt->hangar_num;
00442 }
00443
00445 FORCEINLINE uint GetNumHangars() const
00446 {
00447 uint num = 0;
00448 uint counted = 0;
00449 const AirportSpec *as = this->GetSpec();
00450 for (uint i = 0; i < as->nof_depots; i++) {
00451 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00452 num++;
00453 SetBit(counted, as->depot_table[i].hangar_num);
00454 }
00455 }
00456 return num;
00457 }
00458
00459 private:
00466 FORCEINLINE const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00467 {
00468 const AirportSpec *as = this->GetSpec();
00469 for (uint i = 0; i < as->nof_depots; i++) {
00470 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00471 return as->depot_table + i;
00472 }
00473 }
00474 NOT_REACHED();
00475 }
00476 };
00477
00478 typedef SmallVector<Industry *, 2> IndustryVector;
00479
00481 struct Station : SpecializedStation<Station, false> {
00482 public:
00483 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00484 {
00485 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00486 }
00487
00488 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00489
00490 RoadStop *bus_stops;
00491 TileArea bus_station;
00492 RoadStop *truck_stops;
00493 TileArea truck_station;
00494
00495 Airport airport;
00496 TileIndex dock_tile;
00497
00498 IndustryType indtype;
00499
00500 StationHadVehicleOfTypeByte had_vehicle_of_type;
00501
00502 byte time_since_load;
00503 byte time_since_unload;
00504
00505 byte last_vehicle_type;
00506 std::list<Vehicle *> loading_vehicles;
00507 GoodsEntry goods[NUM_CARGO];
00508 uint32 always_accepted;
00509
00510 IndustryVector industries_near;
00511
00512 Station(TileIndex tile = INVALID_TILE);
00513 ~Station();
00514
00515 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00516
00517 void MarkTilesDirty(bool cargo_change) const;
00518
00519 void UpdateVirtCoord();
00520
00521 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00522 uint GetPlatformLength(TileIndex tile) const;
00523 void RecomputeIndustriesNear();
00524 static void RecomputeIndustriesNearForAll();
00525
00526 uint GetCatchmentRadius() const;
00527 Rect GetCatchmentRect() const;
00528
00529 FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
00530 {
00531 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00532 }
00533
00534 FORCEINLINE bool TileBelongsToAirport(TileIndex tile) const
00535 {
00536 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00537 }
00538
00539 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00540
00541 void GetTileArea(TileArea *ta, StationType type) const;
00542
00543 void RunAverages();
00544 };
00545
00546 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00547
00549 class AirportTileIterator : public OrthogonalTileIterator {
00550 private:
00551 const Station *st;
00552
00553 public:
00558 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00559 {
00560 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00561 }
00562
00563 FORCEINLINE TileIterator& operator ++()
00564 {
00565 (*this).OrthogonalTileIterator::operator++();
00566 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00567 (*this).OrthogonalTileIterator::operator++();
00568 }
00569 return *this;
00570 }
00571
00572 virtual TileIterator *Clone() const
00573 {
00574 return new AirportTileIterator(*this);
00575 }
00576 };
00577
00578 #endif