1
0
Fork 0
SamuXarick 2025-06-24 07:00:00 +00:00 committed by GitHub
commit 29c6f89695
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 24 deletions

View File

@ -158,4 +158,31 @@ namespace StrongType {
}; };
} }
/**
* Implementation of std::hash for StrongType::Typedef.
*
* This specialization of std::hash allows hashing of StrongType::Typedef instances
* by leveraging the hash of the base type.
*
* Example Usage:
* using MyType = StrongType::Typedef<int, struct MyTypeTag>;
* std::unordered_map<MyType, std::string> my_map;
*
* @tparam TBaseType The underlying type of the StrongType::Typedef.
* @tparam TProperties Additional properties for the StrongType::Typedef.
*/
template <typename TBaseType, typename... TProperties>
struct std::hash<StrongType::Typedef<TBaseType, TProperties...>> {
/**
* Computes the hash value for a StrongType::Typedef instance.
*
* @param t The StrongType::Typedef instance to hash.
* @return The hash value of the base type of t.
*/
std::size_t operator()(const StrongType::Typedef<TBaseType, TProperties...> &t) const noexcept
{
return std::hash<TBaseType>()(t.base());
}
};
#endif /* STRONG_TYPEDEF_TYPE_HPP */ #endif /* STRONG_TYPEDEF_TYPE_HPP */

View File

@ -27,7 +27,6 @@
#include "effectvehicle_func.h" #include "effectvehicle_func.h"
#include "landscape_type.h" #include "landscape_type.h"
#include "animated_tile_func.h" #include "animated_tile_func.h"
#include "core/flatset_type.hpp"
#include "core/random_func.hpp" #include "core/random_func.hpp"
#include "object_base.h" #include "object_base.h"
#include "company_func.h" #include "company_func.h"
@ -43,6 +42,8 @@
#include "table/strings.h" #include "table/strings.h"
#include "table/sprites.h" #include "table/sprites.h"
#include <unordered_set>
#include "safeguards.h" #include "safeguards.h"
extern const TileTypeProcs extern const TileTypeProcs
@ -1298,28 +1299,26 @@ public:
*/ */
static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length)
{ {
uint height_begin = TileHeight(begin);
if (IsWaterTile(begin)) { if (IsWaterTile(begin)) {
return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 }; return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 };
} }
FlatSet<TileIndex> marks; int height_begin = TileHeight(begin);
std::unordered_set<TileIndex> marks;
marks.insert(begin); marks.insert(begin);
/* Breadth first search for the closest tile we can flow down to. */ std::vector<TileIndex> queue;
std::list<TileIndex> queue;
queue.push_back(begin); queue.push_back(begin);
/* Breadth first search for the closest tile we can flow down to. */
bool found = false; bool found = false;
uint count = 0; // Number of tiles considered; to be used for lake location guessing.
TileIndex end; TileIndex end;
do { for (size_t i = 0; i != queue.size(); i++) {
end = queue.front(); end = queue[i];
queue.pop_front();
uint height_end = TileHeight(end); int height_end;
if (IsTileFlat(end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) { if (IsTileFlat(end, &height_end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) {
found = true; found = true;
break; break;
} }
@ -1328,31 +1327,29 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
TileIndex t = end + TileOffsByDiagDir(d); TileIndex t = end + TileOffsByDiagDir(d);
if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) { if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) {
marks.insert(t); marks.insert(t);
count++;
queue.push_back(t); queue.push_back(t);
} }
} }
} while (!queue.empty()); }
bool main_river = false; bool main_river = false;
if (found) { if (found) {
/* Flow further down hill. */ /* Flow further down hill. */
std::tie(found, main_river) = FlowRiver(spring, end, min_river_length); std::tie(found, main_river) = FlowRiver(spring, end, min_river_length);
} else if (count > 32) { } else if (queue.size() > 32) {
/* Maybe we can make a lake. Find the Nth of the considered tiles. */ /* Maybe we can make a lake. Find the Nth of the considered tiles. */
auto cit = marks.cbegin(); TileIndex lake_centre = queue[RandomRange(static_cast<uint32_t>(queue.size()))];
std::advance(cit, RandomRange(count - 1)); int height_lake;
TileIndex lake_centre = *cit;
if (IsValidTile(lake_centre) && if (IsValidTile(lake_centre) &&
/* A river, or lake, can only be built on flat slopes. */
IsTileFlat(lake_centre) &&
/* We want the lake to be built at the height of the river. */
TileHeight(begin) == TileHeight(lake_centre) &&
/* We don't want the lake at the entry of the valley. */ /* We don't want the lake at the entry of the valley. */
lake_centre != begin && lake_centre != begin &&
/* We don't want lakes in the desert. */ /* We don't want lakes in the desert. */
(_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) && (_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) &&
/* A river, or lake, can only be built on flat slopes. */
IsTileFlat(lake_centre, &height_lake) &&
/* We want the lake to be built at the height of the river. */
height_lake == height_begin &&
/* We only want a lake if the river is long enough. */ /* We only want a lake if the river is long enough. */
DistanceManhattan(spring, lake_centre) > min_river_length) { DistanceManhattan(spring, lake_centre) > min_river_length) {
end = lake_centre; end = lake_centre;
@ -1362,7 +1359,7 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
/* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */ /* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */
for (uint loops = 0; loops < 2; ++loops) { for (uint loops = 0; loops < 2; ++loops) {
for (auto tile : SpiralTileSequence(lake_centre, diameter)) { for (auto tile : SpiralTileSequence(lake_centre, diameter)) {
MakeLake(tile, height_begin); MakeLake(tile, height_lake);
} }
} }
@ -1370,7 +1367,6 @@ static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint
} }
} }
marks.clear();
if (found) RiverBuilder::Exec(begin, end, spring, main_river); if (found) RiverBuilder::Exec(begin, end, spring, main_river);
return { found, main_river }; return { found, main_river };
} }