1
0
Fork 0

Compare commits

...

5 Commits

Author SHA1 Message Date
SamuXarick b1440a8270
Merge 3d8dad2cc6 into 7546c1acab 2025-07-14 08:01:51 +00:00
Peter Nelson 7546c1acab
Codefix f220ed179d: GetUnicodeGlyph takes a unicode character. (#14438)
Previous change erroneously changed type to GlyphID, based on naming. It should actually be char32_t.
2025-07-14 08:01:42 +00:00
Peter Nelson a6143eea21
Codechange: Include more relevant headers for script_storage. (#14437) 2025-07-14 07:49:50 +01:00
SamuXarick 3d8dad2cc6 Codechange: Optimize FlowRiver
Make all height_tile int to allow comparison between heights generated from TileHeight and heights generated from IsTileFlat.
Make the first check IsWaterTile as that is the first thing that should be checked for FlowRiver recursive calls. Swaps position with height_begin.
Change FlatSet to std::unordered_set which is faster at the contains function.
Change std::list to std::vector to be a queue, but do not pop items from it when advancing the queue. The tiles in it are ordered by insertion which is what's needed for the n-th tile to make lake_centre.
count is not required. It can be extracted from either the unordered set or the vector.
Swap the order of checks for determining the validity of lake_centre tile, making IsTileFlat and DistanceManhattan the last ones to check as I believe are the most computational.
2025-05-08 12:26:39 +01:00
SamuXarick 7ddbd1643e Codechange: Implementation of std::hash for StrongType::Typedef 2025-05-08 10:15:21 +01:00
6 changed files with 64 additions and 41 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

@ -43,26 +43,26 @@ SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs)
} }
/** /**
* Get SpriteID associated with a GlyphID. * Get SpriteID associated with a character.
* @param key Glyph to find. * @param key Character to find.
* @return SpriteID of glyph, or 0 if not present. * @return SpriteID for character, or 0 if not present.
*/ */
SpriteID SpriteFontCache::GetUnicodeGlyph(GlyphID key) SpriteID SpriteFontCache::GetUnicodeGlyph(char32_t key)
{ {
const auto found = this->glyph_to_spriteid_map.find(key & ~SPRITE_GLYPH); const auto found = this->char_map.find(key);
if (found == std::end(this->glyph_to_spriteid_map)) return 0; if (found == std::end(this->char_map)) return 0;
return found->second; return found->second;
} }
void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite) void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite)
{ {
this->glyph_to_spriteid_map[key] = sprite; this->char_map[key] = sprite;
} }
void SpriteFontCache::InitializeUnicodeGlyphMap() void SpriteFontCache::InitializeUnicodeGlyphMap()
{ {
/* Clear out existing glyph map if it exists */ /* Clear out existing glyph map if it exists */
this->glyph_to_spriteid_map.clear(); this->char_map.clear();
SpriteID base; SpriteID base;
switch (this->fs) { switch (this->fs) {

View File

@ -28,8 +28,8 @@ public:
bool IsBuiltInFont() override { return true; } bool IsBuiltInFont() override { return true; }
private: private:
std::unordered_map<GlyphID, SpriteID> glyph_to_spriteid_map{}; ///< Mapping of glyphs to sprite IDs. std::unordered_map<char32_t, SpriteID> char_map{}; ///< Mapping of characters to sprite IDs.
SpriteID GetUnicodeGlyph(GlyphID key); SpriteID GetUnicodeGlyph(char32_t key);
}; };
#endif /* SPRITEFONTCACHE_H */ #endif /* SPRITEFONTCACHE_H */

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 };
} }

View File

@ -24,10 +24,12 @@
#include "api/script_event.hpp" #include "api/script_event.hpp"
#include "api/script_log.hpp" #include "api/script_log.hpp"
#include "../company_base.h" #include "../company_type.h"
#include "../company_func.h"
#include "../fileio_func.h" #include "../fileio_func.h"
#include "../goal_type.h"
#include "../league_type.h" #include "../league_type.h"
#include "../signs_type.h"
#include "../story_type.h"
#include "../misc/endian_buffer.hpp" #include "../misc/endian_buffer.hpp"
#include "../safeguards.h" #include "../safeguards.h"

View File

@ -12,12 +12,10 @@
#include <queue> #include <queue>
#include "../signs_func.h" #include "../command_type.h"
#include "../vehicle_func.h" #include "../company_type.h"
#include "../rail_type.h"
#include "../road_type.h" #include "../road_type.h"
#include "../group.h"
#include "../goal_type.h"
#include "../story_type.h"
#include "script_types.hpp" #include "script_types.hpp"
#include "script_log_types.hpp" #include "script_log_types.hpp"