Symphony Of Empires
trade.cpp
Go to the documentation of this file.
1 // Symphony of Empires
2 // Copyright (C) 2021, Symphony of Empires contributors
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <https://www.gnu.org/licenses/>.
16 //
17 // ----------------------------------------------------------------------------
18 // Name:
19 // server/trade.hpp
20 //
21 // Abstract:
22 // Does some important stuff.
23 // ----------------------------------------------------------------------------
24 
25 #include "server/trade.hpp"
26 #include "world.hpp"
27 #include "eng3d/pathfind.hpp"
28 #include <queue>
29 #include <tbb/blocked_range.h>
30 #include <tbb/parallel_for.h>
31 #include <glm/vec3.hpp>
32 #include <glm/gtc/constants.hpp>
33 #include <glm/trigonometric.hpp>
34 #include <glm/geometric.hpp>
35 
36 using namespace Economy;
37 
38 void Trade::recalculate(const World& world) {
39  if(trade_costs.empty())
40  this->initialize(world);
41 
43  if (cost_eval.empty()) {
44  tbb::parallel_for(static_cast<size_t>(0), world.provinces.size(), [this, &world](const auto province_id) {
45  glm::vec2 world_size{ world.width, world.height};
46  const auto& province = world.provinces[province_id];
47  for(size_t i = 0; i < world.provinces.size(); i++) {
48  const auto& other_province = world.provinces[i];
49  this->trade_costs[province_id][i] =
50  get_trade_cost(province, other_province, world_size);
51  }
52  });
53  }
54 
55  if (cost_eval.empty()) {
56  for(size_t i = 0; i < world.provinces.size(); i++) {
57  if(!world.provinces[i].is_coastal)
58  cost_eval.push_back(i);
59  }
60  }
61 
63  // for(auto& trade_cost : this->trade_costs)
64  // std::fill(trade_cost.begin(), trade_cost.end(), std::numeric_limits<float>::max());
65  // glm::vec2 world_size{ world.width, world.height };
66  // tbb::parallel_for(tbb::blocked_range(cost_eval.begin(), cost_eval.end()), [this, &world](const auto& province_range) {
67  // for(auto& province_id : province_range) {
68  // Eng3D::Pathfind::from_source<ProvinceId>(ProvinceId(province_id), this->neighbours, this->trade_costs[province_id]);
69  // }
70  // }, tbb::auto_partitioner());
71 }
72 
73 float Trade::get_trade_cost(const Province& province1, const Province& province2, glm::vec2 world_size) const {
74  const auto radius = 100.f;
75  const auto distance = province1.euclidean_distance(province2, world_size, radius);
76 
77  // Dissuade trade with foreigners
78  auto foreign_penalty = 1.f;
79  if(province1.controller_id != province2.controller_id) {
80  foreign_penalty = 5.f;
81  // Must be valid controller ids
82  const auto& world = World::get_instance();
83  // Must be in customs union if it's a foreigner
84  const auto& relation = world.get_relation(province1.controller_id, province2.controller_id);
85  if(relation.is_customs_union())
86  foreign_penalty = 1.f;
87  }
88 
89  // Cost to travel around the globe
90  const auto trade_cost = (g_world.terrain_types[province1.terrain_type_id].penalty + g_world.terrain_types[province2.terrain_type_id].penalty) * foreign_penalty;
91  return distance * trade_cost;
92 }
93 
94 inline void Trade::initialize(const World& world) {
95  trade_costs.resize(world.provinces.size(), std::vector<float>(world.provinces.size(), std::numeric_limits<float>::max()));
96 
97  glm::vec2 world_size{ world.width, world.height };
98  neighbours.reserve(world.provinces.size());
99  for(const auto& province : world.provinces) {
100  std::vector<Trade::Vertex> province_neighbours;
101  province_neighbours.reserve(province.neighbour_ids.size());
102  for(const auto neighbour_id : province.neighbour_ids) {
103  const auto& neighbour = world.provinces[neighbour_id];
104  const auto trade_cost = get_trade_cost(province, neighbour, world_size);
105  province_neighbours.emplace_back(trade_cost, neighbour_id);
106  }
107  neighbours.push_back(province_neighbours);
108  }
109 }
A single province, which is used to simulate economy in a "bulk-tiles" way instead of doing economica...
Definition: province.hpp:48
NationId controller_id
Definition: province.hpp:104
TerrainTypeId terrain_type_id
Definition: province.hpp:105
float euclidean_distance(const Province &other_province, glm::vec2 world_size, float radius) const
Definition: province.cpp:59
Definition: world.hpp:114
size_t width
Definition: world.hpp:220
static World & get_instance()
Definition: world.hpp:121
size_t height
Definition: world.hpp:220
void parallel_for(T range, F &&func)
float get_trade_cost(const Province &province1, const Province &province2, glm::vec2 world_size) const
Definition: trade.cpp:73
std::vector< ProvinceId > cost_eval
Cost-evaluatable provinces, we discard sea and ocean provinces from this formula to save space and ti...
Definition: trade.hpp:52
std::vector< std::vector< float > > trade_costs
Definition: trade.hpp:53
void recalculate(const World &world)
Definition: trade.cpp:38
World g_world
Definition: world.cpp:59