14#define WIN32_LEAN_AND_MEAN
31 std::vector<uint8_t> output_data(map_size.x * map_size.y, fill);
35 auto terrain_bmp = open_file(map_dir, name);
66 } __attribute__((__packed__))
77 int32_t biXPelsPerMeter;
78 int32_t biYPelsPerMeter;
81 } __attribute__((__packed__))
100 int32_t bV4XPelsPerMeter;
101 int32_t bV4YPelsPerMeter;
119 uint16_t bV5BitCount;
122 int32_t bV5XPelsPerMeter;
123 int32_t bV5YPelsPerMeter;
131 CIEXYZTRIPLE bV5Endpoints;
141 const int BI_RGB = 0;
142 const int BI_RLE8 = 1;
143 const int BI_RLE4 = 2;
147 int32_t compression_type = 0;
153 bool has_BI_BITFIELDS =
false;
154 bool has_BI_ALPHABITFIELDS =
false;
156 BITMAPFILEHEADER
const* fh = (BITMAPFILEHEADER
const*)(start);
157 uint8_t const* data = start + fh->bfOffBits;
158 std::unique_ptr<uint8_t[]> decompressed_data;
160 auto color_table_offset = start +
sizeof(BITMAPFILEHEADER);
162 BITMAPCOREHEADER
const* core_h = (BITMAPCOREHEADER
const*)(start +
sizeof(BITMAPFILEHEADER));
163 if(core_h->bcSize ==
sizeof(BITMAPINFOHEADER)) {
164 BITMAPINFOHEADER
const* h = (BITMAPINFOHEADER
const*)(start +
sizeof(BITMAPFILEHEADER));
166 size_y = h->biHeight;
167 num_of_colors = h->biClrUsed;
168 if(num_of_colors == 0) {
169 num_of_colors = 1 << h->biBitCount;
171 if(h->biCompression == BI_RLE8) {
172 compression_type = 1;
174 color_table_offset +=
sizeof(BITMAPINFOHEADER);
175 }
else if(core_h->bcSize ==
sizeof(BITMAPV5HEADER)) {
176 BITMAPV5HEADER
const* h = (BITMAPV5HEADER
const*)(start +
sizeof(BITMAPFILEHEADER));
177 if(h->bV5Compression == BI_RLE8) {
178 compression_type = 1;
180 size_x = h->bV5Width;
181 size_y = h->bV5Height;
182 num_of_colors = h->bV5ClrUsed;
183 if(num_of_colors == 0) {
184 num_of_colors = 1 << h->bV5BitCount;
186 color_table_offset +=
sizeof(BITMAPV5HEADER);
187 }
else if(core_h->bcSize ==
sizeof(BITMAPV4HEADER)) {
188 BITMAPV4HEADER
const* h = (BITMAPV4HEADER
const*)(start +
sizeof(BITMAPFILEHEADER));
189 if(h->bV4V4Compression == BI_RLE8) {
190 compression_type = 1;
192 size_x = h->bV4Width;
193 size_y = h->bV4Height;
194 num_of_colors = h->bV4ClrUsed;
195 if(num_of_colors == 0) {
196 num_of_colors = 1 << h->bV4BitCount;
198 color_table_offset +=
sizeof(BITMAPV4HEADER);
199 }
else if(core_h->bcSize ==
sizeof(BITMAPCOREHEADER)) {
200 BITMAPCOREHEADER
const* h = (BITMAPCOREHEADER
const*)(start +
sizeof(BITMAPFILEHEADER));
202 size_y = h->bcHeight;
203 num_of_colors = 1 << h->bcBitCount;
204 color_table_offset +=
sizeof(BITMAPCOREHEADER);
210 if(color_table !=
nullptr) {
211 for(
uint32_t color_entry_index = 0; color_entry_index < num_of_colors; color_entry_index++) {
214 (color_table_offset + color_entry_index *
sizeof(
bmp_pixel_data));
215 color_table->push_back(*new_color);
219 if(compression_type == 1) {
220 decompressed_data.reset(
new uint8_t[std::abs(size_x) * std::abs(size_y)]);
221 memset(decompressed_data.get(), 0xFF, std::abs(size_x) * std::abs(size_y));
222 auto out_ptr = decompressed_data.get();
226 for(
auto ptr = data; ptr < start + content.file_size; ) {
229 auto offset = out_ptr - decompressed_data.get();
230 auto line = (offset - 1) / std::abs(size_x);
231 out_ptr = decompressed_data.get() + (line + 1) * std::abs(size_x);
233 }
else if(ptr[1] == 1) {
235 }
else if(ptr[1] == 2) {
238 auto offset = out_ptr - decompressed_data.get();
239 auto line = offset / std::abs(size_x);
240 auto x = out_ptr - (decompressed_data.get() + line * std::abs(size_x));
241 auto new_line = line + up;
242 out_ptr = decompressed_data.get() + new_line * std::abs(size_x) + x + right;
245 auto num_pixels = int32_t(ptr[1]);
246 auto amount_to_copy = std::min(ptrdiff_t(num_pixels),
248 decompressed_data.get() + std::abs(size_x) * std::abs(size_y) - out_ptr,
249 start + content.file_size - (ptr + 2)
251 memcpy(out_ptr, ptr + 2, amount_to_copy);
252 ptr += 2 + int32_t(ptr[1]) + ((ptr[1] & 1) != 0);
253 out_ptr += num_pixels;
256 auto num_pixels = ptr[0];
257 auto color_index = ptr[1];
259 while(num_pixels > 0 && out_ptr < decompressed_data.get() + std::abs(size_x) * std::abs(size_y)) {
260 *out_ptr = color_index;
267 data = decompressed_data.get();
270 assert(size_x == int32_t(map_size.x));
274 uint32_t top_free_space = (free_space * 3) / 5;
277 for(
uint32_t y = top_free_space + size_y - 1; y >=
uint32_t(top_free_space); --y) {
279 output_data[y * size_x + x] = *data;
287 ankerl::unordered_dense::map<uint32_t, uint8_t> m;
365 auto terrain_file = open_file(map_dir,
NATIVE(
"alice_terrain.png"));
383 if(
auto it = terrain_resolution.find(color); it != terrain_resolution.end()) {
386 bool found_neightbor =
false;
392 if(
auto itb = terrain_resolution.find(colorb); itb != terrain_resolution.end()) {
394 found_neightbor =
true;
397 if(!found_neightbor && y > 0) {
401 if(
auto itb = terrain_resolution.find(colorb); itb != terrain_resolution.end()) {
403 found_neightbor =
true;
406 if(!found_neightbor && x <
size_x - 1) {
410 if(
auto itb = terrain_resolution.find(colorb); itb != terrain_resolution.end()) {
412 found_neightbor =
true;
415 if(!found_neightbor && y <
size_y - 1) {
419 if(
auto itb = terrain_resolution.find(colorb); itb != terrain_resolution.end()) {
421 found_neightbor =
true;
425 if(!found_neightbor) {
427 int32_t min_distance = std::numeric_limits<int32_t>::max();
428 for(
auto& p : terrain_resolution) {
435 auto dist = (r - ptr[0]) * (r - ptr[0]) + (b - ptr[1]) * (b - ptr[1]) + (g - ptr[2]) * (g - ptr[2]);
436 if(dist < min_distance) {
438 resolved_index = p.second;
473 std::vector<std::array<int, 64>> terrain_histogram(context.
state.
world.province_size() + 1, std::array<int, 64>{});
478 terrain_histogram[prov_id][terrain_id] += 1;
481 for(
int i = context.
state.
world.province_size(); i-- > 1;) {
485 for(
int j = max_index; j-- > 0;) {
487 if(terrain_histogram[i][j] > max) {
489 max = terrain_histogram[i][j];
498 std::vector<glm::ivec2> accumulated_tile_positions(context.
state.
world.province_size() + 1, glm::vec2(0));
499 std::vector<int> tiles_number(context.
state.
world.province_size() + 1, 0);
504 accumulated_tile_positions[prov_id] += glm::vec2(x, y);
505 tiles_number[prov_id]++;
508 for(
int i = context.
state.
world.province_size() + 1; i-- > 1;) {
515 if(tiles_number[i] == 0) {
516 tile_pos = glm::vec2(0, 0);
518 tile_pos = accumulated_tile_positions[i] / tiles_number[i];
528 auto top_free_space = (free_space * 3) / 5;
532 for(; i < top_free_space *
size_x; ++i) {
535 auto first_actual_map_pixel = top_free_space *
size_x;
536 for(; i < first_actual_map_pixel + image.size_x * image.size_y; ++i) {
537 uint8_t* ptr = image.data + (i - first_actual_map_pixel) * 4;
546 for(; i < imsz; ++i) {
551 for(
uint32_t i = 0; i < imsz; ++i) {
595 std::vector<uint8_t> river_data;
598 std::vector<bmp_pixel_data> color_table;
599 river_data =
load_bmp(context,
NATIVE(
"rivers.bmp"), size, 255, &color_table);
605 auto r = color_table[color_index].red;
606 auto g = color_table[color_index].green;
607 auto b = color_table[color_index].blue;
608 if(r == 255 && g == 0 && b == 128) {
609 river_data[ty *
size_x + x] = 255;
610 }
else if(r == 255 && g == 255 && b == 255) {
611 river_data[ty *
size_x + x] = 255;
612 }
else if(color_index == 0 )
613 river_data[ty *
size_x + x] = 0;
614 else if(color_index == 1 )
615 river_data[ty *
size_x + x] = 1;
617 river_data[ty *
size_x + x] = std::min<uint8_t>((
uint8_t)250, std::max<uint8_t>((
uint8_t)2, r / 3 + g / 3 + b / 3));
639 if(ptr[0] + ptr[2] < 128 * 2 && ptr[1] > 128 )
640 river_data[ty *
size_x + x] = 0;
641 else if(ptr[1] + ptr[2] < 128 * 2 && ptr[0] > 128 )
642 river_data[ty *
size_x + x] = 1;
643 else if(ptr[0] + ptr[1] + ptr[2] < 128 * 3 )
644 river_data[ty *
size_x + x] = std::min<uint8_t>((
uint8_t)250, std::max<uint8_t>((
uint8_t)2, ptr[0] / 3 + ptr[1] / 3 + ptr[2] / 3));
646 river_data[ty *
size_x + x] = 255;
658 std::vector<bool> borders_visited;
663 std::vector<bool> borders_visited;
void load_terrain_data(parsers::scenario_building_context &context)
std::vector< uint8_t > median_terrain_type
std::vector< uint16_t > province_id_map
void make_coastal_borders(sys::state &state, std::vector< bool > &visited)
std::vector< uint8_t > terrain_id_map
void load_border_data(parsers::scenario_building_context &context)
void load_provinces_mid_point(parsers::scenario_building_context &context)
void load_median_terrain_type(parsers::scenario_building_context &context)
void make_borders(sys::state &state, std::vector< bool > &visited)
void create_curved_river_vertices(parsers::scenario_building_context &context, std::vector< uint8_t > const &river_data, std::vector< uint8_t > const &terrain_data)
void load_map_data(parsers::scenario_building_context &context)
std::vector< uint32_t > province_area
void load_province_data(parsers::scenario_building_context &context, ogl::image &image)
void load_map_data(parsers::scenario_building_context &context)
#define assert(condition)
ankerl::unordered_dense::map< uint32_t, uint8_t > internal_make_index_map()
std::vector< uint8_t > load_bmp(parsers::scenario_building_context &context, native_string_view name, glm::ivec2 map_size, uint8_t fill, std::vector< bmp_pixel_data > *color_table)
void load_river_crossings(parsers::scenario_building_context &context, std::vector< uint8_t > const &river_data, glm::ivec2 map_size)
image load_stb_image(simple_fs::file &file)
constexpr dcon::province_id from_map_id(uint16_t id)
constexpr uint16_t to_map_id(dcon::province_id id)
directory open_directory(directory const &dir, native_string_view directory_name)
directory get_root(file_system const &fs)
std::optional< file > open_file(directory const &dir, native_string_view file_name)
file_contents view_contents(file const &f)
uint32_t pack_color(float r, float g, float b)
int32_t int_red_from_int(uint32_t v)
int32_t int_blue_from_int(uint32_t v)
int32_t int_green_from_int(uint32_t v)
std::string_view native_string_view
ankerl::unordered_dense::map< uint32_t, dcon::province_id > map_color_to_province_id
dcon::province_id first_sea_province
dcon::data_container world
simple_fs::file_system common_fs
province::global_provincial_state province_definitions