OpenTTD Source: src/pathfinder/water_regions.cpp Source File

OpenTTD Source 15.3

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