OpenTTD
station_base.h
Go to the documentation of this file.
1 /* $Id: station_base.h 27178 2015-03-07 18:27:01Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #ifndef STATION_BASE_H
13 #define STATION_BASE_H
14 
15 #include "core/random_func.hpp"
16 #include "base_station_base.h"
17 #include "newgrf_airport.h"
18 #include "cargopacket.h"
19 #include "industry_type.h"
21 #include "newgrf_storage.h"
22 #include <map>
23 
26 
27 static const byte INITIAL_STATION_RATING = 175;
28 
36 class FlowStat {
37 public:
38  typedef std::map<uint32, StationID> SharesMap;
39 
40  static const SharesMap empty_sharesmap;
41 
47  inline FlowStat() {NOT_REACHED();}
48 
55  inline FlowStat(StationID st, uint flow, bool restricted = false)
56  {
57  assert(flow > 0);
58  this->shares[flow] = st;
59  this->unrestricted = restricted ? 0 : flow;
60  }
61 
70  inline void AppendShare(StationID st, uint flow, bool restricted = false)
71  {
72  assert(flow > 0);
73  this->shares[(--this->shares.end())->first + flow] = st;
74  if (!restricted) this->unrestricted += flow;
75  }
76 
77  uint GetShare(StationID st) const;
78 
79  void ChangeShare(StationID st, int flow);
80 
81  void RestrictShare(StationID st);
82 
83  void ReleaseShare(StationID st);
84 
85  void ScaleToMonthly(uint runtime);
86 
92  inline const SharesMap *GetShares() const { return &this->shares; }
93 
98  inline uint GetUnrestricted() const { return this->unrestricted; }
99 
105  inline void SwapShares(FlowStat &other)
106  {
107  this->shares.swap(other.shares);
108  Swap(this->unrestricted, other.unrestricted);
109  }
110 
119  inline StationID GetViaWithRestricted(bool &is_restricted) const
120  {
121  assert(!this->shares.empty());
122  uint rand = RandomRange((--this->shares.end())->first);
123  is_restricted = rand >= this->unrestricted;
124  return this->shares.upper_bound(rand)->second;
125  }
126 
134  inline StationID GetVia() const
135  {
136  assert(!this->shares.empty());
137  return this->unrestricted > 0 ?
138  this->shares.upper_bound(RandomRange(this->unrestricted))->second :
139  INVALID_STATION;
140  }
141 
142  StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
143 
144  void Invalidate();
145 
146 private:
147  SharesMap shares;
149 };
150 
152 class FlowStatMap : public std::map<StationID, FlowStat> {
153 public:
154  uint GetFlow() const;
155  uint GetFlowVia(StationID via) const;
156  uint GetFlowFrom(StationID from) const;
157  uint GetFlowFromVia(StationID from, StationID via) const;
158 
159  void AddFlow(StationID origin, StationID via, uint amount);
160  void PassOnFlow(StationID origin, StationID via, uint amount);
161  StationIDStack DeleteFlows(StationID via);
162  void RestrictFlows(StationID via);
163  void ReleaseFlows(StationID via);
164  void FinalizeLocalConsumption(StationID self);
165 };
166 
170 struct GoodsEntry {
178 
188 
194 
200 
206 
212  };
213 
214  GoodsEntry() :
215  status(0),
216  time_since_pickup(255),
217  rating(INITIAL_STATION_RATING),
218  last_speed(0),
219  last_age(255),
220  amount_fract(0),
221  link_graph(INVALID_LINK_GRAPH),
222  node(INVALID_NODE),
224  {}
225 
226  byte status;
227 
234 
235  byte rating;
236 
247 
252  byte last_age;
253 
256 
257  LinkGraphID link_graph;
258  NodeID node;
261 
267  bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
268 
273  inline bool HasRating() const
274  {
275  return HasBit(this->status, GES_RATING);
276  }
277 
283  inline StationID GetVia(StationID source) const
284  {
285  FlowStatMap::const_iterator flow_it(this->flows.find(source));
286  return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
287  }
288 
297  inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
298  {
299  FlowStatMap::const_iterator flow_it(this->flows.find(source));
300  return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
301  }
302 };
303 
305 struct Airport : public TileArea {
306  Airport() : TileArea(INVALID_TILE, 0, 0) {}
307 
308  uint64 flags;
309  byte type;
310  byte layout;
312 
314 
320  const AirportSpec *GetSpec() const
321  {
322  if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
323  return AirportSpec::Get(this->type);
324  }
325 
332  const AirportFTAClass *GetFTA() const
333  {
334  return this->GetSpec()->fsm;
335  }
336 
338  inline bool HasHangar() const
339  {
340  return this->GetSpec()->nof_depots > 0;
341  }
342 
352  {
353  const AirportSpec *as = this->GetSpec();
354  switch (this->rotation) {
355  case DIR_N: return this->tile + ToTileIndexDiff(tidc);
356 
357  case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
358 
359  case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
360 
361  case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
362 
363  default: NOT_REACHED();
364  }
365  }
366 
373  inline TileIndex GetHangarTile(uint hangar_num) const
374  {
375  const AirportSpec *as = this->GetSpec();
376  for (uint i = 0; i < as->nof_depots; i++) {
377  if (as->depot_table[i].hangar_num == hangar_num) {
378  return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
379  }
380  }
381  NOT_REACHED();
382  }
383 
391  {
392  const AirportSpec *as = this->GetSpec();
393  const HangarTileTable *htt = GetHangarDataByTile(tile);
394  return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
395  }
396 
403  inline uint GetHangarNum(TileIndex tile) const
404  {
405  const HangarTileTable *htt = GetHangarDataByTile(tile);
406  return htt->hangar_num;
407  }
408 
410  inline uint GetNumHangars() const
411  {
412  uint num = 0;
413  uint counted = 0;
414  const AirportSpec *as = this->GetSpec();
415  for (uint i = 0; i < as->nof_depots; i++) {
416  if (!HasBit(counted, as->depot_table[i].hangar_num)) {
417  num++;
418  SetBit(counted, as->depot_table[i].hangar_num);
419  }
420  }
421  return num;
422  }
423 
424 private:
432  {
433  const AirportSpec *as = this->GetSpec();
434  for (uint i = 0; i < as->nof_depots; i++) {
435  if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
436  return as->depot_table + i;
437  }
438  }
439  NOT_REACHED();
440  }
441 };
442 
444 
446 struct Station FINAL : SpecializedStation<Station, false> {
447 public:
448  RoadStop *GetPrimaryRoadStop(RoadStopType type) const
449  {
450  return type == ROADSTOP_BUS ? bus_stops : truck_stops;
451  }
452 
453  RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
454 
459 
462 
463  IndustryType indtype;
464 
465  StationHadVehicleOfTypeByte had_vehicle_of_type;
466 
467  byte time_since_load;
468  byte time_since_unload;
469 
470  byte last_vehicle_type;
471  std::list<Vehicle *> loading_vehicles;
474 
476 
478  ~Station();
479 
480  void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
481 
482  void MarkTilesDirty(bool cargo_change) const;
483 
484  void UpdateVirtCoord();
485 
486  /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
487  /* virtual */ uint GetPlatformLength(TileIndex tile) const;
489  static void RecomputeIndustriesNearForAll();
490 
491  uint GetCatchmentRadius() const;
492  Rect GetCatchmentRect() const;
493 
494  /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
495  {
496  return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
497  }
498 
499  inline bool TileBelongsToAirport(TileIndex tile) const
500  {
501  return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
502  }
503 
504  /* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
505 
506  /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
507 };
508 
509 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
510 
513 private:
514  const Station *st;
515 
516 public:
521  AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
522  {
523  if (!st->TileBelongsToAirport(this->tile)) ++(*this);
524  }
525 
527  {
528  (*this).OrthogonalTileIterator::operator++();
529  while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
530  (*this).OrthogonalTileIterator::operator++();
531  }
532  return *this;
533  }
534 
535  virtual TileIterator *Clone() const
536  {
537  return new AirportTileIterator(*this);
538  }
539 };
540 
541 #endif /* STATION_BASE_H */