OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

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"
20 #include "linkgraph/linkgraph_type.h"
21 #include "newgrf_storage.h"
22 #include <map>
23
24 typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
25 extern StationPool _station_pool;
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;
148 uint unrestricted;
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 {
172 enum GoodsEntryStatus {
177 GES_ACCEPTANCE,
178
187 GES_RATING,
188
193 GES_EVER_ACCEPTED,
194
199 GES_LAST_MONTH,
200
205 GES_CURRENT_MONTH,
206
211 GES_ACCEPTED_BIGTICK,
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),
223 max_waiting_cargo(0)
224 {}
225
226 byte status;
227
233 byte time_since_pickup;
234
235 byte rating;
236
246 byte last_speed;
247
252 byte last_age;
253
254 byte amount_fract;
255 StationCargoList cargo;
256
257 LinkGraphID link_graph;
258 NodeID node;
259 FlowStatMap flows;
260 uint max_waiting_cargo;
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;
311 DirectionByte rotation;
312
313 PersistentStorage *psa;
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
351 inline TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
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
390 inline Direction GetHangarExitDirection(TileIndex tile) const
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:
431 inline const HangarTileTable *GetHangarDataByTile(TileIndex tile) const
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
443 typedef SmallVector<Industry *, 2> IndustryVector;
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
455 RoadStop *bus_stops;
456 TileArea bus_station;
457 RoadStop *truck_stops;
458 TileArea truck_station;
459
460 Airport airport;
461 TileIndex dock_tile;
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;
472 GoodsEntry goods[NUM_CARGO];
473 uint32 always_accepted;
474
475 IndustryVector industries_near;
476
477 Station(TileIndex tile = INVALID_TILE);
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;
488 void RecomputeIndustriesNear();
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
512 class AirportTileIterator : public OrthogonalTileIterator {
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
526 inline TileIterator& operator ++()
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 */