aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/map/ProvinceDefinition.hpp
blob: a4076fe87cfa13d791bb1c1138b464392731b774 (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
131
132
133
134
#pragma once

#include <optional>

#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
#include "openvic-simulation/types/Vector.hpp"

namespace OpenVic {

   struct Map;
   struct Region;
   struct TerrainType;
   struct ProvinceSetModifier;
   using Climate = ProvinceSetModifier;
   using Continent = ProvinceSetModifier;
   struct BuildingType;
   struct BuildingTypeManager;

   /* REQUIREMENTS:
    * MAP-5, MAP-7, MAP-8, MAP-43, MAP-47
    * POP-22
    */
   struct ProvinceDefinition : HasIdentifierAndColour {
      friend struct Map;

      using index_t = uint16_t;
      using distance_t = fixed_point_t; // should this go inside adjacency_t?

      struct adjacency_t {
         using data_t = uint8_t;
         static constexpr data_t NO_CANAL = 0;

         enum struct type_t : uint8_t {
            LAND,       /* Between two land provinces */
            WATER,      /* Between two water provinces */
            COASTAL,    /* Between a land province and a water province */
            IMPASSABLE, /* Between two land provinces (non-traversable) */
            STRAIT,     /* Between two land provinces with a water through province */
            CANAL       /* Between two water provinces with a land through province */
         };

         /* Type display name used for logging */
         static std::string_view get_type_name(type_t type);

      private:
         ProvinceDefinition const* PROPERTY(to);
         ProvinceDefinition const* PROPERTY(through);
         distance_t PROPERTY(distance);
         type_t PROPERTY(type);
         data_t PROPERTY(data); // represents canal index, 0 for non-canal adjacencies

      public:
         adjacency_t(
            ProvinceDefinition const* new_to, distance_t new_distance, type_t new_type,
            ProvinceDefinition const* new_through, data_t new_data
         );
         adjacency_t(adjacency_t const&) = delete;
         adjacency_t(adjacency_t&&) = default;
         adjacency_t& operator=(adjacency_t const&) = delete;
         adjacency_t& operator=(adjacency_t&&) = default;
      };

      struct province_positions_t {
         /* Province name placement */
         std::optional<fvec2_t> text_position;
         std::optional<fixed_point_t> text_rotation;
         std::optional<fixed_point_t> text_scale;

         /* Model positions */
         std::optional<fvec2_t> unit;
         std::optional<fvec2_t> city;
         std::optional<fvec2_t> factory;
         std::optional<fvec2_t> building_construction;
         std::optional<fvec2_t> military_construction;
         ordered_map<BuildingType const*, fvec2_t> building_position;
         fixed_point_map_t<BuildingType const*> building_rotation;
      };

      static constexpr index_t NULL_INDEX = 0, MAX_INDEX = std::numeric_limits<index_t>::max();

   private:
      /* Immutable attributes (unchanged after initial game load) */
      const index_t PROPERTY(index);
      Region const* PROPERTY(region);
      Climate const* PROPERTY(climate);
      Continent const* PROPERTY(continent);
      bool PROPERTY(on_map);
      bool PROPERTY_CUSTOM_PREFIX(water, is);
      bool PROPERTY_CUSTOM_PREFIX(coastal, is);
      bool PROPERTY_CUSTOM_PREFIX(port, has);
      ProvinceDefinition const* PROPERTY(port_adjacent_province);
      /* Terrain type calculated from terrain image */
      TerrainType const* PROPERTY(default_terrain_type);

      std::vector<adjacency_t> PROPERTY(adjacencies);
      /* Calculated mean pixel position. */
      fvec2_t PROPERTY(centre);
      province_positions_t positions;

      ProvinceDefinition(std::string_view new_identifier, colour_t new_colour, index_t new_index);

   public:
      ProvinceDefinition(ProvinceDefinition&&) = default;

      bool operator==(ProvinceDefinition const& other) const;
      std::string to_string() const;

      inline constexpr bool has_region() const {
         return region != nullptr;
      }

      /* The positions' y coordinates need to be inverted. */
      bool load_positions(Map const& map, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root);

      fvec2_t get_text_position() const;
      fixed_point_t get_text_rotation() const;
      fixed_point_t get_text_scale() const;

      /* This returns a pointer to the position of the specified building type, or nullptr if none exists. */
      fvec2_t const* get_building_position(BuildingType const* building_type) const;
      fixed_point_t get_building_rotation(BuildingType const* building_type) const;

      adjacency_t const* get_adjacency_to(ProvinceDefinition const* province) const;
      bool is_adjacent_to(ProvinceDefinition const* province) const;
      std::vector<adjacency_t const*> get_adjacencies_going_through(ProvinceDefinition const* province) const;
      bool has_adjacency_going_through(ProvinceDefinition const* province) const;

      fvec2_t get_unit_position() const;
   };
}