00001
00002
00003
00004
00005
00006
00007
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
00044 class LinkStat {
00045 private:
00049 uint distance;
00050
00055 uint capacity;
00056
00060 uint timeout;
00061
00066 uint usage;
00067
00068 public:
00069 static const uint MIN_DISTANCE = 48;
00070 static const uint MOVING_AVERAGE_LENGTH = 30;
00071
00072 friend const SaveLoad *GetLinkStatDesc();
00073
00077 LinkStat() {NOT_REACHED();}
00078
00085 inline LinkStat(uint distance, uint capacity = 1, uint usage = 0) :
00086 distance(distance), capacity(capacity), timeout(distance), usage(usage)
00087 {
00088 assert(this->distance > 0);
00089 assert(this->usage <= this->capacity);
00090 }
00091
00095 inline void Clear()
00096 {
00097 this->capacity = 1;
00098 this->usage = 0;
00099 this->timeout = this->distance;
00100 }
00101
00105 inline void Decrease()
00106 {
00107 this->usage = this->usage * this->distance / (this->distance + 1);
00108 this->timeout = this->timeout * MIN_DISTANCE / (MIN_DISTANCE + 1);
00109 this->capacity = max(this->capacity * this->distance / (this->distance + 1), 1U);
00110 assert(this->usage <= this->capacity);
00111 }
00112
00117 inline uint Capacity() const
00118 {
00119 return this->capacity * LinkStat::MOVING_AVERAGE_LENGTH / this->distance;
00120 }
00121
00126 inline uint Usage() const
00127 {
00128 return this->usage * LinkStat::MOVING_AVERAGE_LENGTH / this->distance;
00129 }
00130
00136 inline void Increase(uint capacity, uint usage)
00137 {
00138 this->timeout = this->distance;
00139 this->capacity += capacity;
00140 this->usage += usage;
00141 assert(this->usage <= this->capacity);
00142 }
00143
00147 inline void Refresh(uint min_capacity)
00148 {
00149 this->capacity = max(this->capacity, min_capacity);
00150 this->timeout = this->distance;
00151 }
00152
00157 inline bool IsValid() const
00158 {
00159 return this->timeout > 0;
00160 }
00161 };
00162
00170 class FlowStat {
00171 public:
00172 typedef std::map<uint32, StationID> SharesMap;
00173
00174 inline FlowStat() {NOT_REACHED();}
00175
00176 inline FlowStat(StationID st, uint flow)
00177 {
00178 assert(flow > 0);
00179 this->shares[flow] = st;
00180 }
00181
00187 inline void AddShare(StationID st, uint flow)
00188 {
00189 assert(flow > 0);
00190 this->shares[(--this->shares.end())->first + flow] = st;
00191 }
00192
00193 uint GetShare(StationID st) const;
00194
00195 void EraseShare(StationID st);
00196
00197 inline const SharesMap *GetShares() const {return &this->shares;}
00198
00206 inline StationID GetVia() const
00207 {
00208 assert(!this->shares.empty());
00209 return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
00210 }
00211
00212 StationID GetVia(StationID excluded) const;
00213
00214 private:
00215 SharesMap shares;
00216 };
00217
00218 typedef std::map<StationID, LinkStat> LinkStatMap;
00219 typedef std::map<StationID, FlowStat> FlowStatMap;
00220
00221 uint GetMovingAverageLength(const Station *from, const Station *to);
00222
00226 struct GoodsEntry {
00228 enum GoodsEntryStatus {
00233 GES_ACCEPTANCE,
00234
00242 GES_PICKUP,
00243
00248 GES_EVER_ACCEPTED,
00249
00254 GES_LAST_MONTH,
00255
00260 GES_CURRENT_MONTH,
00261
00266 GES_ACCEPTED_BIGTICK,
00267 };
00268
00269 GoodsEntry() :
00270 acceptance_pickup(0),
00271 time_since_pickup(255),
00272 rating(INITIAL_STATION_RATING),
00273 last_speed(0),
00274 last_age(255),
00275 supply(0),
00276 supply_new(0),
00277 last_component(INVALID_LINKGRAPH_COMPONENT),
00278 max_waiting_cargo(0)
00279 {}
00280
00281 byte acceptance_pickup;
00282
00288 byte time_since_pickup;
00289
00290 byte rating;
00291
00301 byte last_speed;
00302
00307 byte last_age;
00308
00309 byte amount_fract;
00310 StationCargoList cargo;
00311
00312 uint supply;
00313 uint supply_new;
00314 FlowStatMap flows;
00315 LinkStatMap link_stats;
00316
00317 LinkGraphComponentID last_component;
00318 uint max_waiting_cargo;
00319
00325 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00326 uint GetSumFlowVia(StationID via) const;
00327
00336 inline StationID GetVia(StationID source, StationID excluded = INVALID_STATION) const
00337 {
00338 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00339 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded) : INVALID_STATION;
00340 }
00341 };
00342
00344 struct Airport : public TileArea {
00345 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00346
00347 uint64 flags;
00348 byte type;
00349 byte layout;
00350 Direction rotation;
00351
00352 PersistentStorage *psa;
00353
00359 const AirportSpec *GetSpec() const
00360 {
00361 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00362 return AirportSpec::Get(this->type);
00363 }
00364
00371 const AirportFTAClass *GetFTA() const
00372 {
00373 return this->GetSpec()->fsm;
00374 }
00375
00377 inline bool HasHangar() const
00378 {
00379 return this->GetSpec()->nof_depots > 0;
00380 }
00381
00390 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00391 {
00392 const AirportSpec *as = this->GetSpec();
00393 switch (this->rotation) {
00394 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00395
00396 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00397
00398 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00399
00400 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00401
00402 default: NOT_REACHED();
00403 }
00404 }
00405
00412 inline TileIndex GetHangarTile(uint hangar_num) const
00413 {
00414 const AirportSpec *as = this->GetSpec();
00415 for (uint i = 0; i < as->nof_depots; i++) {
00416 if (as->depot_table[i].hangar_num == hangar_num) {
00417 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00418 }
00419 }
00420 NOT_REACHED();
00421 }
00422
00429 inline Direction GetHangarExitDirection(TileIndex tile) const
00430 {
00431 const AirportSpec *as = this->GetSpec();
00432 const HangarTileTable *htt = GetHangarDataByTile(tile);
00433 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00434 }
00435
00442 inline uint GetHangarNum(TileIndex tile) const
00443 {
00444 const HangarTileTable *htt = GetHangarDataByTile(tile);
00445 return htt->hangar_num;
00446 }
00447
00449 inline uint GetNumHangars() const
00450 {
00451 uint num = 0;
00452 uint counted = 0;
00453 const AirportSpec *as = this->GetSpec();
00454 for (uint i = 0; i < as->nof_depots; i++) {
00455 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00456 num++;
00457 SetBit(counted, as->depot_table[i].hangar_num);
00458 }
00459 }
00460 return num;
00461 }
00462
00463 private:
00470 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00471 {
00472 const AirportSpec *as = this->GetSpec();
00473 for (uint i = 0; i < as->nof_depots; i++) {
00474 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00475 return as->depot_table + i;
00476 }
00477 }
00478 NOT_REACHED();
00479 }
00480 };
00481
00482 typedef SmallVector<Industry *, 2> IndustryVector;
00483
00485 struct Station FINAL : SpecializedStation<Station, false> {
00486 public:
00487 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00488 {
00489 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00490 }
00491
00492 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00493
00494 RoadStop *bus_stops;
00495 TileArea bus_station;
00496 RoadStop *truck_stops;
00497 TileArea truck_station;
00498
00499 Airport airport;
00500 TileIndex dock_tile;
00501
00502 IndustryType indtype;
00503
00504 StationHadVehicleOfTypeByte had_vehicle_of_type;
00505
00506 byte time_since_load;
00507 byte time_since_unload;
00508
00509 byte last_vehicle_type;
00510 std::list<Vehicle *> loading_vehicles;
00511 GoodsEntry goods[NUM_CARGO];
00512 uint32 always_accepted;
00513
00514 IndustryVector industries_near;
00515
00516 Station(TileIndex tile = INVALID_TILE);
00517 ~Station();
00518
00519 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00520
00521 void MarkTilesDirty(bool cargo_change) const;
00522
00523 void UpdateVirtCoord();
00524
00525 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00526 uint GetPlatformLength(TileIndex tile) const;
00527 void RecomputeIndustriesNear();
00528 static void RecomputeIndustriesNearForAll();
00529
00530 uint GetCatchmentRadius() const;
00531 Rect GetCatchmentRect() const;
00532
00533 inline bool TileBelongsToRailStation(TileIndex tile) const
00534 {
00535 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00536 }
00537
00538 inline bool TileBelongsToAirport(TileIndex tile) const
00539 {
00540 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00541 }
00542
00543 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00544
00545 void GetTileArea(TileArea *ta, StationType type) const;
00546
00547 void RunAverages();
00548 };
00549
00550 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00551
00553 class AirportTileIterator : public OrthogonalTileIterator {
00554 private:
00555 const Station *st;
00556
00557 public:
00562 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00563 {
00564 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00565 }
00566
00567 inline TileIterator& operator ++()
00568 {
00569 (*this).OrthogonalTileIterator::operator++();
00570 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00571 (*this).OrthogonalTileIterator::operator++();
00572 }
00573 return *this;
00574 }
00575
00576 virtual TileIterator *Clone() const
00577 {
00578 return new AirportTileIterator(*this);
00579 }
00580 };
00581
00582 #endif