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 }
00057
00065 inline void AppendShare(StationID st, uint flow)
00066 {
00067 assert(flow > 0);
00068 this->shares[(--this->shares.end())->first + flow] = st;
00069 }
00070
00071 uint GetShare(StationID st) const;
00072
00073 void ChangeShare(StationID st, int flow);
00074
00080 inline const SharesMap *GetShares() const { return &this->shares; }
00081
00089 inline StationID GetVia() const
00090 {
00091 assert(!this->shares.empty());
00092 return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second;
00093 }
00094
00095 StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
00096
00097 private:
00098 SharesMap shares;
00099 };
00100
00102 class FlowStatMap : public std::map<StationID, FlowStat> {
00103 public:
00104 void AddFlow(StationID origin, StationID via, uint amount);
00105 void PassOnFlow(StationID origin, StationID via, uint amount);
00106 void DeleteFlows(StationID via);
00107 void FinalizeLocalConsumption(StationID self);
00108 };
00109
00113 struct GoodsEntry {
00115 enum GoodsEntryStatus {
00120 GES_ACCEPTANCE,
00121
00129 GES_PICKUP,
00130
00135 GES_EVER_ACCEPTED,
00136
00141 GES_LAST_MONTH,
00142
00147 GES_CURRENT_MONTH,
00148
00153 GES_ACCEPTED_BIGTICK,
00154 };
00155
00156 GoodsEntry() :
00157 acceptance_pickup(0),
00158 time_since_pickup(255),
00159 rating(INITIAL_STATION_RATING),
00160 last_speed(0),
00161 last_age(255),
00162 link_graph(INVALID_LINK_GRAPH),
00163 node(INVALID_NODE),
00164 max_waiting_cargo(0)
00165 {}
00166
00167 byte acceptance_pickup;
00168
00174 byte time_since_pickup;
00175
00176 byte rating;
00177
00187 byte last_speed;
00188
00193 byte last_age;
00194
00195 byte amount_fract;
00196 StationCargoList cargo;
00197
00198 LinkGraphID link_graph;
00199 NodeID node;
00200 FlowStatMap flows;
00201 uint max_waiting_cargo;
00202
00208 bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
00209
00214 inline bool HasRating() const
00215 {
00216 return HasBit(this->acceptance_pickup, GES_PICKUP);
00217 }
00218
00219 uint GetSumFlowVia(StationID via) const;
00220
00226 inline StationID GetVia(StationID source) const
00227 {
00228 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00229 return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
00230 }
00231
00240 inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
00241 {
00242 FlowStatMap::const_iterator flow_it(this->flows.find(source));
00243 return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
00244 }
00245 };
00246
00248 struct Airport : public TileArea {
00249 Airport() : TileArea(INVALID_TILE, 0, 0) {}
00250
00251 uint64 flags;
00252 byte type;
00253 byte layout;
00254 Direction rotation;
00255
00256 PersistentStorage *psa;
00257
00263 const AirportSpec *GetSpec() const
00264 {
00265 if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
00266 return AirportSpec::Get(this->type);
00267 }
00268
00275 const AirportFTAClass *GetFTA() const
00276 {
00277 return this->GetSpec()->fsm;
00278 }
00279
00281 inline bool HasHangar() const
00282 {
00283 return this->GetSpec()->nof_depots > 0;
00284 }
00285
00294 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
00295 {
00296 const AirportSpec *as = this->GetSpec();
00297 switch (this->rotation) {
00298 case DIR_N: return this->tile + ToTileIndexDiff(tidc);
00299
00300 case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
00301
00302 case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
00303
00304 case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
00305
00306 default: NOT_REACHED();
00307 }
00308 }
00309
00316 inline TileIndex GetHangarTile(uint hangar_num) const
00317 {
00318 const AirportSpec *as = this->GetSpec();
00319 for (uint i = 0; i < as->nof_depots; i++) {
00320 if (as->depot_table[i].hangar_num == hangar_num) {
00321 return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
00322 }
00323 }
00324 NOT_REACHED();
00325 }
00326
00333 inline Direction GetHangarExitDirection(TileIndex tile) const
00334 {
00335 const AirportSpec *as = this->GetSpec();
00336 const HangarTileTable *htt = GetHangarDataByTile(tile);
00337 return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
00338 }
00339
00346 inline uint GetHangarNum(TileIndex tile) const
00347 {
00348 const HangarTileTable *htt = GetHangarDataByTile(tile);
00349 return htt->hangar_num;
00350 }
00351
00353 inline uint GetNumHangars() const
00354 {
00355 uint num = 0;
00356 uint counted = 0;
00357 const AirportSpec *as = this->GetSpec();
00358 for (uint i = 0; i < as->nof_depots; i++) {
00359 if (!HasBit(counted, as->depot_table[i].hangar_num)) {
00360 num++;
00361 SetBit(counted, as->depot_table[i].hangar_num);
00362 }
00363 }
00364 return num;
00365 }
00366
00367 private:
00374 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
00375 {
00376 const AirportSpec *as = this->GetSpec();
00377 for (uint i = 0; i < as->nof_depots; i++) {
00378 if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
00379 return as->depot_table + i;
00380 }
00381 }
00382 NOT_REACHED();
00383 }
00384 };
00385
00386 typedef SmallVector<Industry *, 2> IndustryVector;
00387
00389 struct Station FINAL : SpecializedStation<Station, false> {
00390 public:
00391 RoadStop *GetPrimaryRoadStop(RoadStopType type) const
00392 {
00393 return type == ROADSTOP_BUS ? bus_stops : truck_stops;
00394 }
00395
00396 RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
00397
00398 RoadStop *bus_stops;
00399 TileArea bus_station;
00400 RoadStop *truck_stops;
00401 TileArea truck_station;
00402
00403 Airport airport;
00404 TileIndex dock_tile;
00405
00406 IndustryType indtype;
00407
00408 StationHadVehicleOfTypeByte had_vehicle_of_type;
00409
00410 byte time_since_load;
00411 byte time_since_unload;
00412
00413 byte last_vehicle_type;
00414 std::list<Vehicle *> loading_vehicles;
00415 GoodsEntry goods[NUM_CARGO];
00416 uint32 always_accepted;
00417
00418 IndustryVector industries_near;
00419
00420 Station(TileIndex tile = INVALID_TILE);
00421 ~Station();
00422
00423 void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
00424
00425 void MarkTilesDirty(bool cargo_change) const;
00426
00427 void UpdateVirtCoord();
00428
00429 uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
00430 uint GetPlatformLength(TileIndex tile) const;
00431 void RecomputeIndustriesNear();
00432 static void RecomputeIndustriesNearForAll();
00433
00434 uint GetCatchmentRadius() const;
00435 Rect GetCatchmentRect() const;
00436
00437 inline bool TileBelongsToRailStation(TileIndex tile) const
00438 {
00439 return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
00440 }
00441
00442 inline bool TileBelongsToAirport(TileIndex tile) const
00443 {
00444 return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
00445 }
00446
00447 uint32 GetNewGRFVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) const;
00448
00449 void GetTileArea(TileArea *ta, StationType type) const;
00450
00451 void RunAverages();
00452 };
00453
00454 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
00455
00457 class AirportTileIterator : public OrthogonalTileIterator {
00458 private:
00459 const Station *st;
00460
00461 public:
00466 AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
00467 {
00468 if (!st->TileBelongsToAirport(this->tile)) ++(*this);
00469 }
00470
00471 inline TileIterator& operator ++()
00472 {
00473 (*this).OrthogonalTileIterator::operator++();
00474 while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
00475 (*this).OrthogonalTileIterator::operator++();
00476 }
00477 return *this;
00478 }
00479
00480 virtual TileIterator *Clone() const
00481 {
00482 return new AirportTileIterator(*this);
00483 }
00484 };
00485
00486 #endif