Freeciv21
Develop your civilization from humble roots to a global empire
citydlg_common.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2023 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <cstdarg>
15 
16 // utility
17 #include "fcintl.h"
18 #include "log.h"
19 #include "support.h"
20 
21 // common
22 #include "city.h"
23 #include "culture.h"
24 #include "game.h"
25 #include "specialist.h"
26 
27 /* client/include */
28 #include "citydlg_g.h"
29 
30 // client
31 #include "citydlg_common.h"
32 
33 // for can_client_issue_orders()
34 #include "client_main.h"
35 #include "climap.h"
36 #include "views/view_map_common.h"
37 
38 // for concise_city_production
39 #include "options.h"
40 
41 // for tileset_is_isometric(tileset)
42 #include "tileset/tilespec.h"
43 
45 
50 
55 
60 {
61  int min_x = 0, max_x = 0, min_y = 0, max_y = 0;
62  int max_rad = rs_max_city_radius_sq();
63 
64  // use maximum possible squared city radius.
65  city_map_iterate_without_index(max_rad, city_x, city_y)
66  {
67  float canvas_x, canvas_y;
68 
69  map_to_gui_vector(tileset, &canvas_x, &canvas_y, CITY_ABS2REL(city_x),
70  CITY_ABS2REL(city_y));
71 
72  min_x = MIN(canvas_x, min_x);
73  max_x = MAX(canvas_x, max_x);
74  min_y = MIN(canvas_y, min_y);
75  max_y = MAX(canvas_y, max_y);
76  }
78 
79  citydlg_map_width = max_x - min_x + tileset_tile_width(tileset);
81 }
82 
87 char *city_production_cost_str(const struct city *pcity)
88 {
89  static char cost_str[50];
90  int cost = city_production_build_shield_cost(pcity);
91  int build_slots = city_build_slots(pcity);
92  int num_units;
93 
94  if (build_slots > 1
95  && city_production_build_units(pcity, true, &num_units)) {
96  // the city could build more than one unit of the selected type
97  if (num_units == 0) {
98  // no unit will be finished this turn but one is build
99  num_units++;
100  }
101 
102  if (build_slots > num_units) {
103  // some build slots for units will be unused
104  fc_snprintf(cost_str, sizeof(cost_str), "{%d*%d}", num_units, cost);
105  } else {
106  // maximal number of units will be build
107  fc_snprintf(cost_str, sizeof(cost_str), "[%d*%d]", num_units, cost);
108  }
109  } else {
110  // nothing special
111  fc_snprintf(cost_str, sizeof(cost_str), "%3d", cost);
112  }
113 
114  return cost_str;
115 }
116 
123 void get_city_dialog_production(struct city *pcity, char *buffer,
124  size_t buffer_len)
125 {
126  char time_str[50], *cost_str;
127  int turns, stock;
128 
129  if (pcity == nullptr) {
130  /*
131  * Some GUIs use this to build a "filler string" so that they can
132  * properly size the widget to hold the string. This has some
133  * obvious problems; the big one is that we have two forms of time
134  * information: "XXX turns" and "never". Later this may need to
135  * be extended to return the longer of the two; in the meantime
136  * translators can fudge it by changing this "filler" string.
137  */
138  // TRANS: Use longer of "XXX turns" and "never"
139  fc_strlcpy(buffer, Q_("?filler:XXX/XXX XXX turns"), buffer_len);
140 
141  return;
142  }
143 
144  if (city_production_has_flag(pcity, IF_GOLD)) {
145  int gold = MAX(0, pcity->surplus[O_SHIELD]);
146  fc_snprintf(buffer, buffer_len,
147  PL_("%3d gold per turn", "%3d gold per turn", gold), gold);
148  return;
149  }
150 
151  turns = city_production_turns_to_build(pcity, true);
152  stock = pcity->shield_stock;
153  cost_str = city_production_cost_str(pcity);
154 
155  if (turns < FC_INFINITY) {
157  fc_snprintf(time_str, sizeof(time_str), "%3d", turns);
158  } else {
159  fc_snprintf(time_str, sizeof(time_str),
160  PL_("%3d turn", "%3d turns", turns), turns);
161  }
162  } else {
163  fc_snprintf(time_str, sizeof(time_str), "%s",
164  gui_options->concise_city_production ? "-" : _("never"));
165  }
166 
168  fc_snprintf(buffer, buffer_len, _("%3d/%s:%s"), stock, cost_str,
169  time_str);
170  } else {
171  fc_snprintf(buffer, buffer_len, _("%3d/%s %s"), stock, cost_str,
172  time_str);
173  }
174 }
175 
176 namespace {
180 QString html_pre(const QString &content)
181 {
182  return QStringLiteral("<pre>") + content + QStringLiteral("</pre>");
183 }
184 
190 struct msum {
191  // The net value that is accumulated.
192  double value;
193  /* Description; compared for duplicate-merging.
194  * Both of these are maintained/compared until the net 'value' is known;
195  * then posdesc is used if value>=0, negdesc if value<0 */
196  QString posdesc, negdesc;
197  // Whether posdesc is printed for total==0
198  bool suppress_if_zero;
199  // An auxiliary value that is also accumulated, but not tested
200  double aux;
201  // ...and the format string for the net aux value (appended to *desc)
202  QString auxfmt;
203 };
204 
205 struct city_sum {
206  QString format;
207  size_t n;
208  QVector<msum> sums;
209 };
210 
217 struct city_sum *city_sum_new(const char *format)
218 {
219  struct city_sum *sum = new city_sum();
220 
221  sum->format = format;
222  sum->n = 0;
223  sum->sums.clear();
224 
225  return sum;
226 }
227 
233 void city_sum_add_real(struct city_sum *sum, double value,
234  bool suppress_if_zero, const QString &auxfmt,
235  double aux, const QString &posdesc,
236  const QString &negdesc)
237 {
238  size_t i;
239 
240  // likely to lead to quadratic behaviour, but who cares:
241  for (i = 0; i < sum->n; i++) {
242  if (sum->sums[i].posdesc == posdesc && sum->sums[i].negdesc == negdesc
243  && sum->sums[i].auxfmt == auxfmt
244  && sum->sums[i].suppress_if_zero == suppress_if_zero) {
245  // Looks like we already have an entry like this. Accumulate values.
246  sum->sums[i].value += value;
247  sum->sums[i].aux += aux;
248 
249  return;
250  }
251  }
252 
253  // Didn't find description already, so add it to the end.
254  sum->sums.resize(sum->n + 1);
255  sum->sums[sum->n].value = value;
256  sum->sums[sum->n].posdesc = posdesc;
257  sum->sums[sum->n].negdesc = negdesc;
258  sum->sums[sum->n].suppress_if_zero = suppress_if_zero;
259  sum->sums[sum->n].aux = aux;
260  sum->sums[sum->n].auxfmt = auxfmt;
261  sum->n++;
262 }
263 
275 void fc__attribute((__format__(__printf__, 6, 8)))
276  fc__attribute((__format__(__printf__, 7, 8)))
277  fc__attribute((nonnull(1, 6, 7)))
278  city_sum_add_full(struct city_sum *sum, double value,
279  bool suppress_if_zero, const char *auxfmt,
280  double aux, const char *posfmt,
281  const char *negfmt, ...)
282 {
283  va_list args;
284 
285  // Format both descriptions
286  va_start(args, negfmt); // sic -- arguments follow negfmt
287  auto posdesc = QString::vasprintf(posfmt, args);
288  va_end(args);
289 
290  va_start(args, negfmt); // sic -- arguments follow negfmt
291  auto negdesc = QString::vasprintf(negfmt, args);
292  va_end(args);
293 
294  city_sum_add_real(sum, value, suppress_if_zero, auxfmt, aux, posdesc,
295  negdesc);
296 }
297 
305 void fc__attribute((__format__(__printf__, 3, 4)))
306  fc__attribute((nonnull(1, 3)))
307  city_sum_add(struct city_sum *sum, double value, const char *descfmt,
308  ...)
309 {
310  va_list args;
311 
312  // Format description (same used for positive or negative net value)
313  va_start(args, descfmt);
314  auto desc = QString::vasprintf(descfmt, args);
315  va_end(args);
316 
317  // Descriptions will be freed individually, so need to strdup
318  city_sum_add_real(sum, value, false, nullptr, 0, desc, desc);
319 }
320 
328 void fc__attribute((__format__(__printf__, 3, 4)))
329  fc__attribute((nonnull(1, 3)))
330  city_sum_add_if_nonzero(struct city_sum *sum, double value,
331  const char *descfmt, ...)
332 {
333  va_list args;
334 
335  // Format description (same used for positive or negative net value)
336  va_start(args, descfmt);
337  auto desc = QString::vasprintf(descfmt, args);
338  va_end(args);
339 
340  // Descriptions will be freed individually, so need to strdup
341  city_sum_add_real(sum, value, true, nullptr, 0, desc, desc);
342 }
343 
347 double city_sum_total(struct city_sum *sum)
348 {
349  size_t i;
350  double total = 0;
351 
352  for (i = 0; i < sum->n; i++) {
353  total += sum->sums[i].value;
354  }
355  return total;
356 }
357 
364 inline int city_sum_compare(double val1, double val2)
365 {
366  /* Fudgey epsilon -- probably the numbers we're dealing with have at
367  * most 1% or 0.1% real difference */
368  if (fabs(val1 - val2) < 0.0000001) {
369  return 0;
370  }
371  return (val1 > val2 ? +1 : -1);
372 }
373 
381 QString fc__attribute((__format__(__printf__, 3, 4)))
382  fc__attribute((nonnull(1, 3)))
383  city_sum_print(struct city_sum *sum, bool account_for_unknown,
384  const char *totalfmt, ...)
385 {
386  va_list args;
387  size_t i;
388 
389  /* This probably ought not to happen in well-designed rulesets, but it's
390  * possible for incomplete client knowledge to give an inaccurate
391  * breakdown. If it does happen, at least acknowledge to the user that
392  * we are confused, rather than displaying an incorrect sum. */
393  if (account_for_unknown) {
394  double total = city_sum_total(sum);
395  double actual_total;
396 
397  va_start(args, totalfmt);
398  actual_total = va_arg(args, double);
399  va_end(args);
400 
401  if (city_sum_compare(total, actual_total) != 0) {
402  city_sum_add(sum, actual_total - total,
403  /* TRANS: Client cannot explain some aspect of city
404  * output. Should never happen. */
405  Q_("?city_sum:(unknown)"));
406  }
407  }
408 
409  QString result;
410  for (i = 0; i < sum->n; i++) {
411  if (!sum->sums[i].suppress_if_zero
412  || city_sum_compare(sum->sums[i].value, 0) != 0) {
413  result += QString::asprintf(
414  qUtf8Printable(sum->format), sum->sums[i].value,
415  (sum->sums[i].value < 0) ? qUtf8Printable(sum->sums[i].negdesc)
416  : qUtf8Printable(sum->sums[i].posdesc));
417  if (!sum->sums[i].auxfmt.isEmpty()) {
418  result += QString::asprintf(qUtf8Printable(sum->sums[i].auxfmt),
419  sum->sums[i].aux);
420  }
421  result += QStringLiteral("\n");
422  }
423  }
424 
425  va_start(args, totalfmt);
426  result += QString::vasprintf(totalfmt, args);
427  va_end(args);
428 
429  delete sum;
430  return html_pre(result);
431 }
432 } // anonymous namespace
433 
437 QString get_city_dialog_output_text(const struct city *pcity,
438  Output_type_id otype)
439 {
440  int priority;
441  int tax[O_LAST];
442  struct output_type *output = &output_types[otype];
443  /* TRANS: format string for a row of the city output sum that adds up
444  * to "Total surplus" */
445  struct city_sum *sum = city_sum_new(Q_("?city_surplus:%+4.0f : %s"));
446 
447  city_sum_add(sum, pcity->citizen_base[otype],
448  Q_("?city_surplus:Citizens"));
449 
450  // Hack to get around the ugliness of add_tax_income.
451  memset(tax, 0, O_LAST * sizeof(*tax));
452  add_tax_income(city_owner(pcity), pcity->prod[O_TRADE], tax);
453  city_sum_add_if_nonzero(sum, tax[otype],
454  Q_("?city_surplus:Taxed from trade"));
455 
456  /* Special cases for "bonus" production. See set_city_production in
457  * city.c. */
458  if (otype == O_TRADE) {
459  trade_routes_iterate(pcity, proute)
460  {
461  /* NB: (proute->value == 0) is valid case. The trade route
462  * is established but doesn't give trade surplus. */
463  struct city *trade_city = game_city_by_number(proute->partner);
464  // TRANS: Trade partner unknown to client
465  const char *name =
466  trade_city ? city_name_get(trade_city) : _("(unknown)");
467  int value = proute->value
468  * (100 + get_city_bonus(pcity, EFT_TRADEROUTE_PCT)) / 100;
469 
470  switch (proute->dir) {
471  case RDIR_BIDIRECTIONAL:
472  city_sum_add(sum, value, Q_("?city_surplus:Trading %s with %s"),
473  goods_name_translation(proute->goods), name);
474  break;
475  case RDIR_FROM:
476  city_sum_add(sum, value, Q_("?city_surplus:Trading %s to %s"),
477  goods_name_translation(proute->goods), name);
478  break;
479  case RDIR_TO:
480  city_sum_add(sum, value, Q_("?city_surplus:Trading %s from %s"),
481  goods_name_translation(proute->goods), name);
482  break;
483  }
484  }
486  } else if (otype == O_GOLD) {
487  int tithes = get_city_tithes_bonus(pcity);
488 
489  city_sum_add_if_nonzero(sum, tithes,
490  Q_("?city_surplus:Building tithes"));
491  }
492 
493  for (priority = 0; priority < 2; priority++) {
494  enum effect_type eft[] = {EFT_OUTPUT_BONUS, EFT_OUTPUT_BONUS_2};
495 
496  {
497  int base = city_sum_total(sum), bonus = 100;
498  struct effect_list *plist = effect_list_new();
499 
500  (void) get_city_bonus_effects(plist, pcity, output, eft[priority]);
501 
502  effect_list_iterate(plist, peffect)
503  {
504  char buf2[512];
505  int delta;
506  int new_total;
507 
508  get_effect_req_text(peffect, buf2, sizeof(buf2));
509 
510  if (peffect->multiplier) {
512  peffect->multiplier);
513 
514  if (mul == 0) {
515  /* Suppress text when multiplier setting suppresses effect
516  * (this will also suppress it when the city owner's policy
517  * settings are not known to us) */
518  continue;
519  }
520  delta = (peffect->value * mul) / 100;
521  } else {
522  delta = peffect->value;
523  }
524  bonus += delta;
525  new_total = bonus * base / 100;
526  city_sum_add_full(sum, new_total - city_sum_total(sum), true,
527  /* TRANS: percentage city output bonus/loss from
528  * some source; preserve leading space */
529  Q_("?city_surplus: (%+.0f%%)"), delta,
530  Q_("?city_surplus:Bonus from %s"),
531  Q_("?city_surplus:Loss from %s"), buf2);
532  }
534  effect_list_destroy(plist);
535  }
536  }
537 
538  if (pcity->waste[otype] != 0) {
539  int wastetypes[OLOSS_LAST];
540  bool breakdown_ok;
541  int regular_waste;
542  auto gov_centers = player_gov_centers(city_owner(pcity));
543  /* FIXME: this will give the wrong answer in rulesets with waste on
544  * taxed outputs, such as 'science waste', as our total so far includes
545  * contributions taxed from trade, whereas the equivalent bit in
546  * set_city_production() does not */
547  if (city_waste(pcity, otype, city_sum_total(sum), wastetypes,
548  gov_centers)
549  == pcity->waste[otype]) {
550  // Our calculation matches the server's, so we trust our breakdown.
551  city_sum_add_if_nonzero(sum, -wastetypes[OLOSS_SIZE],
552  Q_("?city_surplus:Size penalty"));
553  regular_waste = wastetypes[OLOSS_WASTE];
554  breakdown_ok = true;
555  } else {
556  /* Our calculation doesn't match what the server sent. Account it all
557  * to corruption/waste. */
558  regular_waste = pcity->waste[otype];
559  breakdown_ok = false;
560  }
561  if (regular_waste > 0) {
562  const char *fmt;
563  switch (otype) {
564  case O_SHIELD:
565  default: // FIXME other output types?
566  /* TRANS: %s is normally empty, but becomes '?' if client is
567  * uncertain about its accounting (should never happen) */
568  fmt = Q_("?city_surplus:Waste%s");
569  break;
570  case O_TRADE:
571  /* TRANS: %s is normally empty, but becomes '?' if client is
572  * uncertain about its accounting (should never happen) */
573  fmt = Q_("?city_surplus:Corruption%s");
574  break;
575  }
576  city_sum_add(sum, -regular_waste, fmt, breakdown_ok ? "" : "?");
577  }
578  }
579 
580  city_sum_add_if_nonzero(sum, -pcity->unhappy_penalty[otype],
581  Q_("?city_surplus:Disorder"));
582 
583  if (pcity->usage[otype] > 0) {
584  city_sum_add(sum, -pcity->usage[otype], Q_("?city_surplus:Used"));
585  }
586 
587  return city_sum_print(sum, true,
588  Q_("?city_surplus:"
589  "==== : Adds up to\n"
590  "%4.0f : Total surplus"),
591  static_cast<double>(pcity->surplus[otype]));
592 }
593 
597 QString get_city_dialog_illness_text(const struct city *pcity)
598 {
599  int illness, ill_base, ill_size, ill_trade, ill_pollution;
600  struct effect_list *plist;
601  struct city_sum *sum;
602 
603  if (!game.info.illness_on) {
604  return _("Illness deactivated in ruleset.");
605  }
606 
607  sum = city_sum_new(Q_("?city_plague:%+5.1f%% : %s"));
608 
609  illness = city_illness_calc(pcity, &ill_base, &ill_size, &ill_trade,
610  &ill_pollution);
611 
612  city_sum_add(sum, static_cast<float>(ill_size) / 10.0,
613  Q_("?city_plague:Risk from overcrowding"));
614  city_sum_add(sum, static_cast<float>(ill_trade) / 10.0,
615  Q_("?city_plague:Risk from trade"));
616  city_sum_add(sum, static_cast<float>(ill_pollution) / 10.0,
617  Q_("?city_plague:Risk from pollution"));
618 
619  plist = effect_list_new();
620 
621  (void) get_city_bonus_effects(plist, pcity, nullptr, EFT_HEALTH_PCT);
622 
623  effect_list_iterate(plist, peffect)
624  {
625  char buf2[512];
626  int delta;
627 
628  get_effect_req_text(peffect, buf2, sizeof(buf2));
629 
630  if (peffect->multiplier) {
632  peffect->multiplier);
633 
634  if (mul == 0) {
635  /* Suppress text when multiplier setting suppresses effect
636  * (this will also suppress it when the city owner's policy
637  * settings are not known to us) */
638  continue;
639  }
640  delta = (peffect->value * mul) / 100;
641  } else {
642  delta = peffect->value;
643  }
644 
645  city_sum_add_full(sum, -(0.1 * ill_base * delta / 100), true,
646  Q_("?city_plague: (%+.0f%%)"), -delta,
647  Q_("?city_plague:Risk from %s"),
648  Q_("?city_plague:Bonus from %s"), buf2);
649  }
651  effect_list_destroy(plist);
652 
653  /* XXX: account_for_unknown==FALSE: the displayed sum can fail to
654  * add up due to rounding. Making it always add up probably requires
655  * arbitrary assignment of 0.1% rounding figures to particular
656  * effects with something like distribute(). */
657  return city_sum_print(sum, false,
658  Q_("?city_plague:"
659  "====== : Adds up to\n"
660  "%5.1f%% : Plague chance per turn"),
661  (static_cast<double>(illness) / 10.0));
662 }
663 
667 QString get_city_dialog_pollution_text(const struct city *pcity)
668 {
669  int pollu, prod, trade, pop, mod;
670  struct city_sum *sum = city_sum_new(Q_("?city_pollution:%+4.0f : %s"));
671 
672  /* On the server, pollution is calculated before production is deducted
673  * for disorder; we need to compensate for that */
674  pollu = city_pollution_types(
675  pcity, pcity->prod[O_SHIELD] + pcity->unhappy_penalty[O_SHIELD],
676  pcity->prod[O_TRADE] + pcity->unhappy_penalty[O_TRADE], &prod, &trade,
677  &pop, &mod);
678 
679  city_sum_add(sum, prod, Q_("?city_pollution:Pollution from shields"));
680  city_sum_add(sum, trade, Q_("?city_pollution:Pollution from trade"));
681  city_sum_add(sum, pop, Q_("?city_pollution:Pollution from citizens"));
682  city_sum_add(sum, mod, Q_("?city_pollution:Pollution modifier"));
683  return city_sum_print(sum, false,
684  Q_("?city_pollution:"
685  "==== : Adds up to\n"
686  "%4.0f : Total surplus"),
687  static_cast<double>(pollu));
688 }
689 
693 QString get_city_dialog_culture_text(const struct city *pcity)
694 {
695  struct effect_list *plist;
696  struct city_sum *sum = city_sum_new(Q_("?city_culture:%4.0f : %s"));
697 
698  /* XXX: no way to check whether client's idea of gain/turn is accurate */
699  city_sum_add(sum, pcity->history, Q_("?city_culture:History (%+d/turn)"),
700  city_history_gain(pcity));
701 
702  plist = effect_list_new();
703 
704  (void) get_city_bonus_effects(plist, pcity, nullptr, EFT_PERFORMANCE);
705 
706  effect_list_iterate(plist, peffect)
707  {
708  char buf2[512];
709  int mul = 100;
710  int value;
711 
712  get_effect_req_text(peffect, buf2, sizeof(buf2));
713 
714  if (peffect->multiplier) {
716  peffect->multiplier);
717 
718  if (mul == 0) {
719  /* Suppress text when multiplier setting suppresses effect
720  * (this will also suppress it when the city owner's policy
721  * settings are not known to us) */
722  continue;
723  }
724  }
725 
726  value = (peffect->value * mul) / 100;
727  // TRANS: text describing source of culture bonus ("Library+Republic")
728  city_sum_add_if_nonzero(sum, value, Q_("?city_culture:%s"), buf2);
729  }
731  effect_list_destroy(plist);
732 
733  return city_sum_print(sum, true,
734  Q_("?city_culture:"
735  "==== : Adds up to\n"
736  "%4.0f : Total culture"),
737  static_cast<double>(pcity->client.culture));
738 }
739 
743 QString get_city_dialog_airlift_text(const struct city *pcity)
744 {
745  char src[512];
746  char dest[512];
747  int unlimited = 0;
748 
749  if (game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC
750  && pcity->airlift >= 1) {
751  /* AIRLIFTING_UNLIMITED_SRC applies only when the source city has
752  * remaining airlift. */
753 
754  unlimited++;
755 
756  /* TRANS: airlift. Possible take offs text. String is a
757  * proviso that take offs can't occur if landings spend all the
758  * remaining airlift when landings are limited and empty when they
759  * aren't limited. */
760  fc_snprintf(src, sizeof(src), _("unlimited take offs%s"),
761  game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST
762  /* TRANS: airlift unlimited take offs proviso used above.
763  * Plural based on remaining airlift capacity. */
764  ? ""
765  : PL_(" (until the landing has been spent)",
766  " (until all landings have been spent)",
767  pcity->airlift));
768  } else {
769  fc_snprintf(src, sizeof(src),
770  /* TRANS: airlift. Possible take offs text. Number is
771  * airlift capacity. */
772  PL_("%d take off", "%d take offs", pcity->airlift),
773  pcity->airlift);
774  }
775 
776  if (game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST) {
777  /* AIRLIFTING_UNLIMITED_DEST works even if the source city has no
778  * remaining airlift. */
779 
780  unlimited++;
781 
782  // TRANS: airlift. Possible landings text.
783  fc_snprintf(dest, sizeof(dest), _("unlimited landings"));
784  } else {
785  fc_snprintf(dest, sizeof(dest),
786  /* TRANS: airlift. Possible landings text.
787  * Number is airlift capacity. */
788  PL_("%d landing", "%d landings", pcity->airlift),
789  pcity->airlift);
790  }
791 
792  switch (unlimited) {
793  case 2:
794  // TRANS: airlift take offs and landings
795  return _("unlimited take offs and landings");
796  break;
797  case 1:
798  /* TRANS: airlift take offs and landings. One is unlimited. The first
799  * string is the take offs text. The 2nd string is the landings text. */
800  return QString::asprintf(_("%s and %s"), src, dest);
801  break;
802  default:
803  return QString::asprintf(
804  /* TRANS: airlift take offs or landings, no unlimited.
805  * Number is airlift capacity. */
806  PL_("%d take off or landing", "%d take offs or landings",
807  pcity->airlift),
808  pcity->airlift);
809  break;
810  }
811 }
812 
816 QString get_city_dialog_size_text(const struct city *pcity)
817 {
818  auto text = QString();
819  // TRANS: Number of happy citizens
820  text += QString(_("Happy: %1\n"))
821  .arg(pcity->feel[CITIZEN_HAPPY][FEELING_FINAL]);
822  // TRANS: Number of content citizens
823  text += QString(_("Content: %1\n"))
824  .arg(pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]);
825  // TRANS: Number of unhappy citizens
826  text += QString(_("Unhappy: %1\n"))
827  .arg(pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]);
828  // TRANS: Number of angry citizens
829  text += QString(_("Angry: %1\n"))
830  .arg(pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]);
831 
833  {
834  text += QStringLiteral("%1: %2\n")
836  .arg(pcity->specialists[sp]);
837  }
839 
840  return html_pre(text.trimmed());
841 }
842 
846 QString get_city_dialog_status_text(const struct city *pcity)
847 {
848  if (city_unhappy(pcity)) {
849  // TRANS: City dialog Status: Disorder
850  return _("Disorder");
851  } else if (city_celebrating(pcity)) {
852  // TRANS: City dialog Status: Celebrating
853  return _("Celebrating");
854  } else if (city_happy(pcity)) {
855  // TRANS: City dialog Status: Happy
856  return _("Happy");
857  } else {
858  // TRANS: City dialog Status: Content
859  return _("Content");
860  }
861 }
862 
866 QString get_city_dialog_growth_value(const struct city *pcity)
867 {
868  auto granaryturns = city_turns_to_grow(pcity);
869  if (granaryturns == 0) {
870  // TRANS: city growth is blocked. Keep short.
871  return _("blocked");
872  } else if (granaryturns == FC_INFINITY) {
873  // TRANS: city is not growing. Keep short.
874  return _("never");
875  } else {
876  // TRANS: city growth turns. Keep short.
877  return QString::asprintf(PL_("%3d turn", "%3d turns", abs(granaryturns)),
878  abs(granaryturns));
879  }
880 }
881 
885 QString get_city_dialog_airlift_value(const struct city *pcity)
886 {
887  char src[512];
888  char dest[512];
889  int unlimited = 0;
890 
891  if (game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC
892  && pcity->airlift >= 1) {
893  /* AIRLIFTING_UNLIMITED_SRC applies only when the source city has
894  * remaining airlift. */
895 
896  unlimited++;
897 
898  /* TRANS: airlift. Possible take offs text. String is a symbol that
899  * indicates that terms and conditions apply when landings are limited
900  * and empty when they aren't limited. */
901  fc_snprintf(src, sizeof(src), _(" ∞%s"),
902  game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST
903  /* TRANS: airlift unlimited take offs may be spent symbol
904  * used above. */
905  ? ""
906  : _("*"));
907  } else {
908  /* TRANS: airlift. Possible take offs text. Number is
909  * airlift capacity. */
910  fc_snprintf(src, sizeof(src), _("%2d"), pcity->airlift);
911  }
912 
913  if (game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST) {
914  /* AIRLIFTING_UNLIMITED_DEST works even if the source city has no
915  * remaining airlift. */
916 
917  unlimited++;
918 
919  // TRANS: airlift. Possible landings text.
920  fc_snprintf(dest, sizeof(dest), _(" ∞"));
921  } else {
922  // TRANS: airlift. Possible landings text.
923  fc_snprintf(dest, sizeof(dest), _("%2d"), pcity->airlift);
924  }
925 
926  switch (unlimited) {
927  case 2:
928  // TRANS: unlimited airlift take offs and landings
929  return _(" ∞");
930  break;
931  case 1:
932  /* TRANS: airlift take offs and landings. One is unlimited. The first
933  * string is the take offs text. The 2nd string is the landings text. */
934  return QString::asprintf(_(" s: %s d: %s"), src, dest);
935  break;
936  default:
937  // TRANS: airlift take offs or landings, no unlimited
938  return QString::asprintf(_(" %s"), src);
939  break;
940  }
941 }
942 
949 int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx,
950  enum citizen_category *categories)
951 {
952  int i = 0, n;
953 
954  fc_assert(idx >= 0 && idx < FEELING_LAST);
955 
956  for (n = 0; n < pcity->feel[CITIZEN_HAPPY][idx]; n++, i++) {
957  categories[i] = CITIZEN_HAPPY;
958  }
959  for (n = 0; n < pcity->feel[CITIZEN_CONTENT][idx]; n++, i++) {
960  categories[i] = CITIZEN_CONTENT;
961  }
962  for (n = 0; n < pcity->feel[CITIZEN_UNHAPPY][idx]; n++, i++) {
963  categories[i] = CITIZEN_UNHAPPY;
964  }
965  for (n = 0; n < pcity->feel[CITIZEN_ANGRY][idx]; n++, i++) {
966  categories[i] = CITIZEN_ANGRY;
967  }
968 
970  {
971  for (n = 0; n < pcity->specialists[sp]; n++, i++) {
972  categories[i] = static_cast<citizen_category>(
973  static_cast<int>(CITIZEN_SPECIALIST) + static_cast<int>(sp));
974  }
975  }
977 
978  if (city_size_get(pcity) != i) {
979  qCritical("get_city_citizen_types() %d citizens "
980  "not equal %d city size in \"%s\".",
981  i, city_size_get(pcity), city_name_get(pcity));
982  }
983  return i;
984 }
985 
989 void city_rotate_specialist(struct city *pcity, int citizen_index)
990 {
991  enum citizen_category categories[MAX_CITY_SIZE];
992  Specialist_type_id from, to;
993  int num_citizens =
994  get_city_citizen_types(pcity, FEELING_FINAL, categories);
995 
996  if (citizen_index < 0 || citizen_index >= num_citizens
997  || categories[citizen_index] < CITIZEN_SPECIALIST) {
998  return;
999  }
1000  from = categories[citizen_index] - CITIZEN_SPECIALIST;
1001 
1002  /* Loop through all specialists in order until we find a usable one
1003  * (or run out of choices). */
1004  to = from;
1005  fc_assert(to >= 0 && to < specialist_count());
1006  do {
1007  to = (to + 1) % specialist_count();
1008  } while (to != from && !city_can_use_specialist(pcity, to));
1009 
1010  if (from != to) {
1011  city_change_specialist(pcity, from, to);
1012  }
1013 }
1014 
1018 int city_change_production(struct city *pcity, struct universal *target)
1019 {
1020  return dsend_packet_city_change(&client.conn, pcity->id, target->kind,
1021  universal_number(target));
1022 }
1023 
1029 int city_set_worklist(struct city *pcity, const struct worklist *pworklist)
1030 {
1031  return dsend_packet_city_worklist(&client.conn, pcity->id, pworklist);
1032 }
1033 
1042 static bool base_city_queue_insert(struct city *pcity, int position,
1043  struct universal *item)
1044 {
1045  if (position == 0) {
1046  struct universal old = pcity->production;
1047 
1048  // Insert as current production.
1049  if (!can_city_build_direct(pcity, item)) {
1050  return false;
1051  }
1052 
1053  if (!worklist_insert(&pcity->worklist, &old, 0)) {
1054  return false;
1055  }
1056 
1057  city_change_production(pcity, item);
1058  } else if (position >= 1
1059  && position <= worklist_length(&pcity->worklist)) {
1060  // Insert into middle.
1061  if (!can_city_build_later(pcity, item)) {
1062  return false;
1063  }
1064  if (!worklist_insert(&pcity->worklist, item, position - 1)) {
1065  return false;
1066  }
1067  } else {
1068  // Insert at end.
1069  if (!can_city_build_later(pcity, item)) {
1070  return false;
1071  }
1072  if (!worklist_append(&pcity->worklist, item)) {
1073  return false;
1074  }
1075  }
1076  return true;
1077 }
1078 
1084 bool city_queue_insert(struct city *pcity, int position,
1085  struct universal *item)
1086 {
1087  if (base_city_queue_insert(pcity, position, item)) {
1088  city_set_worklist(pcity, &pcity->worklist);
1089  return true;
1090  }
1091  return false;
1092 }
1093 
1099 bool city_queue_insert_worklist(struct city *pcity, int position,
1100  const struct worklist *worklist)
1101 {
1102  bool success = false;
1103 
1104  if (worklist_length(worklist) == 0) {
1105  return true;
1106  }
1107 
1108  worklist_iterate(worklist, target)
1109  {
1110  if (base_city_queue_insert(pcity, position, &target)) {
1111  if (position > 0) {
1112  /* Move to the next position (unless position == -1 in which case
1113  * we're appending. */
1114  position++;
1115  }
1116  success = true;
1117  }
1118  }
1120 
1121  if (success) {
1122  city_set_worklist(pcity, &pcity->worklist);
1123  }
1124 
1125  return success;
1126 }
1127 
1131 void city_get_queue(struct city *pcity, struct worklist *pqueue)
1132 {
1133  worklist_copy(pqueue, &pcity->worklist);
1134 
1135  /* The GUI wants current production to be in the task list, but the
1136  worklist API wants it out for reasons unknown. Perhaps someone enjoyed
1137  making things more complicated than necessary? So I dance around it. */
1138 
1139  // We want the current production to be in the queue. Always.
1140  worklist_remove(pqueue, MAX_LEN_WORKLIST - 1);
1141 
1142  worklist_insert(pqueue, &pcity->production, 0);
1143 }
1144 
1148 bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
1149 {
1150  struct worklist copy;
1151  struct universal target;
1152 
1153  worklist_copy(&copy, pqueue);
1154 
1155  /* The GUI wants current production to be in the task list, but the
1156  worklist API wants it out for reasons unknown. Perhaps someone enjoyed
1157  making things more complicated than necessary? So I dance around it. */
1158  if (worklist_peek(&copy, &target)) {
1159  if (!city_can_change_build(pcity)
1160  && !are_universals_equal(&pcity->production, &target)) {
1161  /* We cannot change production to one from worklist.
1162  * Do not replace old worklist with new one. */
1163  return false;
1164  }
1165 
1166  worklist_advance(&copy);
1167 
1168  city_set_worklist(pcity, &copy);
1169  city_change_production(pcity, &target);
1170  } else {
1171  // You naughty boy, you can't erase the current production. Nyah!
1172  if (worklist_is_empty(&pcity->worklist)) {
1173  refresh_city_dialog(pcity);
1174  } else {
1175  city_set_worklist(pcity, &copy);
1176  }
1177  }
1178 
1179  return true;
1180 }
1181 
1185 bool city_can_buy(const struct city *pcity)
1186 {
1187  /* See really_handle_city_buy() in the server. However this function
1188  * doesn't allow for error messages. It doesn't check the cost of
1189  * buying; that's handled separately (and with an error message). */
1190  return (can_client_issue_orders() && nullptr != pcity
1191  && city_owner(pcity) == client.conn.playing
1192  && pcity->turn_founded != game.info.turn && !pcity->did_buy
1193  && (VUT_UTYPE == pcity->production.kind
1195  IF_GOLD))
1196  && !(VUT_UTYPE == pcity->production.kind && pcity->anarchy != 0)
1197  && pcity->client.buy_cost > 0);
1198 }
1199 
1203 int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
1204 {
1205  return dsend_packet_city_sell(&client.conn, pcity->id, sell_id);
1206 }
1207 
1211 int city_buy_production(struct city *pcity)
1212 {
1213  return dsend_packet_city_buy(&client.conn, pcity->id);
1214 }
1215 
1220  Specialist_type_id to)
1221 {
1222  return dsend_packet_city_change_specialist(&client.conn, pcity->id, from,
1223  to);
1224 }
1225 
1229 int city_rename(struct city *pcity, const char *name)
1230 {
1231  return dsend_packet_city_rename(&client.conn, pcity->id, name);
1232 }
int rs_max_city_radius_sq()
Maximum city radius in this ruleset.
Definition: city.cpp:152
int city_production_build_shield_cost(const struct city *pcity)
Return the number of shields it takes to build current city production.
Definition: city.cpp:701
int city_build_slots(const struct city *pcity)
The maximum number of units a city can build per turn.
Definition: city.cpp:2809
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
bool city_can_use_specialist(const struct city *pcity, Specialist_type_id type)
Returns TRUE iff the given city can use this kind of specialist.
Definition: city.cpp:1005
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Return TRUE when the current production has this flag.
Definition: city.cpp:691
void add_tax_income(const struct player *pplayer, int trade, int *output)
Add the incomes of a city according to the taxrates (ignore # of specialists).
Definition: city.cpp:2150
int get_city_tithes_bonus(const struct city *pcity)
Return the amount of gold generated by buildings under "tithe" attribute governments.
Definition: city.cpp:2132
const char * city_name_get(const struct city *pcity)
Return the name of the city.
Definition: city.cpp:1077
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Calculates the turns which are needed to build the requested production in the city.
Definition: city.cpp:784
bool city_unhappy(const struct city *pcity)
Return TRUE iff the city is unhappy.
Definition: city.cpp:1544
bool city_celebrating(const struct city *pcity)
cities celebrate only after consecutive happy turns
Definition: city.cpp:1564
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Calculate city's illness in tenth of percent:
Definition: city.cpp:2746
bool city_happy(const struct city *pcity)
Return TRUE iff the city is happy.
Definition: city.cpp:1531
bool can_city_build_direct(const struct city *pcity, const struct universal *target)
Returns whether city can immediately build given target, unit or improvement.
Definition: city.cpp:935
int city_waste(const struct city *pcity, Output_type_id otype, int total, int *breakdown, const std::vector< city * > &gov_centers, const cached_waste *pcwaste)
Give corruption/waste generated by city.
Definition: city.cpp:3108
bool can_city_build_later(const struct city *pcity, const struct universal *target)
Returns whether city can ever build given target, unit or improvement.
Definition: city.cpp:970
int city_pollution_types(const struct city *pcity, int shield_total, int trade_total, int *pollu_prod, int *pollu_trade, int *pollu_pop, int *pollu_mod)
Calculate the pollution from production and population in the city.
Definition: city.cpp:2651
bool city_production_build_units(const struct city *pcity, bool add_production, int *num_units)
Return TRUE if the city could use the additional build slots provided by the effect City_Build_Slots.
Definition: city.cpp:711
int city_turns_to_grow(const struct city *pcity)
Calculates the turns which are needed for the city to grow.
Definition: city.cpp:1897
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
struct output_type output_types[O_LAST]
Definition: city.cpp:82
bool city_can_change_build(const struct city *pcity)
Returns TRUE iff the given city can change what it is building.
Definition: city.cpp:1016
citizen_category
Definition: city.h:239
@ CITIZEN_SPECIALIST
Definition: city.h:245
@ CITIZEN_ANGRY
Definition: city.h:243
@ CITIZEN_HAPPY
Definition: city.h:240
@ CITIZEN_CONTENT
Definition: city.h:241
@ CITIZEN_UNHAPPY
Definition: city.h:242
#define MAX_CITY_SIZE
Definition: city.h:79
citizen_feeling
Definition: city.h:250
@ FEELING_FINAL
Definition: city.h:256
@ FEELING_LAST
Definition: city.h:257
@ OLOSS_SIZE
Definition: city.h:263
@ OLOSS_WASTE
Definition: city.h:262
@ OLOSS_LAST
Definition: city.h:264
#define city_map_iterate_without_index_end
Definition: city.h:154
#define CITY_ABS2REL(_coor)
Definition: city.h:89
#define city_map_iterate_without_index(_radius_sq, _x, _y)
Definition: city.h:150
QString get_city_dialog_airlift_value(const struct city *pcity)
Return airlift capacity.
QString get_city_dialog_status_text(const struct city *pcity)
Return text describing the city's status: disorder/celebrating/...
int get_citydlg_canvas_height()
Return the height of the city dialog canvas.
QString get_city_dialog_culture_text(const struct city *pcity)
Return text describing the culture output.
QString get_city_dialog_output_text(const struct city *pcity, Output_type_id otype)
Return text describing the production output.
void get_city_dialog_production(struct city *pcity, char *buffer, size_t buffer_len)
Find the city dialog city production text for the given city, and place it into the buffer.
int city_set_worklist(struct city *pcity, const struct worklist *pworklist)
Set the worklist for a given city.
int city_rename(struct city *pcity, const char *name)
Tell the server to rename the city.
char * city_production_cost_str(const struct city *pcity)
Return a string describing the cost for the production of the city considerung several build slots fo...
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx, enum citizen_category *categories)
Provide a list of all citizens in the city, in order.
int city_buy_production(struct city *pcity)
Buy the current production item in a given city.
bool city_queue_insert(struct city *pcity, int position, struct universal *item)
Insert an item into the city's queue.
bool city_queue_insert_worklist(struct city *pcity, int position, const struct worklist *worklist)
Insert the worklist into the city's queue at the given position.
QString get_city_dialog_growth_value(const struct city *pcity)
Return time until next growth.
bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
Set the city current production and the worklist, like it should be.
QString get_city_dialog_size_text(const struct city *pcity)
Return text describing the city's citizens.
QString get_city_dialog_pollution_text(const struct city *pcity)
Return text describing the pollution output.
int city_change_production(struct city *pcity, struct universal *target)
Change the production of a given city.
void city_rotate_specialist(struct city *pcity, int citizen_index)
Rotate the given specialist citizen to the next type of citizen.
static bool base_city_queue_insert(struct city *pcity, int position, struct universal *item)
Insert an item into the city's queue.
QString get_city_dialog_airlift_text(const struct city *pcity)
Return text describing airlift capacity.
static int citydlg_map_height
int get_citydlg_canvas_width()
Return the width of the city dialog canvas.
void city_get_queue(struct city *pcity, struct worklist *pqueue)
Get the city current production and the worklist, like it should be.
int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
Change the production of a given city.
void generate_citydlg_dimensions()
Calculate the citydlg width and height.
int city_change_specialist(struct city *pcity, Specialist_type_id from, Specialist_type_id to)
Change a specialist in the given city.
QString get_city_dialog_illness_text(const struct city *pcity)
Return text describing the chance for a plague.
bool city_can_buy(const struct city *pcity)
Return TRUE iff the city can buy.
static int citydlg_map_width
void refresh_city_dialog(struct city *pcity)
Definition: shared.h:24
struct civclient client
bool can_client_issue_orders()
Returns TRUE iff the client can issue orders (such as giving unit commands).
int city_history_gain(const struct city *pcity)
How much history city gains this turn.
Definition: culture.cpp:31
static void base(QVariant data1, QVariant data2)
Action "Build Base" for choice dialog.
Definition: dialogs.cpp:2393
int get_city_bonus_effects(struct effect_list *plist, const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Returns the effect sources of this type currently active at the city.
Definition: effects.cpp:909
void get_effect_req_text(const struct effect *peffect, char *buf, size_t buf_len)
Make user-friendly text for the source.
Definition: effects.cpp:1011
int get_city_bonus(const struct city *pcity, enum effect_type effect_type, enum vision_layer vlayer)
Returns the effect bonus at a city.
Definition: effects.cpp:688
#define effect_list_iterate_end
Definition: effects.h:349
#define effect_list_iterate(effect_list, peffect)
Definition: effects.h:347
int Impr_type_id
Definition: fc_types.h:293
int Specialist_type_id
Definition: fc_types.h:292
@ O_SHIELD
Definition: fc_types.h:86
@ O_TRADE
Definition: fc_types.h:87
@ O_GOLD
Definition: fc_types.h:88
@ O_LAST
Definition: fc_types.h:91
enum output_type_id Output_type_id
Definition: fc_types.h:295
#define Q_(String)
Definition: fcintl.h:53
#define PL_(String1, String2, n)
Definition: fcintl.h:54
#define _(String)
Definition: fcintl.h:50
struct civ_game game
Definition: game.cpp:47
struct city * game_city_by_number(int id)
Often used function to get a city pointer from a city ID.
Definition: game.cpp:103
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
Return TRUE if the impr has this flag otherwise FALSE.
const char * name
Definition: inputfile.cpp:118
#define fc_assert(condition)
Definition: log.h:89
client_options * gui_options
Definition: options.cpp:74
int player_multiplier_effect_value(const struct player *pplayer, const struct multiplier *pmul)
Return the multiplier value currently in effect for pplayer, scaled from display units to the units u...
Definition: player.cpp:1867
std::vector< city * > player_gov_centers(const struct player *pplayer)
Locate the player's government centers.
Definition: player.cpp:1264
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Return TRUE iff the two sources are equivalent.
int universal_number(const struct universal *source)
Return the universal number of the constituent.
#define MIN(x, y)
Definition: shared.h:49
#define FC_INFINITY
Definition: shared.h:32
#define MAX(x, y)
Definition: shared.h:48
struct specialist * specialist_by_number(const Specialist_type_id id)
Return the specialist pointer for the given number.
Definition: specialist.cpp:92
Specialist_type_id specialist_count()
Return the number of specialist_types.
Definition: specialist.cpp:63
const char * specialist_plural_translation(const struct specialist *sp)
Return the (translated, plural) name of the specialist type.
Definition: specialist.cpp:151
#define specialist_type_iterate_end
Definition: specialist.h:73
#define specialist_type_iterate(sp)
Definition: specialist.h:67
SPECPQ_PRIORITY_TYPE priority
Definition: specpq.h:76
Definition: city.h:291
struct city::@15::@18 client
int surplus[O_LAST]
Definition: city.h:324
int history
Definition: city.h:379
int id
Definition: city.h:296
int waste[O_LAST]
Definition: city.h:325
int turn_founded
Definition: city.h:357
int airlift
Definition: city.h:349
int citizen_base[O_LAST]
Definition: city.h:328
bool did_buy
Definition: city.h:351
int anarchy
Definition: city.h:355
int usage[O_LAST]
Definition: city.h:329
struct worklist worklist
Definition: city.h:373
struct universal production
Definition: city.h:368
int bonus[O_LAST]
Definition: city.h:335
int unhappy_penalty[O_LAST]
Definition: city.h:326
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition: city.h:302
citizens specialists[SP_MAX]
Definition: city.h:305
int shield_stock
Definition: city.h:339
int prod[O_LAST]
Definition: city.h:327
struct packet_game_info info
Definition: game.h:80
struct connection conn
Definition: client_main.h:89
bool concise_city_production
Definition: options.h:93
struct player * playing
Definition: connection.h:142
Definition: climisc.h:66
enum universals_n kind
Definition: fc_types.h:740
universals_u value
Definition: fc_types.h:739
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
size_t fc_strlcpy(char *dest, const char *src, size_t n)
fc_strlcpy() provides utf-8 version of (non-standard) function strlcpy() It is intended as more user-...
Definition: support.cpp:412
int fc__attribute((nonnull(1, 3)))
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
Definition: tilespec.cpp:383
int tileset_tile_width(const struct tileset *t)
Return the tile width of the current tileset.
Definition: tilespec.cpp:371
const char * goods_name_translation(struct goods_type *pgood)
Return translated name of this goods type.
#define trade_routes_iterate_end
Definition: traderoutes.h:127
#define trade_routes_iterate(c, proute)
Definition: traderoutes.h:122
const struct impr_type * building
Definition: fc_types.h:579
void map_to_gui_vector(const struct tileset *t, float *gui_dx, float *gui_dy, int map_dx, int map_dy)
Translate from a cartesian system to the GUI system.
void worklist_advance(struct worklist *pwl)
Remove first element from worklist.
Definition: worklist.cpp:98
bool worklist_peek(const struct worklist *pwl, struct universal *prod)
Fill in the id and is_unit values for the head of the worklist if the worklist is non-empty.
Definition: worklist.cpp:70
void worklist_copy(struct worklist *dst, const struct worklist *src)
Copy contents from worklist src to worklist dst.
Definition: worklist.cpp:103
bool worklist_is_empty(const struct worklist *pwl)
Returns whether worklist has no elements.
Definition: worklist.cpp:60
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Adds the id to the next available slot in the worklist.
Definition: worklist.cpp:138
bool worklist_insert(struct worklist *pwl, const struct universal *prod, int idx)
Inserts the production at the location idx in the worklist, thus moving all subsequent entries down.
Definition: worklist.cpp:158
void worklist_remove(struct worklist *pwl, int idx)
Remove element from position idx.
Definition: worklist.cpp:113
int worklist_length(const struct worklist *pwl)
Returns the number of entries in the worklist.
Definition: worklist.cpp:51
#define worklist_iterate_end
Definition: worklist.h:55
#define worklist_iterate(_list, _p)
Definition: worklist.h:47
#define MAX_LEN_WORKLIST
Definition: worklist.h:19