MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / FindClosestShipDepot

Function FindClosestShipDepot

src/ship_cmd.cpp:150–201  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

148}
149
150static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
151{
152 const int max_region_distance = (max_distance / WATER_REGION_EDGE_LENGTH) + 1;
153
154 static std::unordered_set<int> visited_patch_hashes;
155 static std::deque<WaterRegionPatchDesc> patches_to_search;
156 visited_patch_hashes.clear();
157 patches_to_search.clear();
158
159 /* Step 1: find a set of reachable Water Region Patches using BFS. */
160 const WaterRegionPatchDesc start_patch = GetWaterRegionPatchInfo(v->tile);
161 patches_to_search.push_back(start_patch);
162 visited_patch_hashes.insert(CalculateWaterRegionPatchHash(start_patch));
163
164 while (!patches_to_search.empty()) {
165 /* Remove first patch from the queue and make it the current patch. */
166 const WaterRegionPatchDesc current_node = patches_to_search.front();
167 patches_to_search.pop_front();
168
169 /* Add neighbours of the current patch to the search queue. */
170 VisitWaterRegionPatchCallback visit_func = [&](const WaterRegionPatchDesc &water_region_patch) {
171 /* Note that we check the max distance per axis, not the total distance. */
172 if (std::abs(water_region_patch.x - start_patch.x) > max_region_distance ||
173 std::abs(water_region_patch.y - start_patch.y) > max_region_distance) return;
174
175 const int hash = CalculateWaterRegionPatchHash(water_region_patch);
176 if (visited_patch_hashes.count(hash) == 0) {
177 visited_patch_hashes.insert(hash);
178 patches_to_search.push_back(water_region_patch);
179 }
180 };
181
182 VisitWaterRegionPatchNeighbours(current_node, visit_func);
183 }
184
185 /* Step 2: Find the closest depot within the reachable Water Region Patches. */
186 const Depot *best_depot = nullptr;
187 uint best_dist_sq = std::numeric_limits<uint>::max();
188 for (const Depot *depot : Depot::Iterate()) {
189 const TileIndex tile = depot->xy;
190 if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
191 const uint dist_sq = DistanceSquare(tile, v->tile);
192 if (dist_sq < best_dist_sq && dist_sq <= max_distance * max_distance &&
193 visited_patch_hashes.count(CalculateWaterRegionPatchHash(GetWaterRegionPatchInfo(tile))) > 0) {
194 best_dist_sq = dist_sq;
195 best_depot = depot;
196 }
197 }
198 }
199
200 return best_depot;
201}
202
203static void CheckIfShipNeedsService(Vehicle *v)
204{

Callers 2

CheckIfShipNeedsServiceFunction · 0.85
FindClosestDepotMethod · 0.85

Calls 12

GetWaterRegionPatchInfoFunction · 0.85
absFunction · 0.85
IsShipDepotTileFunction · 0.85
IsTileOwnerFunction · 0.85
DistanceSquareFunction · 0.85
push_backMethod · 0.80
clearMethod · 0.45
insertMethod · 0.45
emptyMethod · 0.45
countMethod · 0.45

Tested by

no test coverage detected