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
00036 class FlowStat {
00037 public:
00038 typedef std::map<uint32, StationID> SharesMap;
00039
00045 inline FlowStat() {NOT_REACHED();}
00046
00052 inline FlowStat(StationID st, uint flow)
00053 {
00054 assert(flow > 0);
00055 this->shares[flow] = st;
00056 this->unrestricted = flow;
00057 }
00058
00067 inline void AppendShare(StationID st, uint flow, bool restricted = false)
00068 {
00069 assert(flow > 0);
00070 this->shares[(--this->shares.end())->first + flow] = st;
00071 if (!restricted) this->unrestricted += flow;
00072 }
00073
00074 uint GetShare(StationID st) const;
00075
00076 void ChangeShare(StationID st, int flow);
00077
00078 void RestrictShare(StationID st);
00079
00080 void ReleaseShare(StationID st);
00081
00082 void ScaleToMonthly(uint runtime);
00083
00089 inline const SharesMap *GetShares() const { return &this->shares; }
00090
00095 inline uint GetUnrestricted() const { return this->unrestricted; }
00096
00102 inline void SwapShares(FlowStat &other)
00103 {
00104 this->shares.swap(other.shares);
00105 Swap(this->unrestricted, other.unrestricted);
00106 }
00107
00116 inline StationID GetViaWithRestricted(bool &is_restricted) const
00117 {
00118 assert(!this->shares.empty());
00119 uint rand = RandomRange((--this->shares.end())->first);
00120 is_restricted = rand >= this->unrestricted;
00121 return this->shares.upper_bound(rand)->second;
00122 }
00123
00131 inline StationID GetVia() const
00132 {
00133 assert(!this->shares.empty());
00134 return this->unrestricted > 0 ?
00135 this->shares.upper_bound(RandomRange(this->unrestricted))->second :
00136 INVALID_STATION;
00137 }
00138
00139 StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00140
00141 void Invalidate();
00142
00143 private:
00144 SharesMap shares;
00145 uint unrestricted;
00146 };
00147
00149 class FlowStatMap : public std::map<StationID, FlowStat> {
00150 public:
00151 void AddFlow(StationID origin, StationID via, uint amount);
00152 void PassOnFlow(StationID origin, StationID via, uint amount);
00153 StationIDStack DeleteFlows(StationID via);
00154 void RestrictFlows(StationID via);
00155 void ReleaseFlows(StationID via);
00156 void FinalizeLocalConsumption(StationID self);
00157 };
00158
00162 struct GoodsEntry {
00164 enum GoodsEntryStatus {
00169 GES_ACCEPTANCE,
00170
00178 GES_PICKUP,
00179
00184 GES_EVER_ACCEPTED,
00185
00190 GES_LAST_MONTH,
00191
00196 GES_CURRENT_MONTH,
00197
00202 GES_ACCEPTED_BIGTICK,
00203 };
00204
00205 GoodsEntry() :
00206 acceptance_pickup(0),
00207 time_since_pickup(255),
00208 rating(INITIAL_STATION_RATING),
00209 last_speed(0),
00210 last_age(255),
00211 amount_fract(0),
00212 link_graph(INVALID_LINK_GRAPH),
00213 node(INVALID_NODE),
00214 max_waiting_cargo(0)
00215 {}
00216
00217 byte acceptance_pickup;
00218
00224 byte time_since_pickup;
00225
00226 byte rating;
00227
00237 byte last_speed;
00238
00243 byte last_age;
00244
00245 byte amount_fract;
00246 StationCargoList cargo;
00247
00248 LinkGraphID link_graph;
00249 NodeID node;
00250 FlowStatMap flows;
00251 uint max_waiting_cargo;
00252
00258 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00259
00264 inline bool HasRating() const
00265 {
00266 return HasBit(this->acceptance_pickup, GES_PICKUP);
00267 }
00268
00269 uint GetSumFlowVia(StationID via) const;
00270
00276 inline StationID GetVia(StationID source) const
00277 {
00278 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00279 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00280 }
00281
00290 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00291 {
00292 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00293 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00294 }
00295 };
00296
00298 struct Airport : public TileArea {
00299 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00300
00301 uint64 flags;
00302 byte type;
00303 byte layout;
00304 Direction rotation;
00305
00306 PersistentStorage *psa;
00307
00313 const AirportSpec *GetSpec() const
00314 {
00315 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00316 return AirportSpec::Get(this->type);
00317 }
00318
00325 const AirportFTAClass *GetFTA() const
00326 {
00327 return this->GetSpec()->fsm;
00328 }
00329
00331 inline bool HasHangar() const
00332 {
00333 return this->GetSpec()->nof_depots > 0;
00334 }
00335
00344 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00345 {
00346 const AirportSpec *as = this->GetSpec();
00347 switch (this->rotation) {
00348 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00349
00350 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00351
00352 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00353
00354 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00355
00356 default: NOT_REACHED();
00357 }
00358 }
00359
00366 inline TileIndex GetHangarTile(uint hangar_num) const
00367 {
00368 const AirportSpec *as = this->GetSpec();
00369 for (uint i = 0; i < as->nof_depots; i++) {
00370 if (as->depot_table[i].hangar_num == hangar_num) {
00371 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00372 }
00373 }
00374 NOT_REACHED();
00375 }
00376
00383 inline Direction GetHangarExitDirection(TileIndex tile) const
00384 {
00385 const AirportSpec *as = this->GetSpec();
00386 const HangarTileTable *htt = GetHangarDataByTile(tile);
00387 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00388 }
00389
00396 inline uint GetHangarNum(TileIndex tile) const
00397 {
00398 const HangarTileTable *htt = GetHangarDataByTile(tile);
00399 return htt->hangar_num;
00400 }
00401
00403 inline uint GetNumHangars() const
00404 {
00405 uint num = 0;
00406 uint counted = 0;
00407 const AirportSpec *as = this->GetSpec();
00408 for (uint i = 0; i < as->nof_depots; i++) {
00409 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00410 num++;
00411 SetBit(counted, as->depot_table[i].hangar_num);
00412 }
00413 }
00414 return num;
00415 }
00416
00417 private:
00424 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00425 {
00426 const AirportSpec *as = this->GetSpec();
00427 for (uint i = 0; i < as->nof_depots; i++) {
00428 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00429 return as->depot_table + i;
00430 }
00431 }
00432 NOT_REACHED();
00433 }
00434 };
00435
00436 typedef SmallVector<Industry *, 2> IndustryVector;
00437
00439 struct Station FINAL : SpecializedStation<Station, false> {
00440 public:
00441 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00442 {
00443 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00444 }
00445
00446 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00447
00448 RoadStop *bus_stops;
00449 TileArea bus_station;
00450 RoadStop *truck_stops;
00451 TileArea truck_station;
00452
00453 Airport airport;
00454 TileIndex dock_tile;
00455
00456 IndustryType indtype;
00457
00458 StationHadVehicleOfTypeByte had_vehicle_of_type;
00459
00460 byte time_since_load;
00461 byte time_since_unload;
00462
00463 byte last_vehicle_type;
00464 std::list<Vehicle *> loading_vehicles;
00465 GoodsEntry goods[NUM_CARGO];
00466 uint32 always_accepted;
00467
00468 IndustryVector industries_near;
00469
00470 Station(TileIndex tile = INVALID_TILE);
00471 ~Station();
00472
00473 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00474
00475 void MarkTilesDirty(bool cargo_change) const;
00476
00477 void UpdateVirtCoord();
00478
00479 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00480 uint GetPlatformLength(TileIndex tile) const;
00481 void RecomputeIndustriesNear();
00482 static void RecomputeIndustriesNearForAll();
00483
00484 uint GetCatchmentRadius() const;
00485 Rect GetCatchmentRect() const;
00486
00487 inline bool TileBelongsToRailStation(TileIndex tile) const
00488 {
00489 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00490 }
00491
00492 inline bool TileBelongsToAirport(TileIndex tile) const
00493 {
00494 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00495 }
00496
00497 uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
00498
00499 void GetTileArea(TileArea *ta, StationType type) const;
00500 };
00501
00502 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00503
00505 class AirportTileIterator : public OrthogonalTileIterator {
00506 private:
00507 const Station *st;
00508
00509 public:
00514 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00515 {
00516 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00517 }
00518
00519 inline TileIterator& operator ++()
00520 {
00521 (*this).OrthogonalTileIterator::operator++();
00522 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00523 (*this).OrthogonalTileIterator::operator++();
00524 }
00525 return *this;
00526 }
00527
00528 virtual TileIterator *Clone() const
00529 {
00530 return new AirportTileIterator(*this);
00531 }
00532 };
00533
00534 #endif