aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/map/Map.hpp
blob: 189713c1247fe749315d34c06dcf6069156ba74c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#pragma once

#include <filesystem>
#include <functional>

#include <openvic-dataloader/csv/LineObject.hpp>

#include "openvic-simulation/map/Region.hpp"
#include "openvic-simulation/map/TerrainType.hpp"

namespace OpenVic {
   namespace fs = std::filesystem;

   struct Mapmode : HasIdentifier {
      friend struct Map;

      /* Bottom 32 bits are the base colour, top 32 are the stripe colour, both in ARGB format with the alpha channels
       * controlling interpolation with the terrain colour (0 = all terrain, 255 = all corresponding RGB) */
      using base_stripe_t = uint64_t;
      using colour_func_t = std::function<base_stripe_t(Map const&, Province const&)>;
      using index_t = size_t;

   private:
      const index_t index;
      const colour_func_t colour_func;

      Mapmode(std::string_view new_identifier, index_t new_index, colour_func_t new_colour_func);

   public:
      static const Mapmode ERROR_MAPMODE;

      Mapmode(Mapmode&&) = default;

      index_t get_index() const;
      base_stripe_t get_base_stripe_colours(Map const& map, Province const& province) const;
   };

   struct GoodManager;
   struct ProvinceHistoryManager;

   /* REQUIREMENTS:
    * MAP-4
    */
   struct Map {

#pragma pack(push, 1)
      /* Used to represent tightly packed 3-byte integer pixel information. */
      struct shape_pixel_t {
         Province::index_t index;
         TerrainTypeMapping::index_t terrain;
      };
#pragma pack(pop)
   private:
      using colour_index_map_t = std::map<colour_t, Province::index_t>;

      IdentifierRegistry<Province> provinces;
      IdentifierRegistry<Region> regions;
      IdentifierRegistry<Mapmode> mapmodes;
      ProvinceSet water_provinces;
      TerrainTypeManager terrain_type_manager;

      size_t width = 0, height = 0;
      std::vector<shape_pixel_t> province_shape_image;
      colour_index_map_t colour_index_map;

      Province::index_t max_provinces = Province::MAX_INDEX;
      Province::index_t selected_province = Province::NULL_INDEX;
      Pop::pop_size_t highest_province_population, total_map_population;

      Province::index_t get_index_from_colour(colour_t colour) const;
      bool _generate_province_adjacencies();

   public:
      Map();

      bool add_province(std::string_view identifier, colour_t colour);
      IDENTIFIER_REGISTRY_ACCESSORS(province)
      IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(province)

      bool set_water_province(std::string_view identifier);
      bool set_water_province_list(std::vector<std::string_view> const& list);
      void lock_water_provinces();

      Province* get_province_by_index(Province::index_t index);
      Province const* get_province_by_index(Province::index_t index) const;
      Province::index_t get_province_index_at(size_t x, size_t y) const;
      bool set_max_provinces(Province::index_t new_max_provinces);
      Province::index_t get_max_provinces() const;
      void set_selected_province(Province::index_t index);
      Province::index_t get_selected_province_index() const;
      Province const* get_selected_province() const;

      size_t get_width() const;
      size_t get_height() const;
      std::vector<shape_pixel_t> const& get_province_shape_image() const;
      REF_GETTERS(terrain_type_manager)

      bool add_region(std::string_view identifier, std::vector<std::string_view> const& province_identifiers);
      IDENTIFIER_REGISTRY_ACCESSORS(region)
      IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(region)

      bool add_mapmode(std::string_view identifier, Mapmode::colour_func_t colour_func);
      IDENTIFIER_REGISTRY_ACCESSORS(mapmode)
      Mapmode const* get_mapmode_by_index(size_t index) const;

      /* The mapmode colour image contains of a list of base colours and stripe colours. Each colour is four bytes
       * in RGBA format, with the alpha value being used to interpolate with the terrain colour, so A = 0 is fully terrain
       * and A = 255 is fully the RGB colour packaged with A. The base and stripe colours for each province are packed
       * together adjacently, so each province's entry is 8 bytes long. The list contains Province::MAX_INDEX + 1 entries,
       * that is the maximum allowed number of provinces plus one for the index-zero "null province". */
      bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const;

      bool reset(BuildingManager const& building_manager);
      bool apply_history_to_provinces(ProvinceHistoryManager const& history_manager, Date date);

      void update_highest_province_population();
      Pop::pop_size_t get_highest_province_population() const;
      void update_total_map_population();
      Pop::pop_size_t get_total_map_population() const;

      void update_state(Date today);
      void tick(Date today);

      bool load_province_definitions(std::vector<ovdl::csv::LineObject> const& lines);
      bool load_province_positions(BuildingManager const& building_manager, ast::NodeCPtr root);
      bool load_region_file(ast::NodeCPtr root);
      bool load_map_images(fs::path const& province_path, fs::path const& terrain_path, bool detailed_errors);
      bool generate_and_load_province_adjacencies(std::vector<ovdl::csv::LineObject> const& additional_adjacencies);
   };
}