• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ParadoxGameConverters / Vic2ToHoI4 / 41374112180

02 Nov 2026 01:45AM UTC coverage: 65.277% (-0.3%) from 65.598%
41374112180

push

github

web-flow
Bump github/codeql-action from 4.38.2 to 4.39.1 (#1789)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.38.2 to 4.39.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v4.38.2...v4.39.1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.39.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

30199 of 46263 relevant lines covered (65.28%)

27418.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.27
/src/Maps/MapData.cpp
1
#include "src/Maps/MapData.h"
2
#include "external/bitmap/bitmap_image.hpp"
3
#include "external/common_items/Color.h"
4
#include "external/common_items/Log.h"
5
#include "src/Configuration.h"
6

7

8

9
namespace
10
{
11

12
commonItems::Color GetCenterColor(const Maps::Point position, const bitmap_image& province_map)
23,040,008 ✔
13
{
14
        rgb_t color{0, 0, 0};
23,040,008 ✔
15
        province_map.get_pixel(position.first, position.second, color);
23,040,008 ✔
16

17
        return commonItems::Color(std::array<int, 3>{color.red, color.green, color.blue});
46,080,016 ✔
18
}
19

20

21
commonItems::Color GetAboveColor(Maps::Point position, const bitmap_image& province_map)
23,040,008 ✔
22
{
23
        if (position.second > 0)
23,040,008 ✔
24
        {
25
                position.second--;
23,001,600 ✔
26
        }
27

28
        rgb_t color{0, 0, 0};
23,040,008 ✔
29
        province_map.get_pixel(position.first, position.second, color);
23,040,008 ✔
30

31
        return commonItems::Color(std::array<int, 3>{color.red, color.green, color.blue});
46,080,016 ✔
32
}
33

34

35
commonItems::Color GetBelowColor(Maps::Point position, int height, const bitmap_image& province_map)
23,040,008 ✔
36
{
37
        if (position.second < height - 1)
23,040,008 ✔
38
        {
39
                position.second++;
23,001,600 ✔
40
        }
41

42
        rgb_t color{0, 0, 0};
23,040,008 ✔
43
        province_map.get_pixel(position.first, position.second, color);
23,040,008 ✔
44

45
        return commonItems::Color(std::array<int, 3>{color.red, color.green, color.blue});
46,080,016 ✔
46
}
47

48

49
commonItems::Color GetLeftColor(Maps::Point position, int width, const bitmap_image& province_map)
23,040,008 ✔
50
{
51
        if (position.first > 0)
23,040,008 ✔
52
        {
53
                position.first--;
23,011,200 ✔
54
        }
55
        else
56
        {
57
                position.first = width - 1;
28,808 ✔
58
        }
59

60
        rgb_t color{0, 0, 0};
23,040,008 ✔
61
        province_map.get_pixel(position.first, position.second, color);
23,040,008 ✔
62

63
        return commonItems::Color(std::array<int, 3>{color.red, color.green, color.blue});
46,080,016 ✔
64
}
65

66

67
commonItems::Color GetRightColor(Maps::Point position, int width, const bitmap_image& province_map)
23,040,008 ✔
68
{
69
        if (position.first < width - 1)
23,040,008 ✔
70
        {
71
                position.first++;
23,011,200 ✔
72
        }
73
        else
74
        {
75
                position.first = 0;
28,808 ✔
76
        }
77

78
        rgb_t color{0, 0, 0};
23,040,008 ✔
79
        province_map.get_pixel(position.first, position.second, color);
23,040,008 ✔
80

81
        return commonItems::Color(std::array<int, 3>{color.red, color.green, color.blue});
46,080,016 ✔
82
}
83

84
} // namespace
85

86

87
Maps::MapData::MapData(const ProvinceDefinitions& province_definitions,
58 ✔
88
         const commonItems::ModFilesystem& mod_filesystem): province_definitions_(province_definitions)
58 ✔
89
{
90
        ImportProvinces(mod_filesystem);
58 ✔
91
        ImportAdjacencies(mod_filesystem);
56 ✔
92
}
66 ✔
93

94
Maps::MapData::MapData(const ProvinceDefinitions& province_definitions, const std::filesystem::path& path):
×
95
         province_definitions_(province_definitions)
×
96
{
97
        ImportProvinces(path);
×
98
        ImportAdjacencies(path);
×
99
}
×
100

101

102
void Maps::MapData::ImportProvinces(const commonItems::ModFilesystem& mod_filesystem)
58 ✔
103
{
104
        const auto path = mod_filesystem.GetActualFileLocation("map/provinces.bmp");
58 ✔
105
        if (!path)
58 ✔
106
        {
107
                throw std::runtime_error("Could not find map/provinces.bmp");
2 ✔
108
        }
109
        ImportProvinces(*path);
56 ✔
110
}
58 ✔
111

112

113
void Maps::MapData::ImportProvinces(const std::filesystem::path& path)
56 ✔
114
{
115
        std::filesystem::path full_path = path;
56 ✔
116
        if (!path.string().contains("map/provinces.bmp") && !path.string().contains("map\\provinces.bmp"))
56 ✔
117
        {
118
                full_path = path / "map/provinces.bmp";
×
119
        }
120

121
        bitmap_image province_map(full_path.string());
56 ✔
122
        if (!province_map)
56 ✔
123
        {
124
                throw std::runtime_error("Could not open " + (full_path / "map/provinces.bmp").string());
×
125
        }
126

127
        height = static_cast<int>(province_map.height());
56 ✔
128
        width = static_cast<int>(province_map.width());
56 ✔
129
        province_number_by_point_.assign(static_cast<std::size_t>(width) * height, -1);
56 ✔
130
        for (int y = 0; y < height; y++)
28,864 ✔
131
        {
132
                for (int x = 0; x < width; x++)
23,068,816 ✔
133
                {
134
                        Point position = {x, y};
23,040,008 ✔
135

136
                        auto center_color = GetCenterColor(position, province_map);
23,040,008 ✔
137
                        auto above_color = GetAboveColor(position, province_map);
23,040,008 ✔
138
                        auto below_color = GetBelowColor(position, height, province_map);
23,040,008 ✔
139
                        auto left_color = GetLeftColor(position, width, province_map);
23,040,008 ✔
140
                        auto right_color = GetRightColor(position, width, province_map);
23,040,008 ✔
141

142
                        position.second = height - y - 1;
23,040,008 ✔
143
                        if (center_color != above_color)
23,040,008 ✔
144
                        {
145
                                HandleNeighbor(center_color, above_color, position);
5,184 ✔
146
                        }
147
                        if (center_color != right_color)
23,040,008 ✔
148
                        {
149
                                HandleNeighbor(center_color, right_color, position);
5,616 ✔
150
                        }
151
                        if (center_color != below_color)
23,040,008 ✔
152
                        {
153
                                HandleNeighbor(center_color, below_color, position);
5,184 ✔
154
                        }
155
                        if (center_color != left_color)
23,040,008 ✔
156
                        {
157
                                HandleNeighbor(center_color, left_color, position);
5,616 ✔
158
                        }
159

160
                        if (auto province = province_definitions_.getProvinceFromColor(center_color); province)
23,040,008 ✔
161
                        {
162
                                const auto point_index = static_cast<std::size_t>(position.second) * width + static_cast<std::size_t>(x);
22,761 ✔
163
                                province_number_by_point_[point_index] = *province;
22,761 ✔
164

165
                                if (auto specific_province_points = the_province_points_.find(*province);
22,761 ✔
166
                                         specific_province_points != the_province_points_.end())
22,761 ✔
167
                                {
168
                                        specific_province_points->second.addPoint(position);
22,480 ✔
169
                                }
170
                                else
171
                                {
172
                                        ProvincePoints the_new_points;
281 ✔
173
                                        the_new_points.addPoint(position);
281 ✔
174
                                        the_province_points_.insert(std::make_pair(*province, the_new_points));
281 ✔
175
                                }
281 ✔
176
                        }
177
                }
178
        }
179
}
56 ✔
180

181

182
void Maps::MapData::HandleNeighbor(const commonItems::Color& center_color,
21,600 ✔
183
         const commonItems::Color& other_color,
184
         const Point& position)
185
{
186
        const auto center_province = province_definitions_.getProvinceFromColor(center_color);
21,600 ✔
187
        const auto other_province = province_definitions_.getProvinceFromColor(other_color);
21,600 ✔
188
        if (center_province && other_province)
21,600 ✔
189
        {
190
                AddNeighbor(*center_province, *other_province);
3,150 ✔
191
                AddPointToBorder(*center_province, *other_province, position);
3,150 ✔
192
        }
193
}
21,600 ✔
194

195

196
void Maps::MapData::AddNeighbor(int main_province, int neighbor_province)
3,222 ✔
197
{
198
        if (const auto center_mapping = province_neighbors_.find(main_province); center_mapping != province_neighbors_.end())
3,222 ✔
199
        {
200
                center_mapping->second.insert(neighbor_province);
2,902 ✔
201
        }
202
        else
203
        {
204
                const std::set<int> neighbors = {neighbor_province};
640 ✔
205
                province_neighbors_[main_province] = neighbors;
320 ✔
206
        }
320 ✔
207
}
3,222 ✔
208

209

210
void Maps::MapData::RemoveNeighbor(int main_province, int neighbor_province)
36 ✔
211
{
212
        if (const auto center_mapping = province_neighbors_.find(main_province); center_mapping != province_neighbors_.end())
36 ✔
213
        {
214
                center_mapping->second.erase(neighbor_province);
10 ✔
215
        }
216
}
36 ✔
217

218

219
void Maps::MapData::AddPointToBorder(int main_province, int neighbor_province, const Point position)
3,150 ✔
220
{
221
        auto borders_with_neighbors = borders_.find(main_province);
3,150 ✔
222
        if (borders_with_neighbors == borders_.end())
3,150 ✔
223
        {
224
                BordersWith new_borders_with_neighbors;
248 ✔
225
                borders_.insert(make_pair(main_province, new_borders_with_neighbors));
248 ✔
226
                borders_with_neighbors = borders_.find(main_province);
248 ✔
227
        }
248 ✔
228

229
        auto border = borders_with_neighbors->second.find(neighbor_province);
3,150 ✔
230
        if (border == borders_with_neighbors->second.end())
3,150 ✔
231
        {
232
                BorderPoints new_border;
350 ✔
233
                borders_with_neighbors->second.insert(make_pair(neighbor_province, new_border));
350 ✔
234
                border = borders_with_neighbors->second.find(neighbor_province);
350 ✔
235
        }
350 ✔
236

237
        if (border->second.empty())
3,150 ✔
238
        {
239
                border->second.push_back(position);
350 ✔
240
        }
241
        else
242
        {
243
                if (const auto last_point = border->second.back();
2,800 ✔
244
                         (last_point.first != position.first) || (last_point.second != position.second))
2,800 ✔
245
                {
246
                        border->second.push_back(position);
2,800 ✔
247
                }
248
        }
249
}
3,150 ✔
250

251

252
void Maps::MapData::ImportAdjacencies(const commonItems::ModFilesystem& mod_filesystem)
56 ✔
253
{
254
        const auto path = mod_filesystem.GetActualFileLocation("map/adjacencies.csv");
56 ✔
255
        if (!path)
56 ✔
256
        {
257
                throw std::runtime_error("Could not find map/adjacencies.csv");
×
258
        }
259
        ImportAdjacencies(*path);
56 ✔
260
}
56 ✔
261

262

263
void Maps::MapData::ImportAdjacencies(const std::filesystem::path& path)
56 ✔
264
{
265
        std::filesystem::path full_path = path;
56 ✔
266
        if (!path.string().contains("map/adjacencies.csv") && !path.string().contains("map\\adjacencies.csv"))
56 ✔
267
        {
268
                full_path = path / "map/adjacencies.csv";
×
269
        }
270

271
        std::ifstream adjacencies_file(full_path);
56 ✔
272
        if (!adjacencies_file.is_open())
56 ✔
273
        {
274
                throw std::runtime_error("Could not open " + full_path.string());
×
275
        }
276

277
        while (!adjacencies_file.eof())
220 ✔
278
        {
279
                std::string line;
164 ✔
280
                getline(adjacencies_file, line);
164 ✔
281
                if (line.starts_with('#'))
164 ✔
282
                {
283
                        continue;
36 ✔
284
                }
285

286
                const std::regex pattern("([^;]*);([^;]*);([^;]*)(.*)\r?");
128 ✔
287
                if (std::smatch matches; regex_match(line, matches, pattern))
128 ✔
288
                {
289
                        if (matches[1] == "From" || matches[1] == "-1")
90 ✔
290
                        {
291
                                continue;
18 ✔
292
                        }
293

294
                        if (matches[1].length() == 0)
72 ✔
295
                        {
296
                                continue;
18 ✔
297
                        }
298
                        const int first_province = std::stoi(matches[1]);
54 ✔
299
                        if (matches[2].length() == 0)
54 ✔
300
                        {
301
                                continue;
×
302
                        }
303
                        const int second_province = std::stoi(matches[2]);
54 ✔
304
                        if (matches[3] != "impassable")
54 ✔
305
                        {
306
                                AddNeighbor(first_province, second_province);
36 ✔
307
                                AddNeighbor(second_province, first_province);
36 ✔
308
                        }
309
                        else
310
                        {
311
                                RemoveNeighbor(first_province, second_province);
18 ✔
312
                                RemoveNeighbor(second_province, first_province);
18 ✔
313
                        }
314
                }
128 ✔
315
        }
200 ✔
316
}
56 ✔
317

318

319
std::set<int> Maps::MapData::GetNeighbors(int province) const
9 ✔
320
{
321
        const auto neighbors = province_neighbors_.find(province);
9 ✔
322
        if (neighbors == province_neighbors_.end())
9 ✔
323
        {
324
                return {};
1 ✔
325
        }
326

327
        return neighbors->second;
8 ✔
328
}
329

330

331
std::optional<Maps::Point> Maps::MapData::GetSpecifiedBorderCenter(int main_province, int neighbor) const
4 ✔
332
{
333
        const auto borders_with_neighbors = borders_.find(main_province);
4 ✔
334
        if (borders_with_neighbors == borders_.end())
4 ✔
335
        {
336
                Log(LogLevel::Warning) << "Province " << main_province << " has no borders.";
1 ✔
337
                return std::nullopt;
1 ✔
338
        }
339

340
        const auto border = borders_with_neighbors->second.find(neighbor);
3 ✔
341
        if (border == borders_with_neighbors->second.end())
3 ✔
342
        {
343
                Log(LogLevel::Warning) << "Province " << main_province << " does not border " << neighbor << ".";
1 ✔
344
                return std::nullopt;
1 ✔
345
        }
346

347
        return border->second[(border->second.size() / 2)];
2 ✔
348
}
349

350

351
std::optional<Maps::Point> Maps::MapData::GetAnyBorderCenter(const int province) const
3 ✔
352
{
353
        const auto borders_with_neighbors = borders_.find(province);
3 ✔
354
        if (borders_with_neighbors == borders_.end())
3 ✔
355
        {
356
                Log(LogLevel::Warning) << "Province " << province << " has no borders.";
2 ✔
357
                return std::nullopt;
2 ✔
358
        }
359

360
        const auto border = borders_with_neighbors->second.begin();
1 ✔
361
        // if a province has borders, by definition they're with some number of neighbors and of some length
362
        return border->second[(border->second.size() / 2)];
1 ✔
363
}
364

365

366
std::optional<int> Maps::MapData::GetProvinceNumber(const Point& point) const
3 ✔
367
{
368
        if (point.first < 0 || point.first >= width || point.second < 0 || point.second >= height)
3 ✔
369
        {
370
                return std::nullopt;
1 ✔
371
        }
372

373
        const auto point_index = static_cast<std::size_t>(point.second) * width + static_cast<std::size_t>(point.first);
2 ✔
374
        const auto province_number = province_number_by_point_[point_index];
2 ✔
375
        if (province_number == -1)
2 ✔
376
        {
377
                return std::nullopt;
1 ✔
378
        }
379
        return province_number;
1 ✔
380
}
381

382

383
std::optional<Maps::ProvincePoints> Maps::MapData::GetProvincePoints(int province_num) const
2 ✔
384
{
385
        const auto possible_points = the_province_points_.find(province_num);
2 ✔
386
        if (possible_points == the_province_points_.end())
2 ✔
387
        {
388
                return std::nullopt;
1 ✔
389
        }
390
        return possible_points->second;
1 ✔
391
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc