OpenTTD
station_base.h
Go to the documentation of this file.
1 /* $Id: station_base.h 26891 2014-09-21 16:19:52Z fonsinchen $ */
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 
45  inline FlowStat() {NOT_REACHED();}
46 
53  inline FlowStat(StationID st, uint flow, bool restricted = false)
54  {
55  assert(flow > 0);
56  this->shares[flow] = st;
57  this->unrestricted = restricted ? 0 : flow;
58  }
59 
68  inline void AppendShare(StationID st, uint flow, bool restricted = false)
69  {
70  assert(flow > 0);
71  this->shares[(--this->shares.end())->first + flow] = st;
72  if (!restricted) this->unrestricted += flow;
73  }
74 
75  uint GetShare(StationID st) const;
76 
77  void ChangeShare(StationID st, int flow);
78 
79  void RestrictShare(StationID st);
80 
81  void ReleaseShare(StationID st);
82 
83  void ScaleToMonthly(uint runtime);
84 
90  inline const SharesMap *GetShares() const { return &this->shares; }
91 
96  inline uint GetUnrestricted() const { return this->unrestricted; }
97 
103  inline void SwapShares(FlowStat &other)
104  {
105  this->shares.swap(other.shares);
106  Swap(this->unrestricted, other.unrestricted);
107  }
108 
117  inline StationID GetViaWithRestricted(bool &is_restricted) const
118  {
119  assert(!this->shares.empty());
120  uint rand = RandomRange((--this->shares.end())->first);
121  is_restricted = rand >= this->unrestricted;
122  return this->shares.upper_bound(rand)->second;
123  }
124 
132  inline StationID GetVia() const
133  {
134  assert(!this->shares.empty());
135  return this->unrestricted > 0 ?
136  this->shares.upper_bound(RandomRange(this->unrestricted))->second :
137  INVALID_STATION;
138  }
139 
140  StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const;
141 
142  void Invalidate();
143 
144 private:
145  SharesMap shares;
147 };
148 
150 class FlowStatMap : public std::map<StationID, FlowStat> {
151 public:
152  uint GetFlow() const;
153  uint GetFlowVia(StationID via) const;
154  uint GetFlowFrom(StationID from) const;
155  uint GetFlowFromVia(StationID from, StationID via) const;
156 
157  void AddFlow(StationID origin, StationID via, uint amount);
158  void PassOnFlow(StationID origin, StationID via, uint amount);
159  StationIDStack DeleteFlows(StationID via);
160  void RestrictFlows(StationID via);
161  void ReleaseFlows(StationID via);
162  void FinalizeLocalConsumption(StationID self);
163 };
164 
168 struct GoodsEntry {
176 
186 
192 
198 
204 
210  };
211 
212  GoodsEntry() :
213  status(0),
214  time_since_pickup(255),
215  rating(INITIAL_STATION_RATING),
216  last_speed(0),
217  last_age(255),
218  amount_fract(0),
219  link_graph(INVALID_LINK_GRAPH),
220  node(INVALID_NODE),
222  {}
223 
224  byte status;
225 
232 
233  byte rating;
234 
245 
250  byte last_age;
251 
254 
255  LinkGraphID link_graph;
256  NodeID node;
259 
265  bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
266 
271  inline bool HasRating() const
272  {
273  return HasBit(this->status, GES_RATING);
274  }
275 
281  inline StationID GetVia(StationID source) const
282  {
283  FlowStatMap::const_iterator flow_it(this->flows.find(source));
284  return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
285  }
286 
295  inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
296  {
297  FlowStatMap::const_iterator flow_it(this->flows.find(source));
298  return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
299  }
300 };
301 
303 struct Airport : public TileArea {
304  Airport() : TileArea(INVALID_TILE, 0, 0) {}
305 
306  uint64 flags;
307  byte type;
308  byte layout;
310 
312 
318  const AirportSpec *GetSpec() const
319  {
320  if (this->tile == INVALID_TILE) return &AirportSpec::dummy;
321  return AirportSpec::Get(this->type);
322  }
323 
330  const AirportFTAClass *GetFTA() const
331  {
332  return this->GetSpec()->fsm;
333  }
334 
336  inline bool HasHangar() const
337  {
338  return this->GetSpec()->nof_depots > 0;
339  }
340 
350  {
351  const AirportSpec *as = this->GetSpec();
352  switch (this->rotation) {
353  case DIR_N: return this->tile + ToTileIndexDiff(tidc);
354 
355  case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
356 
357  case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
358 
359  case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
360 
361  default: NOT_REACHED();
362  }
363  }
364 
371  inline TileIndex GetHangarTile(uint hangar_num) const
372  {
373  const AirportSpec *as = this->GetSpec();
374  for (uint i = 0; i < as->nof_depots; i++) {
375  if (as->depot_table[i].hangar_num == hangar_num) {
376  return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
377  }
378  }
379  NOT_REACHED();
380  }
381 
389  {
390  const AirportSpec *as = this->GetSpec();
391  const HangarTileTable *htt = GetHangarDataByTile(tile);
392  return ChangeDir(htt->dir, DirDifference(this->rotation, as->rotation[0]));
393  }
394 
401  inline uint GetHangarNum(TileIndex tile) const
402  {
403  const HangarTileTable *htt = GetHangarDataByTile(tile);
404  return htt->hangar_num;
405  }
406 
408  inline uint GetNumHangars() const
409  {
410  uint num = 0;
411  uint counted = 0;
412  const AirportSpec *as = this->GetSpec();
413  for (uint i = 0; i < as->nof_depots; i++) {
414  if (!HasBit(counted, as->depot_table[i].hangar_num)) {
415  num++;
416  SetBit(counted, as->depot_table[i].hangar_num);
417  }
418  }
419  return num;
420  }
421 
422 private:
430  {
431  const AirportSpec *as = this->GetSpec();
432  for (uint i = 0; i < as->nof_depots; i++) {
433  if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
434  return as->depot_table + i;
435  }
436  }
437  NOT_REACHED();
438  }
439 };
440 
442 
444 struct Station FINAL : SpecializedStation<Station, false> {
445 public:
446  RoadStop *GetPrimaryRoadStop(RoadStopType type) const
447  {
448  return type == ROADSTOP_BUS ? bus_stops : truck_stops;
449  }
450 
451  RoadStop *GetPrimaryRoadStop(const struct RoadVehicle *v) const;
452 
457 
460 
461  IndustryType indtype;
462 
463  StationHadVehicleOfTypeByte had_vehicle_of_type;
464 
465  byte time_since_load;
466  byte time_since_unload;
467 
468  byte last_vehicle_type;
469  std::list<Vehicle *> loading_vehicles;
472 
474 
476  ~Station();
477 
478  void AddFacility(StationFacility new_facility_bit, TileIndex facil_xy);
479 
480  void MarkTilesDirty(bool cargo_change) const;
481 
482  void UpdateVirtCoord();
483 
484  /* virtual */ uint GetPlatformLength(TileIndex tile, DiagDirection dir) const;
485  /* virtual */ uint GetPlatformLength(TileIndex tile) const;
487  static void RecomputeIndustriesNearForAll();
488 
489  uint GetCatchmentRadius() const;
490  Rect GetCatchmentRect() const;
491 
492  /* virtual */ inline bool TileBelongsToRailStation(TileIndex tile) const
493  {
494  return IsRailStationTile(tile) && GetStationIndex(tile) == this->index;
495  }
496 
497  inline bool TileBelongsToAirport(TileIndex tile) const
498  {
499  return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
500  }
501 
502  /* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
503 
504  /* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
505 };
506 
507 #define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
508 
511 private:
512  const Station *st;
513 
514 public:
519  AirportTileIterator(const Station *st) : OrthogonalTileIterator(st->airport), st(st)
520  {
521  if (!st->TileBelongsToAirport(this->tile)) ++(*this);
522  }
523 
525  {
526  (*this).OrthogonalTileIterator::operator++();
527  while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) {
528  (*this).OrthogonalTileIterator::operator++();
529  }
530  return *this;
531  }
532 
533  virtual TileIterator *Clone() const
534  {
535  return new AirportTileIterator(*this);
536  }
537 };
538 
539 #endif /* STATION_BASE_H */