Freeciv21
Develop your civilization from humble roots to a global empire
tradecalculation.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2023 Freeciv21 and Freeciv contributors. This file is
3  part of Freeciv21. Freeciv21 is free software: you can redistribute it
4  and/or modify it under the terms of the GNU General Public License as
5  published by the Free Software Foundation, either version 3 of the
6  License, or (at your option) any later version. You should have received
7  a copy of the GNU General Public License along with Freeciv21. If not,
8  see https://www.gnu.org/licenses/.
9  */
10 #include "tradecalculation.h"
11 
12 #include <random>
13 // common
14 #include "city.h"
15 #include "featured_text.h"
16 #include "traderoutes.h"
17 // client
18 #include "chatline_common.h" // Help me, I want to common
19 #include "client_main.h"
20 // qt
21 #include "fc_client.h"
22 #include "messagewin.h"
23 #include "page_game.h"
24 #include "views/view_map.h"
25 
30 {
31  city = pcity;
32  tile = nullptr;
33  trade_num = 0;
34  poss_trade_num = 0;
35  done = false;
36  over_max = false;
37 }
38 
43 
48 {
49  int i, s;
50  struct city *pcity;
52  s = city_list_size(client.conn.playing->cities);
53  if (s == 0) {
54  return;
55  }
56  for (i = 0; i < s; i++) {
57  pcity = city_list_get(client.conn.playing->cities, i);
58  add_city(pcity);
59  }
60 }
61 
66 {
67  for (auto *pcity : qAsConst(virtual_cities)) {
68  destroy_city_virtual(pcity);
69  }
70  virtual_cities.clear();
71  for (auto *tc : qAsConst(cities)) {
72  delete tc;
73  }
74  cities.clear();
75  lines.clear();
76  queen()->mapview_wdg->repaint();
77 }
78 
82 void trade_generator::add_city(struct city *pcity)
83 {
84  trade_city *tc = new trade_city(pcity);
85  cities.append(tc);
86  queen()->chat->append(
87  QString(_("Adding city %1 to trade planning")).arg(tc->city->name));
88 }
89 
93 void trade_generator::add_tile(struct tile *ptile)
94 {
95  struct city *pcity;
96  pcity = tile_city(ptile);
97 
98  for (auto *tc : qAsConst(cities)) {
99  if (pcity != nullptr) {
100  if (tc->city == pcity) {
101  remove_city(pcity);
102  return;
103  }
104  }
105  if (tc->city->tile == ptile) {
106  remove_virtual_city(ptile);
107  return;
108  }
109  }
110 
111  if (pcity != nullptr) {
112  add_city(pcity);
113  return;
114  }
115 
116  pcity = create_city_virtual(client_player(), ptile, "Virtual");
117  add_city(pcity);
118  virtual_cities.append(pcity);
119 }
120 
125 {
126  for (auto *tc : qAsConst(cities)) {
127  if (tc->city->tile == pcity->tile) {
128  cities.removeAll(tc);
129  queen()->chat->append(
130  QString(_("Removing city %1 from trade planning"))
131  .arg(tc->city->name));
132  return;
133  }
134  }
135 }
136 
141 {
142  for (auto *c : qAsConst(virtual_cities)) {
143  if (c->tile == ptile) {
144  virtual_cities.removeAll(c);
145  queen()->chat->append(
146  QString(_("Removing city %1 from trade planning")).arg(c->name));
147  }
148  }
149 
150  for (auto *tc : qAsConst(cities)) {
151  if (tc->city->tile == ptile) {
152  cities.removeAll(tc);
153  return;
154  }
155  }
156 }
157 
162 {
163  int i;
164  bool tdone;
165  std::random_device rd;
166  std::mt19937 g(rd());
167 
168  for (i = 0; i < 100; i++) {
169  tdone = true;
170  std::shuffle(cities.begin(), cities.end(), g);
171  lines.clear();
172  for (auto *tc : qAsConst(cities)) {
173  tc->pos_cities.clear();
174  tc->new_tr_cities.clear();
175  tc->curr_tr_cities.clear();
176  }
177  for (auto *tc : qAsConst(cities)) {
178  tc->trade_num = city_num_trade_routes(tc->city);
179  tc->poss_trade_num = 0;
180  tc->pos_cities.clear();
181  tc->new_tr_cities.clear();
182  tc->curr_tr_cities.clear();
183  tc->done = false;
184  for (auto *ttc : qAsConst(cities)) {
185  if (!have_cities_trade_route(tc->city, ttc->city)
186  && can_establish_trade_route(tc->city, ttc->city)) {
187  tc->poss_trade_num++;
188  tc->pos_cities.append(ttc->city);
189  }
190  tc->over_max =
191  tc->trade_num + tc->poss_trade_num - max_trade_routes(tc->city);
192  }
193  }
194 
196  discard();
198 
199  for (auto *tc : qAsConst(cities)) {
200  if (!tc->done) {
201  tdone = false;
202  }
203  }
204  if (tdone) {
205  break;
206  }
207  }
208  for (auto *tc : qAsConst(cities)) {
209  if (!tc->done) {
210  char text[1024];
211  fc_snprintf(text, sizeof(text),
212  PL_("City %s - 1 free trade route.",
213  "City %s - %d free trade routes.",
214  max_trade_routes(tc->city) - tc->trade_num),
215  city_link(tc->city),
216  max_trade_routes(tc->city) - tc->trade_num);
218  }
219  }
220 
221  queen()->mapview_wdg->repaint();
222 }
223 
228 int trade_generator::find_over_max(struct city *pcity = nullptr)
229 {
230  int max = 0;
231 
232  for (auto *tc : qAsConst(cities)) {
233  if (pcity != tc->city) {
234  max = qMax(max, tc->over_max);
235  }
236  }
237  return max;
238 }
239 
244 {
245  trade_city *rc = nullptr;
246  int max = 0;
247 
248  for (auto *tc : qAsConst(cities)) {
249  if (max < tc->over_max) {
250  max = tc->over_max;
251  rc = tc;
252  }
253  }
254  return rc;
255 }
256 
261 {
262  trade_city *tc;
263  int j = 5;
264 
265  for (int i = j; i > -j; i--) {
266  while ((tc = find_most_free())) {
267  if (!discard_any(tc, i)) {
268  break;
269  }
270  }
271  }
272 }
273 
278 {
279  tc->pos_cities.removeOne(ttc->city);
280  ttc->pos_cities.removeOne(tc->city);
281  tc->poss_trade_num--;
282  ttc->poss_trade_num--;
283  tc->over_max--;
284  ttc->over_max--;
285  check_if_done(tc, ttc);
286 }
287 
291 bool trade_generator::discard_any(trade_city *tc, int freeroutes)
292 {
293  trade_city *ttc;
294 
295  for (int i = cities.size() - 1; i >= 0; i--) {
296  ttc = cities.at(i);
297  if (tc->pos_cities.contains(ttc->city)
298  && ttc->pos_cities.contains(tc->city)
299  && ttc->over_max > freeroutes) {
300  discard_trade(tc, ttc);
301  return true;
302  }
303  }
304  return false;
305 }
306 
311 {
312  for (auto *tc : qAsConst(cities)) {
313  if (tc->done || tc->over_max > 0) {
314  continue;
315  }
316  for (auto *ttc : qAsConst(cities)) {
317  if (ttc->done || ttc->over_max > 0 || tc == ttc || tc->done
318  || tc->over_max > 0) {
319  continue;
320  }
321  if (tc->pos_cities.contains(ttc->city)
322  && ttc->pos_cities.contains(tc->city)) {
323  struct qtiles gilles;
324  tc->pos_cities.removeOne(ttc->city);
325  ttc->pos_cities.removeOne(tc->city);
326  tc->poss_trade_num--;
327  ttc->poss_trade_num--;
328  tc->new_tr_cities.append(ttc->city);
329  ttc->new_tr_cities.append(ttc->city);
330  tc->trade_num++;
331  ttc->trade_num++;
332  tc->over_max--;
333  ttc->over_max--;
334  check_if_done(tc, ttc);
335  gilles.t1 = tc->city->tile;
336  gilles.t2 = ttc->city->tile;
337  gilles.autocaravan = nullptr;
338  lines.append(gilles);
339  }
340  }
341  }
342 }
343 
348 {
349  if (tc1->trade_num == max_trade_routes(tc1->city)) {
350  tc1->done = true;
351  }
352  if (tc2->trade_num == max_trade_routes(tc2->city)) {
353  tc2->done = true;
354  }
355 }
void output_window_append(const struct ft_color color, const char *featured_text)
Add a line of text to the output ("chatline") window, like puts() would do it in the console.
void destroy_city_virtual(struct city *pcity)
Removes the virtual skeleton of a city.
Definition: city.cpp:3421
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Create virtual skeleton for a city.
Definition: city.cpp:3346
void append(const QString &str)
Adds news string to chat_widget.
Definition: chatline.cpp:596
map_view * mapview_wdg
Definition: page_game.h:81
chat_widget * chat
Definition: page_game.h:80
QList< struct city * > pos_cities
trade_city(struct city *pcity)
Constructor for trade city used to trade calculation.
struct city * city
void add_city(struct city *pcity)
Adds single city to trade generator.
void find_certain_routes()
Adds routes for cities which can only have maximum possible trade routes.
trade_city * find_most_free()
Finds city with highest trade routes possible.
void discard_trade(trade_city *tc1, trade_city *tc2)
Drops trade routes between given cities.
void add_tile(struct tile *ptile)
Adds/removes tile to trade generator.
trade_generator()
Constructor for trade calculator.
void remove_virtual_city(struct tile *ptile)
Removes virtual city from trade generator.
QList< trade_city * > cities
void add_all_cities()
Adds all cities to trade generator.
void clear_trade_planing()
Clears genrated routes, virtual cities, cities.
void discard()
Drops all possible trade routes.
void remove_city(struct city *pcity)
Removes single city from trade generator.
QList< qtiles > lines
bool discard_any(trade_city *tc, int freeroutes)
Drops all trade routes for given city.
void check_if_done(trade_city *tc1, trade_city *tc2)
Marks cities with full trade routes to finish searching.
QList< struct city * > virtual_cities
int find_over_max(struct city *pcity)
Finds highest number of trade routes over maximum for all cities, skips given city.
void calculate()
Finds trade routes to establish.
struct player * client_player()
Either controlling or observing.
struct civclient client
#define PL_(String1, String2, n)
Definition: fcintl.h:54
#define _(String)
Definition: fcintl.h:50
const struct ft_color ftc_client
const char * city_link(const struct city *pcity)
Get a text link to a city.
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
Definition: city.h:291
char name[MAX_LEN_CITYNAME]
Definition: city.h:292
struct tile * tile
Definition: city.h:293
struct connection conn
Definition: client_main.h:89
struct player * playing
Definition: connection.h:142
struct city_list * cities
Definition: player.h:263
struct tile * t1
struct tile * t2
struct unit * autocaravan
Definition: tile.h:42
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
int max_trade_routes(const struct city *pcity)
Return current maximum number of trade routes city can have.
Definition: traderoutes.cpp:41
int city_num_trade_routes(const struct city *pcity)
Return number of trade route city has.
bool can_establish_trade_route(const struct city *pc1, const struct city *pc2)
Returns TRUE iff the two cities can establish a trade route.
bool have_cities_trade_route(const struct city *pc1, const struct city *pc2)
Check if cities have an established trade route.