OpenTTD Source  20240917-master-g9ab0a47812
water_regions.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #include "stdafx.h"
11 #include "map_func.h"
12 #include "water_regions.h"
13 #include "map_func.h"
14 #include "tilearea_type.h"
15 #include "track_func.h"
16 #include "transport_type.h"
17 #include "landscape.h"
18 #include "tunnelbridge_map.h"
19 #include "follow_track.hpp"
20 #include "ship.h"
21 #include "debug.h"
22 
23 using TWaterRegionTraversabilityBits = uint16_t;
24 constexpr TWaterRegionPatchLabel FIRST_REGION_LABEL = 1;
25 
26 static_assert(sizeof(TWaterRegionTraversabilityBits) * 8 == WATER_REGION_EDGE_LENGTH);
27 static_assert(sizeof(TWaterRegionPatchLabel) == sizeof(uint8_t)); // Important for the hash calculation.
28 
29 static inline TrackBits GetWaterTracks(TileIndex tile) { return TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)); }
30 static inline bool IsAqueductTile(TileIndex tile) { return IsBridgeTile(tile) && GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER; }
31 
32 static inline int GetWaterRegionX(TileIndex tile) { return TileX(tile) / WATER_REGION_EDGE_LENGTH; }
33 static inline int GetWaterRegionY(TileIndex tile) { return TileY(tile) / WATER_REGION_EDGE_LENGTH; }
34 
35 static inline int GetWaterRegionMapSizeX() { return Map::SizeX() / WATER_REGION_EDGE_LENGTH; }
36 static inline int GetWaterRegionMapSizeY() { return Map::SizeY() / WATER_REGION_EDGE_LENGTH; }
37 
38 static inline TWaterRegionIndex GetWaterRegionIndex(int region_x, int region_y) { return GetWaterRegionMapSizeX() * region_y + region_x; }
39 static inline TWaterRegionIndex GetWaterRegionIndex(TileIndex tile) { return GetWaterRegionIndex(GetWaterRegionX(tile), GetWaterRegionY(tile)); }
40 
41 using TWaterRegionPatchLabelArray = std::array<TWaterRegionPatchLabel, WATER_REGION_NUMBER_OF_TILES>;
42 
47  friend class WaterRegion;
48 
49  std::array<TWaterRegionTraversabilityBits, DIAGDIR_END> edge_traversability_bits{};
50  std::unique_ptr<TWaterRegionPatchLabelArray> tile_patch_labels; // Tile patch labels, this may be nullptr in the following trivial cases: region is invalid, region is only land (0 patches), region is only water (1 patch)
51  bool has_cross_region_aqueducts = false;
52  TWaterRegionPatchLabel number_of_patches = 0; // 0 = no water, 1 = one single patch of water, etc...
53 };
54 
62 {
63 private:
64  WaterRegionData &data;
65  const OrthogonalTileArea tile_area;
66 
73  inline int GetLocalIndex(TileIndex tile) const
74  {
75  assert(this->tile_area.Contains(tile));
76  return (TileX(tile) - TileX(this->tile_area.tile)) + WATER_REGION_EDGE_LENGTH * (TileY(tile) - TileY(this->tile_area.tile));
77  }
78 
79 public:
80  WaterRegion(int region_x, int region_y, WaterRegionData &water_region_data)
81  : data(water_region_data)
82  , tile_area(TileXY(region_x * WATER_REGION_EDGE_LENGTH, region_y * WATER_REGION_EDGE_LENGTH), WATER_REGION_EDGE_LENGTH, WATER_REGION_EDGE_LENGTH)
83  {}
84 
85  OrthogonalTileIterator begin() const { return this->tile_area.begin(); }
86  OrthogonalTileIterator end() const { return this->tile_area.end(); }
87 
95  TWaterRegionTraversabilityBits GetEdgeTraversabilityBits(DiagDirection side) const { return this->data.edge_traversability_bits[side]; }
96 
101  int NumberOfPatches() const { return this->data.number_of_patches; }
102 
106  bool HasCrossRegionAqueducts() const { return this->data.has_cross_region_aqueducts; }
107 
113  TWaterRegionPatchLabel GetLabel(TileIndex tile) const
114  {
115  assert(this->tile_area.Contains(tile));
116  if (this->data.tile_patch_labels == nullptr) {
117  return this->NumberOfPatches() == 0 ? INVALID_WATER_REGION_PATCH : 1;
118  }
119  return (*this->data.tile_patch_labels)[GetLocalIndex(tile)];
120  }
121 
126  void ForceUpdate()
127  {
128  Debug(map, 3, "Updating water region ({},{})", GetWaterRegionX(this->tile_area.tile), GetWaterRegionY(this->tile_area.tile));
129  this->data.has_cross_region_aqueducts = false;
130 
131  /* Acquire a tile patch label array if this region does not already have one */
132  if (this->data.tile_patch_labels == nullptr) {
133  this->data.tile_patch_labels = std::make_unique<TWaterRegionPatchLabelArray>();
134  }
135 
136  this->data.tile_patch_labels->fill(INVALID_WATER_REGION_PATCH);
137  this->data.edge_traversability_bits.fill(0);
138 
139  TWaterRegionPatchLabel current_label = 1;
140  TWaterRegionPatchLabel highest_assigned_label = 0;
141 
142  /* Perform connected component labeling. This uses a flooding algorithm that expands until no
143  * additional tiles can be added. Only tiles inside the water region are considered. */
144  for (const TileIndex start_tile : tile_area) {
145  static std::vector<TileIndex> tiles_to_check;
146  tiles_to_check.clear();
147  tiles_to_check.push_back(start_tile);
148 
149  bool increase_label = false;
150  while (!tiles_to_check.empty()) {
151  const TileIndex tile = tiles_to_check.back();
152  tiles_to_check.pop_back();
153 
154  const TrackdirBits valid_dirs = TrackBitsToTrackdirBits(GetWaterTracks(tile));
155  if (valid_dirs == TRACKDIR_BIT_NONE) continue;
156 
157  TWaterRegionPatchLabel &tile_patch = (*this->data.tile_patch_labels)[GetLocalIndex(tile)];
158  if (tile_patch != INVALID_WATER_REGION_PATCH) continue;
159 
160  tile_patch = current_label;
161  highest_assigned_label = current_label;
162  increase_label = true;
163 
164  for (const Trackdir dir : SetTrackdirBitIterator(valid_dirs)) {
165  /* By using a TrackFollower we "play by the same rules" as the actual ship pathfinder */
167  if (ft.Follow(tile, dir)) {
168  if (this->tile_area.Contains(ft.m_new_tile)) {
169  tiles_to_check.push_back(ft.m_new_tile);
170  } else if (!ft.m_is_bridge) {
171  assert(DistanceManhattan(ft.m_new_tile, tile) == 1);
172  const auto side = DiagdirBetweenTiles(tile, ft.m_new_tile);
173  const int local_x_or_y = DiagDirToAxis(side) == AXIS_X ? TileY(tile) - TileY(this->tile_area.tile) : TileX(tile) - TileX(this->tile_area.tile);
174  SetBit(this->data.edge_traversability_bits[side], local_x_or_y);
175  } else {
176  this->data.has_cross_region_aqueducts = true;
177  }
178  }
179  }
180  }
181 
182  if (increase_label) current_label++;
183  }
184 
185  this->data.number_of_patches = highest_assigned_label;
186 
187  if (this->data.number_of_patches == 0 || (this->data.number_of_patches == 1 &&
188  std::all_of(this->data.tile_patch_labels->begin(), this->data.tile_patch_labels->end(), [](TWaterRegionPatchLabel label) { return label == 1; }))) {
189  /* No need for patch storage: trivial cases */
190  this->data.tile_patch_labels.reset();
191  }
192  }
193 
194  void PrintDebugInfo()
195  {
196  Debug(map, 9, "Water region {},{} labels and edge traversability = ...", GetWaterRegionX(tile_area.tile), GetWaterRegionY(tile_area.tile));
197 
198  const size_t max_element_width = std::to_string(this->data.number_of_patches).size();
199 
200  std::array<int, 16> traversability_NW{0};
201  for (auto bitIndex : SetBitIterator(this->data.edge_traversability_bits[DIAGDIR_NW])) *(traversability_NW.rbegin() + bitIndex) = 1;
202  Debug(map, 9, " {:{}}", fmt::join(traversability_NW, " "), max_element_width);
203  Debug(map, 9, " +{:->{}}+", "", WATER_REGION_EDGE_LENGTH * (max_element_width + 1) + 1);
204 
205  for (int y = 0; y < WATER_REGION_EDGE_LENGTH; ++y) {
206  std::string line{};
207  for (int x = 0; x < WATER_REGION_EDGE_LENGTH; ++x) {
208  const auto label = this->GetLabel(TileAddXY(tile_area.tile, x, y));
209  const std::string label_str = label == INVALID_WATER_REGION_PATCH ? "." : std::to_string(label);
210  line = fmt::format("{:{}}", label_str, max_element_width) + " " + line;
211  }
212  Debug(map, 9, "{} | {}| {}", GB(this->data.edge_traversability_bits[DIAGDIR_SW], y, 1), line, GB(this->data.edge_traversability_bits[DIAGDIR_NE], y, 1));
213  }
214 
215  Debug(map, 9, " +{:->{}}+", "", WATER_REGION_EDGE_LENGTH * (max_element_width + 1) + 1);
216  std::array<int, 16> traversability_SE{0};
217  for (auto bitIndex : SetBitIterator(this->data.edge_traversability_bits[DIAGDIR_SE])) *(traversability_SE.rbegin() + bitIndex) = 1;
218  Debug(map, 9, " {:{}}", fmt::join(traversability_SE, " "), max_element_width);
219  }
220 };
221 
222 std::vector<WaterRegionData> _water_region_data;
223 std::vector<bool> _is_water_region_valid;
224 
225 TileIndex GetTileIndexFromLocalCoordinate(int region_x, int region_y, int local_x, int local_y)
226 {
227  assert(local_x >= 0 && local_x < WATER_REGION_EDGE_LENGTH);
228  assert(local_y >= 0 && local_y < WATER_REGION_EDGE_LENGTH);
229  return TileXY(WATER_REGION_EDGE_LENGTH * region_x + local_x, WATER_REGION_EDGE_LENGTH * region_y + local_y);
230 }
231 
232 TileIndex GetEdgeTileCoordinate(int region_x, int region_y, DiagDirection side, int x_or_y)
233 {
234  assert(x_or_y >= 0 && x_or_y < WATER_REGION_EDGE_LENGTH);
235  switch (side) {
236  case DIAGDIR_NE: return GetTileIndexFromLocalCoordinate(region_x, region_y, 0, x_or_y);
237  case DIAGDIR_SW: return GetTileIndexFromLocalCoordinate(region_x, region_y, WATER_REGION_EDGE_LENGTH - 1, x_or_y);
238  case DIAGDIR_NW: return GetTileIndexFromLocalCoordinate(region_x, region_y, x_or_y, 0);
239  case DIAGDIR_SE: return GetTileIndexFromLocalCoordinate(region_x, region_y, x_or_y, WATER_REGION_EDGE_LENGTH - 1);
240  default: NOT_REACHED();
241  }
242 }
243 
244 WaterRegion GetUpdatedWaterRegion(uint16_t region_x, uint16_t region_y)
245 {
246  const int index = GetWaterRegionIndex(region_x, region_y);
247  WaterRegion water_region(region_x, region_y, _water_region_data[index]);
248  if (!_is_water_region_valid[index]) {
249  water_region.ForceUpdate();
250  _is_water_region_valid[index] = true;
251  }
252  return water_region;
253 }
254 
255 WaterRegion GetUpdatedWaterRegion(TileIndex tile)
256 {
257  return GetUpdatedWaterRegion(GetWaterRegionX(tile), GetWaterRegionY(tile));
258 }
259 
264 TWaterRegionIndex GetWaterRegionIndex(const WaterRegionDesc &water_region)
265 {
266  return GetWaterRegionIndex(water_region.x, water_region.y);
267 }
268 
274 {
275  return water_region_patch.label | GetWaterRegionIndex(water_region_patch) << 8;
276 }
277 
284 {
285  return TileXY(water_region.x * WATER_REGION_EDGE_LENGTH + (WATER_REGION_EDGE_LENGTH / 2), water_region.y * WATER_REGION_EDGE_LENGTH + (WATER_REGION_EDGE_LENGTH / 2));
286 }
287 
293 {
294  return WaterRegionDesc{ GetWaterRegionX(tile), GetWaterRegionY(tile) };
295 }
296 
302 {
303  const WaterRegion region = GetUpdatedWaterRegion(tile);
304  return WaterRegionPatchDesc{ GetWaterRegionX(tile), GetWaterRegionY(tile), region.GetLabel(tile)};
305 }
306 
312 {
313  if (!IsValidTile(tile)) return;
314 
315  auto invalidate_region = [](TileIndex tile) {
316  const int water_region_index = GetWaterRegionIndex(tile);
317  if (!_is_water_region_valid[water_region_index]) Debug(map, 3, "Invalidated water region ({},{})", GetWaterRegionX(tile), GetWaterRegionY(tile));
318  _is_water_region_valid[water_region_index] = false;
319  };
320 
321  invalidate_region(tile);
322 
323  /* When updating the water region we look into the first tile of adjacent water regions to determine edge
324  * traversability. This means that if we invalidate any region edge tiles we might also change the traversability
325  * of the adjacent region. This code ensures the adjacent regions also get invalidated in such a case. */
326  for (DiagDirection side = DIAGDIR_BEGIN; side < DIAGDIR_END; side++) {
327  const TileIndex adjacent_tile = TileAddByDiagDir(tile, side);
328  if (GetWaterRegionIndex(adjacent_tile) != GetWaterRegionIndex(tile)) invalidate_region(adjacent_tile);
329  }
330 }
331 
339 static inline void VisitAdjacentWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_patch, DiagDirection side, TVisitWaterRegionPatchCallBack &func)
340 {
341  if (water_region_patch.label == INVALID_WATER_REGION_PATCH) return;
342 
343  const WaterRegion current_region = GetUpdatedWaterRegion(water_region_patch.x, water_region_patch.y);
344 
345  const TileIndexDiffC offset = TileIndexDiffCByDiagDir(side);
346  const int nx = water_region_patch.x + offset.x;
347  const int ny = water_region_patch.y + offset.y;
348 
349  if (nx < 0 || ny < 0 || nx >= GetWaterRegionMapSizeX() || ny >= GetWaterRegionMapSizeY()) return;
350 
351  const WaterRegion neighboring_region = GetUpdatedWaterRegion(nx, ny);
352  const DiagDirection opposite_side = ReverseDiagDir(side);
353 
354  /* Indicates via which local x or y coordinates (depends on the "side" parameter) we can cross over into the adjacent region. */
355  const TWaterRegionTraversabilityBits traversability_bits = current_region.GetEdgeTraversabilityBits(side)
356  & neighboring_region.GetEdgeTraversabilityBits(opposite_side);
357  if (traversability_bits == 0) return;
358 
359  if (current_region.NumberOfPatches() == 1 && neighboring_region.NumberOfPatches() == 1) {
360  func(WaterRegionPatchDesc{ nx, ny, FIRST_REGION_LABEL }); // No further checks needed because we know there is just one patch for both adjacent regions
361  return;
362  }
363 
364  /* Multiple water patches can be reached from the current patch. Check each edge tile individually. */
365  static std::vector<TWaterRegionPatchLabel> unique_labels; // static and vector-instead-of-map for performance reasons
366  unique_labels.clear();
367  for (int x_or_y = 0; x_or_y < WATER_REGION_EDGE_LENGTH; ++x_or_y) {
368  if (!HasBit(traversability_bits, x_or_y)) continue;
369 
370  const TileIndex current_edge_tile = GetEdgeTileCoordinate(water_region_patch.x, water_region_patch.y, side, x_or_y);
371  const TWaterRegionPatchLabel current_label = current_region.GetLabel(current_edge_tile);
372  if (current_label != water_region_patch.label) continue;
373 
374  const TileIndex neighbor_edge_tile = GetEdgeTileCoordinate(nx, ny, opposite_side, x_or_y);
375  const TWaterRegionPatchLabel neighbor_label = neighboring_region.GetLabel(neighbor_edge_tile);
376  assert(neighbor_label != INVALID_WATER_REGION_PATCH);
377  if (std::find(unique_labels.begin(), unique_labels.end(), neighbor_label) == unique_labels.end()) unique_labels.push_back(neighbor_label);
378  }
379  for (TWaterRegionPatchLabel unique_label : unique_labels) func(WaterRegionPatchDesc{ nx, ny, unique_label });
380 }
381 
388 void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_patch, TVisitWaterRegionPatchCallBack &callback)
389 {
390  if (water_region_patch.label == INVALID_WATER_REGION_PATCH) return;
391 
392  const WaterRegion current_region = GetUpdatedWaterRegion(water_region_patch.x, water_region_patch.y);
393 
394  /* Visit adjacent water region patches in each cardinal direction */
395  for (DiagDirection side = DIAGDIR_BEGIN; side < DIAGDIR_END; side++) VisitAdjacentWaterRegionPatchNeighbors(water_region_patch, side, callback);
396 
397  /* Visit neigboring water patches accessible via cross-region aqueducts */
398  if (current_region.HasCrossRegionAqueducts()) {
399  for (const TileIndex tile : current_region) {
400  if (GetWaterRegionPatchInfo(tile) == water_region_patch && IsAqueductTile(tile)) {
401  const TileIndex other_end_tile = GetOtherBridgeEnd(tile);
402  if (GetWaterRegionIndex(tile) != GetWaterRegionIndex(other_end_tile)) callback(GetWaterRegionPatchInfo(other_end_tile));
403  }
404  }
405  }
406 }
407 
412 {
413  const int number_of_regions = GetWaterRegionMapSizeX() * GetWaterRegionMapSizeY();
414 
415  _water_region_data.clear();
416  _water_region_data.resize(number_of_regions);
417 
418  _is_water_region_valid.clear();
419  _is_water_region_valid.resize(number_of_regions, false);
420 
421  Debug(map, 2, "Allocating {} x {} water regions", GetWaterRegionMapSizeX(), GetWaterRegionMapSizeY());
422  assert(_is_water_region_valid.size() == _water_region_data.size());
423 }
424 
425 void PrintWaterRegionDebugInfo(TileIndex tile)
426 {
427  GetUpdatedWaterRegion(tile).PrintDebugInfo();
428 }
TileY
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:437
TileIndexDiffCByDiagDir
TileIndexDiffC TileIndexDiffCByDiagDir(DiagDirection dir)
Returns the TileIndexDiffC offset from a DiagDirection.
Definition: map_func.h:492
transport_type.h
DIAGDIR_NE
@ DIAGDIR_NE
Northeast, upper right on your monitor.
Definition: direction_type.h:75
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition: bitmath_func.hpp:121
GetOtherBridgeEnd
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
Definition: bridge_map.cpp:59
WaterRegion::ForceUpdate
void ForceUpdate()
Performs the connected component labeling and other data gathering.
Definition: water_regions.cpp:126
WaterRegionPatchDesc
Describes a single interconnected patch of water within a particular water region.
Definition: water_regions.h:26
tunnelbridge_map.h
TRANSPORT_WATER
@ TRANSPORT_WATER
Transport over water.
Definition: transport_type.h:29
GB
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
map_func.h
DiagDirToAxis
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Definition: direction_func.h:214
TileAddXY
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition: map_func.h:479
ship.h
WaterRegionPatchDesc::y
int y
The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis.
Definition: water_regions.h:29
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition: direction_type.h:73
GetWaterRegionCenterTile
TileIndex GetWaterRegionCenterTile(const WaterRegionDesc &water_region)
Returns the center tile of a particular water region.
Definition: water_regions.cpp:283
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
CFollowTrackT::m_is_bridge
bool m_is_bridge
last turn passed bridge ramp
Definition: follow_track.hpp:47
GetTileTrackStatus
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:553
OrthogonalTileIterator
Iterator to iterate over a tile area (rectangle) of the map.
Definition: tilearea_type.h:185
DistanceManhattan
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:140
GetWaterRegionPatchInfo
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
Definition: water_regions.cpp:301
GetWaterRegionInfo
WaterRegionDesc GetWaterRegionInfo(TileIndex tile)
Returns basic water region information for the provided tile.
Definition: water_regions.cpp:292
DIAGDIR_NW
@ DIAGDIR_NW
Northwest.
Definition: direction_type.h:78
TrackBitsToTrackdirBits
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:319
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition: direction_type.h:76
SetBitIterator
Iterable ensemble of each set bit in a value.
Definition: bitmath_func.hpp:301
TrackBits
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
WaterRegion
Represents a square section of the map of a fixed size.
Definition: water_regions.cpp:61
DIAGDIR_BEGIN
@ DIAGDIR_BEGIN
Used for iterations.
Definition: direction_type.h:74
WaterRegion::GetLocalIndex
int GetLocalIndex(TileIndex tile) const
Returns the local index of the tile within the region.
Definition: water_regions.cpp:73
TRACKDIR_BIT_NONE
@ TRACKDIR_BIT_NONE
No track build.
Definition: track_type.h:99
OrthogonalTileArea::begin
OrthogonalTileIterator begin() const
Returns an iterator to the beginning of the tile area.
Definition: tilearea.cpp:153
ReverseDiagDir
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Definition: direction_func.h:118
OrthogonalTileArea
Represents the covered area of e.g.
Definition: tilearea_type.h:18
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition: direction_type.h:77
water_regions.h
IsBridgeTile
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition: bridge_map.h:35
follow_track.hpp
VisitWaterRegionPatchNeighbors
void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_patch, TVisitWaterRegionPatchCallBack &callback)
Calls the provided callback function on all accessible water region patches in each cardinal directio...
Definition: water_regions.cpp:388
OrthogonalTileArea::end
OrthogonalTileIterator end() const
Returns an iterator to the end of the tile area.
Definition: tilearea.cpp:162
WaterRegion::GetEdgeTraversabilityBits
TWaterRegionTraversabilityBits GetEdgeTraversabilityBits(DiagDirection side) const
Returns a set of bits indicating whether an edge tile on a particular side is traversable or not.
Definition: water_regions.cpp:95
WaterRegionData
The data stored for each water region.
Definition: water_regions.cpp:46
TrackStatusToTrackBits
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition: track_func.h:363
stdafx.h
WaterRegionDesc
Describes a single square water region.
Definition: water_regions.h:40
landscape.h
CalculateWaterRegionPatchHash
int CalculateWaterRegionPatchHash(const WaterRegionPatchDesc &water_region_patch)
Calculates a number that uniquely identifies the provided water region patch.
Definition: water_regions.cpp:273
WaterRegionDesc::y
int y
The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis.
Definition: water_regions.h:43
GetWaterRegionIndex
TWaterRegionIndex GetWaterRegionIndex(const WaterRegionDesc &water_region)
Returns the index of the water region.
Definition: water_regions.cpp:264
AXIS_X
@ AXIS_X
The X axis.
Definition: direction_type.h:117
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161
TileIndexDiffC
A pair-construct of a TileIndexDiff.
Definition: map_type.h:31
Map::SizeX
static debug_inline uint SizeX()
Get the size of the map along the X.
Definition: map_func.h:270
tilearea_type.h
DiagdirBetweenTiles
DiagDirection DiagdirBetweenTiles(TileIndex tile_from, TileIndex tile_to)
Determines the DiagDirection to get from one tile to another.
Definition: map_func.h:618
Trackdir
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:67
OrthogonalTileArea::tile
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
GetTunnelBridgeTransportType
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
Definition: tunnelbridge_map.h:39
InvalidateWaterRegion
void InvalidateWaterRegion(TileIndex tile)
Marks the water region that tile is part of as invalid.
Definition: water_regions.cpp:311
DIAGDIR_END
@ DIAGDIR_END
Used for iterations.
Definition: direction_type.h:79
track_func.h
AllocateWaterRegions
void AllocateWaterRegions()
Allocates the appropriate amount of water regions for the current map size.
Definition: water_regions.cpp:411
CFollowTrackT::m_new_tile
TileIndex m_new_tile
the new tile (the vehicle has entered)
Definition: follow_track.hpp:43
TileIndexDiffC::y
int16_t y
The y value of the coordinate.
Definition: map_type.h:33
WaterRegionPatchDesc::label
TWaterRegionPatchLabel label
Unique label identifying the patch within the region.
Definition: water_regions.h:30
CFollowTrackT::Follow
bool Follow(TileIndex old_tile, Trackdir old_td)
main follower routine.
Definition: follow_track.hpp:119
TileXY
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition: map_func.h:385
WaterRegion::GetLabel
TWaterRegionPatchLabel GetLabel(TileIndex tile) const
Returns the patch label that was assigned to the tile.
Definition: water_regions.cpp:113
WaterRegionDesc::x
int x
The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis.
Definition: water_regions.h:42
TrackdirBits
TrackdirBits
Allow incrementing of Trackdir variables.
Definition: track_type.h:98
TileX
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:427
VisitAdjacentWaterRegionPatchNeighbors
static void VisitAdjacentWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_patch, DiagDirection side, TVisitWaterRegionPatchCallBack &func)
Calls the provided callback function for all water region patches accessible from one particular side...
Definition: water_regions.cpp:339
WaterRegion::HasCrossRegionAqueducts
bool HasCrossRegionAqueducts() const
Definition: water_regions.cpp:106
TileAddByDiagDir
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition: map_func.h:606
TileIndexDiffC::x
int16_t x
The x value of the coordinate.
Definition: map_type.h:32
WaterRegion::NumberOfPatches
int NumberOfPatches() const
Definition: water_regions.cpp:101
CFollowTrackT
Track follower helper template class (can serve pathfinders and vehicle controllers).
Definition: follow_track.hpp:28
Map::SizeY
static uint SizeY()
Get the size of the map along the Y.
Definition: map_func.h:279
OrthogonalTileArea::Contains
bool Contains(TileIndex tile) const
Does this tile area contain a tile?
Definition: tilearea.cpp:104
debug.h
WaterRegionPatchDesc::x
int x
The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis.
Definition: water_regions.h:28
HasBit
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103