Skip to content

Commit d3073f8

Browse files
committed
Fix province number vs index issues
1 parent d0b3fcb commit d3073f8

File tree

5 files changed

+61
-50
lines changed

5 files changed

+61
-50
lines changed

src/openvic-simulation/map/MapDefinition.cpp

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <algorithm>
77
#include <cstddef>
88
#include <cstdint>
9+
#include <limits>
910
#include <system_error>
1011
#include <vector>
1112

@@ -21,6 +22,7 @@
2122
#include "openvic-simulation/modifier/ModifierManager.hpp"
2223
#include "openvic-simulation/types/Colour.hpp"
2324
#include "openvic-simulation/types/OrderedContainersMath.hpp"
25+
#include "openvic-simulation/types/TypedSpan.hpp"
2426
#include "openvic-simulation/types/Vector.hpp"
2527
#include "openvic-simulation/utility/BMP.hpp"
2628
#include "openvic-simulation/utility/FormatValidate.hpp"
@@ -48,11 +50,14 @@ ProvinceDefinition const* MapDefinition::get_province_definition_from_number(
4850
RiverSegment::RiverSegment(uint8_t new_size, memory::vector<ivec2_t>&& new_points)
4951
: size { new_size }, points { std::move(new_points) } {}
5052

53+
//1 entry reserved for null province
54+
static constexpr std::size_t MAX_PROVINCE_COUNT = type_safe::get(std::numeric_limits<province_index_t>().max()) - 1;
55+
5156
bool MapDefinition::add_province_definition(std::string_view identifier, colour_t colour) {
5257
if (province_definitions.size() >= type_safe::get(max_provinces)) {
5358
spdlog::error_s(
5459
"The map's province list is full - maximum number of provinces is {} (this can be at most {})",
55-
max_provinces, ProvinceDefinition::MAX_INDEX
60+
max_provinces, MAX_PROVINCE_COUNT
5661
);
5762
return false;
5863
}
@@ -71,24 +76,24 @@ bool MapDefinition::add_province_definition(std::string_view identifier, colour_
7176
spdlog::error_s("Invalid province colour for {} - null! ({})", identifier, colour);
7277
return false;
7378
}
74-
const ProvinceDefinition::index_t province_number = get_province_number_from_colour(colour);
75-
if (province_number != ProvinceDefinition::NULL_INDEX) {
79+
const province_number_t province_number = get_province_number_from_colour(colour);
80+
if (province_number != ProvinceDefinition::NULL_PROVINCE_NUMBER) {
7681
spdlog::error_s(
7782
"Duplicate province colours: {} and {}",
78-
get_province_definition_from_number(type_safe::get(province_number))->to_string(), identifier
83+
get_province_definition_from_number(province_number)->to_string(), identifier
7984
);
8085
return false;
8186
}
8287

8388
if (!province_definitions.emplace_item(
8489
identifier,
85-
identifier, colour, ProvinceDefinition::index_t(get_province_definition_count())
90+
identifier, colour, province_index_t(get_province_definition_count())
8691
)) {
8792
return false;
8893
}
8994

9095
ProvinceDefinition const& new_province = province_definitions.back();
91-
colour_index_map[new_province.get_colour()] = ProvinceDefinition::index_t(new_province.get_province_number());
96+
colour_index_map[new_province.get_colour()] = province_index_t(new_province.get_province_number());
9297
return true;
9398
}
9499

@@ -468,34 +473,34 @@ bool MapDefinition::add_region(std::string_view identifier, memory::vector<Provi
468473
return ret;
469474
}
470475

471-
ProvinceDefinition::index_t MapDefinition::get_province_number_from_colour(colour_t colour) const {
476+
MapDefinition::province_number_t MapDefinition::get_province_number_from_colour(colour_t colour) const {
472477
const colour_index_map_t::const_iterator it = colour_index_map.find(colour);
473478
if (it != colour_index_map.end()) {
474-
return it->second;
479+
return ProvinceDefinition::get_province_number_from_index(it.value());
475480
}
476-
return ProvinceDefinition::NULL_INDEX;
481+
return ProvinceDefinition::NULL_PROVINCE_NUMBER;
477482
}
478483

479-
ProvinceDefinition::index_t MapDefinition::get_province_number_at(ivec2_t pos) const {
484+
MapDefinition::province_number_t MapDefinition::get_province_number_at(ivec2_t pos) const {
480485
if (pos.nonnegative() && pos.is_within_bound(dims)) {
481486
return province_shape_image[get_pixel_index_from_pos(pos)].province_number;
482487
}
483-
return ProvinceDefinition::NULL_INDEX;
488+
return ProvinceDefinition::NULL_PROVINCE_NUMBER;
484489
}
485490

486491
ProvinceDefinition* MapDefinition::get_province_definition_at(ivec2_t pos) {
487-
return get_province_definition_from_number(type_safe::get(get_province_number_at(pos)));
492+
return get_province_definition_from_number(get_province_number_at(pos));
488493
}
489494

490495
ProvinceDefinition const* MapDefinition::get_province_definition_at(ivec2_t pos) const {
491-
return get_province_definition_from_number(type_safe::get(get_province_number_at(pos)));
496+
return get_province_definition_from_number(get_province_number_at(pos));
492497
}
493498

494-
bool MapDefinition::set_max_provinces(ProvinceDefinition::index_t new_max_provinces) {
495-
if (new_max_provinces <= ProvinceDefinition::NULL_INDEX) {
499+
bool MapDefinition::set_max_provinces(province_index_t new_max_provinces) {
500+
if (new_max_provinces <= province_index_t(0)) {
496501
spdlog::error_s(
497-
"Trying to set max province count to an invalid value {} (must be greater than {})",
498-
new_max_provinces, ProvinceDefinition::NULL_INDEX
502+
"Trying to set max province count to an invalid value {} (must be greater than 0)",
503+
new_max_provinces
499504
);
500505
return false;
501506
}
@@ -847,19 +852,22 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
847852
uint8_t const* province_data = province_bmp.get_pixel_data().data();
848853
uint8_t const* terrain_data = terrain_bmp.get_pixel_data().data();
849854

850-
memory::vector<fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list(province_definitions.size());
855+
memory::FixedVector<fixed_point_map_t<TerrainType const*>> _terrain_type_pixels_list(province_definitions.size());
856+
TypedSpan<province_index_t, fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list { _terrain_type_pixels_list };
851857

852858
bool ret = true;
853859
ordered_set<colour_t> unrecognised_province_colours;
854860

855-
memory::vector<fixed_point_t> pixels_per_province(province_definitions.size());
856-
memory::vector<fvec2_t> pixel_position_sum_per_province(province_definitions.size());
861+
memory::FixedVector<fixed_point_t> _pixels_per_province(province_definitions.size());
862+
TypedSpan<province_index_t, fixed_point_t> pixels_per_province { _pixels_per_province };
863+
memory::FixedVector<fvec2_t> _pixel_position_sum_per_province(province_definitions.size());
864+
TypedSpan<province_index_t, fvec2_t> pixel_position_sum_per_province { _pixel_position_sum_per_province };
857865

858866
for (ivec2_t pos {}; pos.y < get_height(); ++pos.y) {
859867
for (pos.x = 0; pos.x < get_width(); ++pos.x) {
860868
const size_t pixel_index = get_pixel_index_from_pos(pos);
861869
const colour_t province_colour = colour_at(province_data, pixel_index);
862-
ProvinceDefinition::index_t province_number = ProvinceDefinition::NULL_INDEX;
870+
province_number_t province_number = ProvinceDefinition::NULL_PROVINCE_NUMBER;
863871

864872
if (pos.x > 0) {
865873
const size_t jdx = pixel_index - 1;
@@ -879,7 +887,7 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
879887

880888
province_number = get_province_number_from_colour(province_colour);
881889

882-
if (province_number == ProvinceDefinition::NULL_INDEX && !unrecognised_province_colours.contains(province_colour)) {
890+
if (province_number == ProvinceDefinition::NULL_PROVINCE_NUMBER && !unrecognised_province_colours.contains(province_colour)) {
883891
unrecognised_province_colours.insert(province_colour);
884892
if (detailed_errors) {
885893
spdlog::warn_s(
@@ -892,17 +900,18 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
892900
index_found:
893901
province_shape_image[pixel_index].province_number = province_number;
894902

895-
if (province_number != ProvinceDefinition::NULL_INDEX) {
896-
const ProvinceDefinition::index_t array_index = province_number - 1;
897-
pixels_per_province[type_safe::get(array_index)]++;
898-
pixel_position_sum_per_province[type_safe::get(array_index)] += static_cast<fvec2_t>(pos);
903+
if (province_number != ProvinceDefinition::NULL_PROVINCE_NUMBER) {
904+
const province_index_t province_index = ProvinceDefinition::get_index_from_province_number(province_number);
905+
pixels_per_province[province_index]++;
906+
pixel_position_sum_per_province[province_index] += static_cast<fvec2_t>(pos);
899907
}
900908

901909
const TerrainTypeMapping::index_t terrain = terrain_data[pixel_index];
902910
TerrainTypeMapping const* mapping = terrain_type_manager.get_terrain_type_mapping_for(terrain);
903911
if (mapping != nullptr) {
904-
if (province_number != ProvinceDefinition::NULL_INDEX) {
905-
terrain_type_pixels_list[type_safe::get(province_number - 1)][&mapping->type]++;
912+
if (province_number != ProvinceDefinition::NULL_PROVINCE_NUMBER) {
913+
const province_index_t province_index = ProvinceDefinition::get_index_from_province_number(province_number);
914+
terrain_type_pixels_list[province_index][&mapping->type]++;
906915
}
907916
if (mapping->has_texture && terrain < terrain_type_manager.get_terrain_texture_limit()) {
908917
province_shape_image[pixel_index].terrain = terrain + 1;
@@ -920,21 +929,20 @@ bool MapDefinition::load_map_images(fs::path const& province_path, fs::path cons
920929
}
921930

922931
size_t missing = 0;
923-
for (size_t array_index = 0; array_index < province_definitions.size(); ++array_index) {
924-
ProvinceDefinition* province = province_definitions.get_item_by_index(array_index);
925-
926-
fixed_point_map_t<TerrainType const*> const& terrain_type_pixels = terrain_type_pixels_list[array_index];
932+
for (ProvinceDefinition& province : province_definitions.get_items()) {
933+
const province_index_t province_index = province.index;
934+
fixed_point_map_t<TerrainType const*> const& terrain_type_pixels = terrain_type_pixels_list[province_index];
927935
const fixed_point_map_const_iterator_t<TerrainType const*> largest = get_largest_item(terrain_type_pixels);
928-
province->default_terrain_type = largest != terrain_type_pixels.end() ? largest->first : nullptr;
936+
province.default_terrain_type = largest != terrain_type_pixels.end() ? largest->first : nullptr;
929937

930-
const fixed_point_t pixel_count = pixels_per_province[array_index];
931-
province->on_map = pixel_count > 0;
938+
const fixed_point_t pixel_count = pixels_per_province[province_index];
939+
province.on_map = pixel_count > 0;
932940

933-
if (province->on_map) {
934-
province->centre = pixel_position_sum_per_province[array_index] / pixel_count;
941+
if (province.on_map) {
942+
province.centre = pixel_position_sum_per_province[province_index] / pixel_count;
935943
} else {
936944
if (detailed_errors) {
937-
spdlog::warn_s("Province missing from shape image: {}", province->to_string());
945+
spdlog::warn_s("Province missing from shape image: {}", province.to_string());
938946
}
939947
missing++;
940948
}

src/openvic-simulation/map/MapDefinition.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ namespace OpenVic {
4040
* MAP-4
4141
*/
4242
struct MapDefinition {
43-
43+
using province_number_t = decltype(std::declval<ProvinceDefinition>().get_province_number());
4444
#pragma pack(push, 1)
4545
/* Used to represent tightly packed 3-byte integer pixel information. */
4646
struct shape_pixel_t {
47-
ProvinceDefinition::index_t province_number;
47+
province_number_t province_number;
4848
TerrainTypeMapping::index_t terrain;
4949
};
5050
#pragma pack(pop)
@@ -67,12 +67,12 @@ namespace OpenVic {
6767
memory::vector<shape_pixel_t> PROPERTY(province_shape_image);
6868
colour_index_map_t colour_index_map;
6969

70-
ProvinceDefinition::index_t PROPERTY(max_provinces, ProvinceDefinition::MAX_INDEX);
70+
ProvinceDefinition::index_t PROPERTY(max_provinces);
7171

7272
PointMap PROPERTY_REF(path_map_land);
7373
PointMap PROPERTY_REF(path_map_sea);
7474

75-
ProvinceDefinition::index_t get_province_number_from_colour(colour_t colour) const;
75+
province_number_t get_province_number_from_colour(colour_t colour) const;
7676
bool _generate_standard_province_adjacencies();
7777

7878
inline constexpr int32_t get_pixel_index_from_pos(ivec2_t pos) const {
@@ -85,10 +85,10 @@ namespace OpenVic {
8585
MapDefinition();
8686

8787
ProvinceDefinition* get_province_definition_from_number(
88-
decltype(std::declval<ProvinceDefinition>().get_province_number())province_number
88+
const province_number_t province_number
8989
);
9090
ProvinceDefinition const* get_province_definition_from_number(
91-
decltype(std::declval<ProvinceDefinition>().get_province_number())province_number
91+
const province_number_t province_number
9292
) const;
9393

9494
inline constexpr int32_t get_width() const { return dims.x; }
@@ -112,7 +112,7 @@ namespace OpenVic {
112112
size_t get_land_province_count() const;
113113
size_t get_water_province_count() const;
114114

115-
ProvinceDefinition::index_t get_province_number_at(ivec2_t pos) const;
115+
province_number_t get_province_number_at(ivec2_t pos) const;
116116

117117
private:
118118
ProvinceDefinition* get_province_definition_at(ivec2_t pos);

src/openvic-simulation/map/Mapmode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ bool MapmodeManager::generate_mapmode_colours(
8888

8989
Mapmode::base_stripe_t* target_stripes = reinterpret_cast<Mapmode::base_stripe_t*>(target);
9090

91-
target_stripes[type_safe::get(ProvinceDefinition::NULL_INDEX)] = colour_argb_t::null();
91+
target_stripes[ProvinceDefinition::NULL_PROVINCE_NUMBER] = colour_argb_t::null();
9292

9393
for (ProvinceInstance const& province : map_instance.get_province_instances()) {
9494
target_stripes[province.province_definition.get_province_number()] = mapmode->get_base_stripe_colours(

src/openvic-simulation/map/Mapmode.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ namespace OpenVic {
7070
/* The mapmode colour image contains of a list of base colours and stripe colours. Each colour is four bytes
7171
* in RGBA format, with the alpha value being used to interpolate with the terrain colour, so A = 0 is fully terrain
7272
* and A = 255 is fully the RGB colour packaged with A. The base and stripe colours for each province are packed
73-
* together adjacently, so each province's entry is 8 bytes long. The list contains ProvinceDefinition::MAX_INDEX + 1
74-
* entries, that is the maximum allowed number of provinces plus one for the index-zero "null province". */
73+
* together adjacently, so each province's entry is 8 bytes long.
74+
* The list contains all provinces indexed by their number + index 0 for the "null province". */
7575
bool generate_mapmode_colours(
7676
MapInstance const& map_instance, Mapmode const* mapmode,
7777
CountryInstance const* player_country, ProvinceInstance const* selected_province,

src/openvic-simulation/map/ProvinceDefinition.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ namespace OpenVic {
8484
fixed_point_map_t<BuildingType const*> building_rotation;
8585
};
8686

87-
static constexpr index_t NULL_INDEX { 0 }, MAX_INDEX = std::numeric_limits<index_t>::max();
87+
static constexpr type_safe::underlying_type<index_t> NULL_PROVINCE_NUMBER { 0 };
8888

8989
private:
9090
/* Immutable attributes (unchanged after initial game load) */
@@ -115,7 +115,10 @@ namespace OpenVic {
115115
}
116116

117117
constexpr std::size_t get_province_number() const {
118-
return index.value_ + 1;
118+
return get_province_number_from_index(index);
119+
}
120+
static constexpr std::size_t get_province_number_from_index(const province_index_t index) {
121+
return type_safe::get(index) + 1;
119122
}
120123
static constexpr index_t get_index_from_province_number(const std::size_t province_number) {
121124
return index_t(province_number - 1);

0 commit comments

Comments
 (0)