Freeciv21
Develop your civilization from humble roots to a global empire
text.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 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 
11 #include <math.h> // ceil
12 #include <string.h>
13 
14 // utility
15 #include "astring.h"
16 #include "fcintl.h"
17 #include "log.h"
18 #include "nation.h"
19 #include "support.h"
20 
21 // common
22 #include "calendar.h"
23 #include "citizens.h"
24 #include "city.h"
25 #include "clientutils.h"
26 #include "combat.h"
27 #include "culture.h"
28 #include "effects.h"
29 #include "fc_types.h" // LINE_BREAK
30 #include "game.h"
31 #include "government.h"
32 #include "map.h"
33 #include "movement.h"
34 #include "research.h"
35 #include "traderoutes.h"
36 #include "unitlist.h"
37 
38 // client
39 #include "client_main.h"
40 #include "climap.h"
41 #include "climisc.h"
42 #include "control.h"
43 #include "goto.h"
44 
45 #include "text.h"
46 
47 int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs);
48 
52 const QString get_tile_output_text(const struct tile *ptile)
53 {
54  QString str;
55  int i;
56  char output_text[O_LAST][16];
57 
58  for (i = 0; i < O_LAST; i++) {
59  int before_penalty = 0;
60  int x = city_tile_output(nullptr, ptile, false,
61  static_cast<Output_type_id>(i));
62 
63  if (nullptr != client.conn.playing) {
64  before_penalty = get_player_output_bonus(
66  get_output_type(static_cast<Output_type_id>(i)),
67  EFT_OUTPUT_PENALTY_TILE);
68  }
69 
70  if (before_penalty > 0 && x > before_penalty) {
71  fc_snprintf(output_text[i], sizeof(output_text[i]), "%d(-1)", x);
72  } else {
73  fc_snprintf(output_text[i], sizeof(output_text[i]), "%d", x);
74  }
75  }
76 
77  str = QStringLiteral("%1/%2/%3")
78  .arg(output_text[O_FOOD], output_text[O_SHIELD],
79  output_text[O_TRADE]);
80 
81  return qUtf8Printable(str);
82 }
83 
88 static inline void get_full_username(char *buf, int buflen,
89  const struct player *pplayer)
90 {
91  if (!buf || buflen < 1) {
92  return;
93  }
94 
95  if (!pplayer) {
96  buf[0] = '\0';
97  return;
98  }
99 
100  if (is_ai(pplayer)) {
101  // TRANS: "AI <player name>"
102  fc_snprintf(buf, buflen, _("AI %s"), pplayer->name);
103  } else {
104  fc_strlcpy(buf, pplayer->username, buflen);
105  }
106 }
107 
112 static inline void get_full_nation(char *buf, int buflen,
113  const struct player *pplayer)
114 {
115  if (!buf || buflen < 1) {
116  return;
117  }
118 
119  if (!pplayer) {
120  buf[0] = '\0';
121  return;
122  }
123 
124  if (pplayer->team) {
125  // TRANS: "<nation adjective>, team <team name>"
126  fc_snprintf(buf, buflen, _("%s, team %s"),
128  team_name_translation(pplayer->team));
129  } else {
130  fc_strlcpy(buf, nation_adjective_for_player(pplayer), buflen);
131  }
132 }
133 
137 const QString popup_info_text(struct tile *ptile)
138 {
139  QString activity_text;
140  struct city *pcity = tile_city(ptile);
141  struct unit *punit = find_visible_unit(ptile);
142  const char *diplo_nation_plural_adjectives[DS_LAST] = {
143  "" /* unused, DS_ARMISTICE */, Q_("?nation:Hostile"),
144  "" /* unused, DS_CEASEFIRE */, Q_("?nation:Peaceful"),
145  Q_("?nation:Friendly"), Q_("?nation:Mysterious"),
146  Q_("?nation:Friendly(team)")};
147  const char *diplo_city_adjectives[DS_LAST] = {
148  "" /* unused, DS_ARMISTICE */, Q_("?city:Hostile"),
149  "" /* unused, DS_CEASEFIRE */, Q_("?city:Peaceful"),
150  Q_("?city:Friendly"), Q_("?city:Mysterious"),
151  Q_("?city:Friendly(team)")};
152  QString str;
153  char username[MAX_LEN_NAME + 32];
154  char nation[2 * MAX_LEN_NAME + 32];
155  int tile_x, tile_y, nat_x, nat_y;
156  bool first;
157 
158  index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
159  str = QString(_("Location: (%1, %2) [%3]\n"))
160  .arg(QString::number(tile_x), QString::number(tile_y),
161  QString::number(tile_continent(ptile)));
163  str += QString(_("Native coordinates: (%1, %2)\n"))
164  .arg(QString::number(nat_x), QString::number(nat_y));
165 
166  if (client_tile_get_known(ptile) == TILE_UNKNOWN) {
167  str += QString(_("Unknown"));
168  return str.trimmed();
169  }
170  str += QString(_("Terrain: %1")).arg(tile_get_info_text(ptile, true, 0))
171  + qendl();
172  str += QString(_("Food/Prod/Trade: %1")).arg(get_tile_output_text(ptile))
173  + qendl();
174  first = true;
175  extra_type_iterate(pextra)
176  {
177  if (pextra->category == ECAT_BONUS
178  && tile_has_visible_extra(ptile, pextra)) {
179  if (!first) {
180  str += QStringLiteral(",%1").arg(extra_name_translation(pextra));
181  } else {
182  str += QStringLiteral("%1").arg(extra_name_translation(pextra))
183  + qendl();
184  first = false;
185  }
186  }
187  }
189  if (BORDERS_DISABLED != game.info.borders && !pcity) {
190  struct player *owner = tile_owner(ptile);
191 
192  get_full_username(username, sizeof(username), owner);
193  get_full_nation(nation, sizeof(nation), owner);
194 
195  if (nullptr != client.conn.playing && owner == client.conn.playing) {
196  str += QString(_("Our territory")) + qendl();
197  } else if (nullptr != owner && nullptr == client.conn.playing) {
198  // TRANS: "Territory of <username> (<nation + team>)"
199  str +=
200  QString(_("Territory of %1 (%2)")).arg(username, nation) + qendl();
201  } else if (nullptr != owner) {
202  struct player_diplstate *ds =
204 
205  if (ds->type == DS_CEASEFIRE) {
206  int turns = ds->turns_left;
207  /* TRANS: "Territory of <username> (<nation + team>)
208  * (<number> turn cease-fire)" */
209  str +=
210  QString(PL_("Territory of %1 (%2) (%3 turn cease-fire)",
211  "Territory of %1 (%2) (%3 turn cease-fire)", turns))
212  .arg(username, nation, QString::number(turns))
213  + qendl();
214  } else if (ds->type == DS_ARMISTICE) {
215  int turns = ds->turns_left;
216  /* TRANS: "Territory of <username> (<nation + team>)
217  * (<number> turn armistice)" */
218  str +=
219  QString(PL_("Territory of %1 (%2) (%3 turn armistice)",
220  "Territory of %1 (%2) (%3 turn armistice)", turns))
221  .arg(username, nation, QString::number(turns))
222  + qendl();
223  } else {
224  int type = ds->type;
225  /* TRANS: "Territory of <username>
226  * (<nation + team> | <diplomatic state>)" */
227  str +=
228  QString(_("Territory of %1 (%2 | %3)"))
229  .arg(username, nation, diplo_nation_plural_adjectives[type])
230  + qendl();
231  }
232  } else {
233  str += QString(_("Unclaimed territory")) + qendl();
234  }
235  }
236  if (pcity) {
237  /* Look at city owner, not tile owner (the two should be the same, if
238  * borders are in use). */
239  struct player *owner = city_owner(pcity);
240  QVector<QString> improvements;
241  improvements.reserve(improvement_count());
242 
243  get_full_username(username, sizeof(username), owner);
244  get_full_nation(nation, sizeof(nation), owner);
245 
246  if (nullptr == client.conn.playing || owner == client.conn.playing) {
247  // TRANS: "City: <city name> | <username> (<nation + team>)"
248  str += QString(_("City: %1 | %2 (%3)"))
249  .arg(city_name_get(pcity), username, nation)
250  + qendl();
251  } else {
252  struct player_diplstate *ds =
254  if (ds->type == DS_CEASEFIRE) {
255  int turns = ds->turns_left;
256 
257  /* TRANS: "City: <city name> | <username>
258  * (<nation + team>, <number> turn cease-fire)" */
259  str += QString(PL_("City: %1 | %2 (%3, %4 turn cease-fire)",
260  "City: %1 | %2 (%3, %4 turn cease-fire)", turns))
261  .arg(city_name_get(pcity), username, nation,
262  QString::number(turns))
263  + qendl();
264 
265  } else if (ds->type == DS_ARMISTICE) {
266  int turns = ds->turns_left;
267 
268  /* TRANS: "City: <city name> | <username>
269  * (<nation + team>, <number> turn armistice)" */
270  str += QString(PL_("City: %1 | %2 (%3, %4 turn armistice)",
271  "City: %1 | %2 (%3, %4 turn armistice)", turns))
272  .arg(city_name_get(pcity), username, nation,
273  QString::number(turns))
274  + qendl();
275  } else {
276  /* TRANS: "City: <city name> | <username>
277  * (<nation + team>, <diplomatic state>)" */
278  str += QString(_("City: %1 | %2 (%3, %4)"))
279  .arg(city_name_get(pcity), username, nation,
280  diplo_city_adjectives[ds->type])
281  + qendl();
282  }
283  }
285  int count = unit_list_size(ptile->units);
286 
287  if (count > 0) {
288  // TRANS: preserve leading space
289  str += QString(PL_(" | Occupied with %1 unit.",
290  " | Occupied with %2 units.", count))
291  .arg(QString::number(count));
292  } else {
293  // TRANS: preserve leading space
294  str += QString(_(" | Not occupied."));
295  }
296  } else {
297  if (city_is_occupied(pcity)) {
298  // TRANS: preserve leading space
299  str += QString(_(" | Occupied."));
300  } else {
301  // TRANS: preserve leading space
302  str += QString(_(" | Not occupied."));
303  }
304  }
305  improvement_iterate(pimprove)
306  {
307  if (is_improvement_visible(pimprove)
308  && city_has_building(pcity, pimprove)) {
309  improvements.append(improvement_name_translation(pimprove));
310  }
311  }
313 
314  if (!improvements.isEmpty()) {
315  // TRANS: %s is a list of "and"-separated improvements.
316  str += QString(_(" with %1.")).arg(strvec_to_and_list(improvements))
317  + qendl();
318  }
319 
320  for (const auto &pfocus_unit : get_units_in_focus()) {
321  struct city *hcity = game_city_by_number(pfocus_unit->homecity);
322 
323  if (utype_can_do_action(unit_type_get(pfocus_unit), ACTION_TRADE_ROUTE)
324  && can_cities_trade(hcity, pcity)
325  && can_establish_trade_route(hcity, pcity)) {
326  // TRANS: "Trade from Warsaw: 5"
327  str += QString(_("Trade from %1: %2"))
328  .arg(city_name_get(hcity),
329  QString::number(
330  trade_base_between_cities(hcity, pcity)))
331  + qendl();
332  }
333  }
334  }
335  {
336  const char *infratext = get_infrastructure_text(ptile->extras);
337 
338  if (*infratext != '\0') {
339  str += QString(_("Infrastructure: %1")).arg(infratext) + qendl();
340  }
341  }
342  activity_text = concat_tile_activity_text(ptile);
343  if (activity_text.length() > 0) {
344  str += QString(_("Activity: %1")).arg(activity_text) + qendl();
345  }
346  if (punit && !pcity) {
347  struct player *owner = unit_owner(punit);
348  const struct unit_type *ptype = unit_type_get(punit);
349 
350  get_full_username(username, sizeof(username), owner);
351  get_full_nation(nation, sizeof(nation), owner);
352 
353  time_t dt = time(nullptr) - punit->action_timestamp;
354  if (dt < 0 && !can_unit_move_now(punit)) {
355  char buf[64];
356  format_time_duration(-dt, buf, sizeof(buf));
357  str += _("Can move in ") + QString(buf) + qendl();
358  }
359 
360  auto unit_description = QString();
361  if (punit->name.isEmpty()) {
362  // TRANS: "Unit: <unit type> #<unit id>
363  unit_description = QString(_("%1 #%2"))
364  .arg(utype_name_translation(ptype))
365  .arg(punit->id);
366  } else {
367  // TRANS: "Unit: <unit type> #<unit id> "<unit name>"
368  unit_description = QString(_("%1 #%2 \"%3\""))
369  .arg(utype_name_translation(ptype))
370  .arg(punit->id)
371  .arg(punit->name);
372  }
373 
374  if (!client_player() || owner == client_player()) {
375  struct city *hcity = player_city_by_number(owner, punit->homecity);
376 
377  str += QString(_("Unit: %1 | %2 (%3)"))
378  .arg(unit_description)
379  .arg(username)
380  .arg(nation)
381  + qendl();
382 
383  if (game.info.citizen_nationality
384  && unit_nationality(punit) != unit_owner(punit)) {
385  if (hcity != nullptr) {
386  /* TRANS: on own line immediately following \n, "from <city> |
387  * <nationality> people" */
388  str +=
389  QString(_("from %1 | %2 people"))
390  .arg(city_name_get(hcity),
392  + qendl();
393  } else {
394  /* TRANS: Nationality of the people comprising a unit, if
395  * different from owner. */
396  str +=
397  QString(_("%1 people"))
399  + qendl();
400  }
401  } else if (hcity != nullptr) {
402  // TRANS: on own line immediately following \n, ... <city>
403  str += QString(_("from %1")).arg(city_name_get(hcity)) + qendl();
404  }
405  } else if (nullptr != owner) {
406  struct player_diplstate *ds =
408  if (ds->type == DS_CEASEFIRE) {
409  int turns = ds->turns_left;
410 
411  /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
412  * <number> turn cease-fire)" */
413  str += QString(PL_("Unit: %1 | %2 (%3, %4 turn cease-fire)",
414  "Unit: %1 | %2 (%3, %4 turn cease-fire)", turns))
415  .arg(unit_description, username, nation,
416  QString::number(turns))
417  + qendl();
418  } else if (ds->type == DS_ARMISTICE) {
419  int turns = ds->turns_left;
420 
421  /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
422  * <number> turn armistice)" */
423  str += QString(PL_("Unit: %1 | %2 (%3, %4 turn armistice)",
424  "Unit: %1 | %2 (%3, %4 turn armistice)", turns))
425  .arg(unit_description, username, nation,
426  QString::number(turns))
427  + qendl();
428  } else {
429  /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
430  * <diplomatic state>)" */
431  str += QString(_("Unit: %1 | %2 (%3, %4)"))
432  .arg(unit_description, username, nation,
433  diplo_city_adjectives[ds->type])
434  + qendl();
435  }
436  }
437 
438  for (const auto pfocus_unit : get_units_in_focus()) {
439  int att_chance = FC_INFINITY, def_chance = FC_INFINITY;
440  bool found = false;
441 
442  unit_list_iterate(ptile->units, tile_unit)
443  {
444  if (unit_owner(tile_unit) != unit_owner(pfocus_unit)) {
445  int att = unit_win_chance(pfocus_unit, tile_unit) * 100;
446  int def = (1.0 - unit_win_chance(tile_unit, pfocus_unit)) * 100;
447 
448  found = true;
449 
450  // Presumably the best attacker and defender will be used.
451  att_chance = MIN(att, att_chance);
452  def_chance = MIN(def, def_chance);
453  }
454  }
456 
457  if (found) {
458  // TRANS: "Chance to win: A:95% D:46%"
459  str += QString(_("Chance to win: A:%1% D:%2%"))
460  .arg(QString::number(att_chance),
461  QString::number(def_chance))
462  + qendl();
463  }
464  }
465 
466  // TRANS: Unknown MP left
467  QString mp_left = _("?");
468  if (!client_player() || owner == client_player()) {
469  mp_left = move_points_text_full(punit->moves_left, false, nullptr,
470  nullptr, false);
471  }
472  /* TRANS: A is attack power, D is defense power, FP is firepower,
473  * HP is hitpoints (current and max). */
474  QString max_mp = move_points_text_full(unit_move_rate(punit), false,
475  nullptr, nullptr, false);
476  str += QString(_("A:%1 D:%2 FP:%3 HP:%4/%5 MP:%6 of %7"))
477  .arg(QString::number(ptype->attack_strength),
478  QString::number(ptype->defense_strength),
479  QString::number(ptype->firepower),
480  QString::number(punit->hp), QString::number(ptype->hp),
481  mp_left, max_mp);
482  {
483  const char *veteran_name =
485  if (veteran_name) {
486  str += QStringLiteral(" (%1)").arg(veteran_name);
487  }
488  }
489  str += qendl();
490 
491  if (!is_action_possible_on_unit(ACTION_SPY_BRIBE_UNIT, punit)) {
492  str += _("Bribing not possible.") + qendl();
493  } else if (unit_owner(punit) == client_player()
495  // Show bribe cost for own units.
496  str += QString(_("Probable bribe cost: %1"))
497  .arg(QString::number(unit_bribe_cost(punit, nullptr)))
498  + qendl();
499  } else {
500  // We can only give an (lower) boundary for units of other players.
501  str +=
502  QString(_("Estimated bribe cost: > %1"))
503  .arg(QString::number(unit_bribe_cost(punit, client_player())))
504  + qendl();
505  }
506 
507  if ((nullptr == client.conn.playing || owner == client.conn.playing)
508  && unit_list_size(ptile->units) >= 2) {
509  // TRANS: "5 more" units on this tile
510  str += QString(_(" (%1 more)"))
511  .arg(QString::number(unit_list_size(ptile->units) - 1));
512  }
513  }
514 
515  return str.trimmed();
516 }
517 
518 #define FAR_CITY_SQUARE_DIST (2 * (6 * 6))
522 const QString get_nearest_city_text(struct city *pcity, int sq_dist)
523 {
524  if (!pcity) {
525  sq_dist = -1;
526  }
527  QString str =
528  QString((sq_dist >= FAR_CITY_SQUARE_DIST)
529  // TRANS: on own line immediately following \n, ... <city>
530  ? _("far from %1")
531  : (sq_dist > 0)
532  /* TRANS: on own line immediately following \n, ...
533  <city> */
534  ? _("near %1")
535  : (sq_dist == 0)
536  /* TRANS: on own line immediately following \n,
537  ... <city> */
538  ? _("in %1")
539  : "%1")
540  .arg(pcity ? city_name_get(pcity) : "");
541  return str.trimmed();
542 }
543 
551 const QString unit_description(const unit *punit)
552 {
553  int pcity_near_dist;
554  struct player *owner = unit_owner(punit);
555  struct player *nationality = unit_nationality(punit);
556  struct city *pcity = player_city_by_number(owner, punit->homecity);
557  struct city *pcity_near = get_nearest_city(punit, &pcity_near_dist);
558  const struct unit_type *ptype = unit_type_get(punit);
559  const struct player *pplayer = client_player();
560  QString str = QStringLiteral("%1").arg(utype_name_translation(ptype));
561  const char *veteran_name =
563  if (veteran_name) {
564  str += QStringLiteral("( %1)").arg(veteran_name);
565  }
566 
567  if (pplayer == owner) {
568  unit_upkeep_astr(punit, str);
569  } else {
570  str += qendl();
571  }
572  unit_activity_astr(punit, str);
573 
574  if (pcity) {
575  // TRANS: on own line immediately following \n, ... <city>
576  str += QString(_("from %1")).arg(city_name_get(pcity)) + qendl();
577  } else {
578  str += qendl();
579  }
580  if (game.info.citizen_nationality) {
581  if (nationality != nullptr && owner != nationality) {
582  /* TRANS: Nationality of the people comprising a unit, if
583  * different from owner. */
584  str += QString(_("%1 people"))
585  .arg(nation_adjective_for_player(nationality))
586  + qendl();
587  } else {
588  str += qendl();
589  }
590  }
591  str += QStringLiteral("%1").arg(
592  get_nearest_city_text(pcity_near, pcity_near_dist))
593  + qendl();
594 #ifdef FREECIV_DEBUG
595  str += QStringLiteral("Unit ID: %1").arg(punit->id);
596 #endif
597 
598  return str.trimmed();
599 }
600 
612 const QString get_airlift_text(const std::vector<unit *> &units,
613  const struct city *pdest)
614 {
615  QString str;
616  bool src = (pdest == nullptr);
617  enum texttype {
618  AL_IMPOSSIBLE,
619  AL_UNKNOWN,
620  AL_FINITE,
621  AL_INFINITE
622  } best = AL_IMPOSSIBLE;
623  int cur = 0, max = 0;
624 
625  for (const auto punit : units) {
626  enum texttype tthis = AL_IMPOSSIBLE;
627  enum unit_airlift_result result;
628 
629  // nullptr will tell us about the capability of airlifting from source
630  result = test_unit_can_airlift_to(client_player(), punit, pdest);
631 
632  switch (result) {
633  case AR_NO_MOVES:
634  case AR_WRONG_UNITTYPE:
635  case AR_OCCUPIED:
636  case AR_NOT_IN_CITY:
637  case AR_BAD_SRC_CITY:
638  case AR_BAD_DST_CITY:
639  // No chance of an airlift.
640  tthis = AL_IMPOSSIBLE;
641  break;
642  case AR_OK:
643  case AR_OK_SRC_UNKNOWN:
644  case AR_OK_DST_UNKNOWN:
645  case AR_SRC_NO_FLIGHTS:
646  case AR_DST_NO_FLIGHTS:
647  /* May or may not be able to airlift now, but there's a chance we could
648  * later */
649  {
650  const struct city *pcity = src ? tile_city(unit_tile(punit)) : pdest;
651 
652  fc_assert_ret_val(pcity != nullptr, fc_strdup("-"));
653  if (!src
654  && (game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
655  /* No restrictions on destination (and we can infer this even for
656  * other players' cities). */
657  tthis = AL_INFINITE;
658  } else if (client_player() == city_owner(pcity)) {
659  // A city we know about.
660  int this_cur = pcity->airlift, this_max = city_airlift_max(pcity);
661 
662  if (this_max <= 0) {
663  // City known not to be airlift-capable.
664  tthis = AL_IMPOSSIBLE;
665  } else {
666  if (src
667  && (game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
668  // Unlimited capacity.
669  tthis = AL_INFINITE;
670  } else {
671  // Limited capacity (possibly zero right now).
672  tthis = AL_FINITE;
673  /* Store the numbers. This whole setup assumes that numeric
674  * capacity isn't unit-dependent. */
675  if (best == AL_FINITE) {
676  fc_assert(cur == this_cur && max == this_max);
677  }
678  cur = this_cur;
679  max = this_max;
680  }
681  }
682  } else {
683  // Unknown capacity.
684  tthis = AL_UNKNOWN;
685  }
686  }
687  break;
688  }
689 
690  // Now take the most optimistic view.
691  best = MAX(best, tthis);
692  }
693 
694  switch (best) {
695  case AL_IMPOSSIBLE:
696  return nullptr;
697  case AL_UNKNOWN:
698  str = QStringLiteral("?");
699  break;
700  case AL_FINITE:
701  str = QStringLiteral("%1/%2").arg(cur, max);
702  break;
703  case AL_INFINITE:
704  str = _("Yes");
705  break;
706  }
707 
708  return str.trimmed();
709 }
710 
714 int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs)
715 {
716  const struct research *presearch;
717  int ours = 0, theirs = 0;
718  bool team = false;
719 
720  if (!client_has_player()) {
721  return 0;
722  }
723  presearch = research_get(client_player());
724 
725  // Sum up science
726  research_players_iterate(presearch, pplayer)
727  {
728  if (pplayer == client_player()) {
729  city_list_iterate(pplayer->cities, pcity)
730  {
731  ours += pcity->surplus[O_SCIENCE];
732  }
734  } else {
735  team = true;
736  theirs -= pplayer->client.tech_upkeep;
737  }
738  }
740 
741  if (team) {
742  theirs += presearch->client.total_bulbs_prod - ours;
743  }
744  ours -= client_player()->client.tech_upkeep;
745 
746  if (pours) {
747  *pours = ours;
748  }
749  if (pteam) {
750  *pteam = team;
751  }
752  if (ptheirs) {
753  *ptheirs = theirs;
754  }
755  return ours + theirs;
756 }
757 
761 int turns_to_research_done(const struct research *presearch, int per_turn)
762 {
763  // Can be negative if the tech cost went down due to tech leak.
764  int missing =
765  presearch->client.researching_cost - presearch->bulbs_researched;
766  if (missing <= per_turn) {
767  // Tech will be researched at TC.
768  return 1;
769  } else if (per_turn > 0) {
770  return std::ceil(static_cast<double>(missing) / per_turn);
771  } else {
772  return -1;
773  }
774 }
775 
780 static int turns_per_advance(const struct research *presearch, int per_turn)
781 {
782  if (per_turn > 0) {
783  return MAX(1,
784  ceil((double) presearch->client.researching_cost) / per_turn);
785  } else {
786  return -1;
787  }
788 }
789 
794 static int turns_to_tech_loss(const struct research *presearch, int per_turn)
795 {
796  if (per_turn >= 0 || game.info.techloss_forgiveness == -1) {
797  /* With techloss_forgiveness == -1, we'll never lose a tech, just
798  * get further into debt. */
799  return -1;
800  } else {
801  int bulbs_to_loss = presearch->bulbs_researched
802  + (presearch->client.researching_cost
803  * game.info.techloss_forgiveness / 100);
804 
805  return ceil(static_cast<double>(bulbs_to_loss) / -per_turn);
806  }
807 }
808 
812 const QString science_dialog_text()
813 {
814  bool team;
815  int ours, theirs, perturn, upkeep;
816  QString str, ourbuf, theirbuf;
817  struct research *research;
818 
819  perturn = get_bulbs_per_turn(&ours, &team, &theirs);
820 
822  upkeep = client_player()->client.tech_upkeep;
823 
824  if (nullptr == client.conn.playing
825  || (ours == 0 && theirs == 0 && upkeep == 0)) {
826  return _("Progress: no research");
827  }
828 
829  if (A_UNSET == research->researching) {
830  str = _("Progress: no research");
831  } else {
832  int turns;
833 
834  if ((turns = turns_per_advance(research, perturn)) >= 0) {
835  str += QString(PL_("Progress: %1 turn/advance",
836  "Progress: %1 turns/advance", turns))
837  .arg(turns);
838  } else if ((turns = turns_to_tech_loss(research, perturn)) >= 0) {
839  /* FIXME: turns to next loss is not a good predictor of turns to
840  * following loss, due to techloss_restore etc. But it'll do. */
841  str += QString(PL_("Progress: %1 turn/advance loss",
842  "Progress: %1 turns/advance loss", turns))
843  .arg(turns);
844  } else {
845  // no forward progress -- no research, or tech loss disallowed
846  if (perturn < 0) {
847  str += QString(_("Progress: decreasing!"));
848  } else {
849  str += QString(_("Progress: none"));
850  }
851  }
852  }
853  ourbuf = QString(PL_("%1 bulb/turn", "%1 bulbs/turn", ours)).arg(ours);
854  if (team) {
855  /* TRANS: This is appended to "%d bulb/turn" text */
856  theirbuf = QString(PL_(", %1 bulb/turn from team",
857  ", %1 bulbs/turn from team", theirs))
858  .arg(theirs);
859  } else {
860  theirbuf = QLatin1String("");
861  }
862  str += QStringLiteral(" (%1%2)").arg(ourbuf, theirbuf);
863 
864  if (game.info.tech_upkeep_style != TECH_UPKEEP_NONE) {
865  // perturn is defined as: (bulbs produced) - upkeep
866  str += qendl();
867  str += QString(_("Bulbs produced per turn: %1"))
868  .arg(QString::number(perturn + upkeep));
869  /* TRANS: keep leading space; appended to "Bulbs produced per turn: %d"
870  */
871  str += QString(_(" (needed for technology upkeep: %1)"))
872  .arg(QString::number(upkeep));
873  }
874 
875  return str.trimmed();
876 }
877 
887 const QString get_science_target_text()
888 {
890  QString str;
891 
892  if (!research) {
893  return QStringLiteral("-");
894  }
895 
896  if (research->researching == A_UNSET) {
897  str = QString(_("%1/- (never)"))
898  .arg(QString::number(research->bulbs_researched));
899  } else {
900  int total = research->client.researching_cost;
901  int done = research->bulbs_researched;
902  int perturn = get_bulbs_per_turn(nullptr, nullptr, nullptr);
903  int turns;
904 
905  if ((turns = turns_to_research_done(research, perturn)) >= 0) {
906  str = QString(PL_("%1/%2 (%3 turn)", "%1/%2 (%3 turns)", turns))
907  .arg(QString::number(done), QString::number(total),
908  QString::number(turns));
909  } else if ((turns = turns_to_tech_loss(research, perturn)) >= 0) {
910  str = QString(PL_("%1/%2 (%3 turn to loss)",
911  "%1/%2 (%3 turns to loss)", turns))
912  .arg(QString::number(done), QString::number(total),
913  QString::number(turns));
914  } else {
915  // no forward progress -- no research, or tech loss disallowed
916  str = QString(_("%1/%2 (never)"))
917  .arg(QString::number(done), QString::number(total));
918  }
919  }
920 
921  return str.trimmed();
922 }
923 
928 {
929  const struct research *research = research_get(client_player());
930  if (!research) {
931  return QStringLiteral("-");
932  }
933 
934  if (!valid_advance_by_number(goal)) {
935  // No goal - act as if it were the current research
936  goal = research->researching;
937  }
938 
939  int steps = research_goal_unknown_techs(research, goal);
940  int bulbs_needed = research_goal_bulbs_required(research, goal);
941  int perturn = get_bulbs_per_turn(nullptr, nullptr, nullptr);
942 
944  || research->researching == goal) {
945  bulbs_needed -= research->bulbs_researched;
946  // Adjust for the actual cost of the current tech (e.g. due to tech leak)
947  bulbs_needed -=
949  bulbs_needed += research->client.researching_cost;
950  }
951 
952  int turns = -1;
953  if (bulbs_needed < perturn) {
954  turns = 1;
955  } else if (perturn > 0) {
956  turns = (bulbs_needed + perturn - 1) / perturn;
957  }
958 
959  QString buf1, buf2, buf3;
960  buf1 =
961  QString(PL_("%1 step", "%1 steps", steps)).arg(QString::number(steps));
962  buf2 = QString(PL_("%1 bulb", "%1 bulbs", bulbs_needed))
963  .arg(QString::number(bulbs_needed));
964 
965  if (turns >= 0) {
966  buf3 = QString(PL_("%1 turn", "%1 turns", turns))
967  .arg(QString::number(turns));
968  } else {
969  buf3 = QString(_("never"));
970  }
971 
972  return QStringLiteral("(%1 - %2 - %3)").arg(buf1, buf2, buf3);
973 }
974 
981 const QString get_info_label_text(bool moreinfo)
982 {
983  QString str;
984 
985  if (nullptr != client.conn.playing) {
986  str = QString(_("Population: %1"))
988  + qendl();
989  }
990  str += QString(_("Year: %1 (T%2)"))
991  .arg(calendar_text(), QString::number(game.info.turn))
992  + qendl();
993 
994  if (nullptr != client.conn.playing) {
995  str += QString(_("Gold: %1 (%2)"))
996  .arg(QString::number(client.conn.playing->economic.gold),
997  QString::number(
999  + qendl();
1000  str += QString(_("Tax: %1 Lux: %2 Sci: %3"))
1001  .arg(QString::number(client.conn.playing->economic.tax),
1002  QString::number(client.conn.playing->economic.luxury),
1003  QString::number(client.conn.playing->economic.science))
1004  + qendl();
1005  }
1006  if (game.info.phase_mode == PMT_PLAYERS_ALTERNATE) {
1007  if (game.info.phase < 0 || game.info.phase >= player_count()) {
1008  str += QString(_("Moving: Nobody")) + qendl();
1009  } else {
1010  str += QString(_("Moving: %1"))
1011  .arg(player_name(player_by_number(game.info.phase)))
1012  + qendl();
1013  }
1014  } else if (game.info.phase_mode == PMT_TEAMS_ALTERNATE) {
1015  if (game.info.phase < 0 || game.info.phase >= team_count()) {
1016  str += QString(_("Moving: Nobody")) + qendl();
1017  } else {
1018  str += QString(_("Moving: %1"))
1020  + qendl();
1021  }
1022  }
1023 
1024  if (moreinfo) {
1025  str += QString(_("(Click for more info)")) + qendl();
1026  }
1027 
1028  return str.trimmed();
1029 }
1030 
1037 {
1038  QString str;
1039 
1040  if (nullptr != client.conn.playing) {
1041  str = QString(_("%1 People"))
1043  + qendl();
1044  }
1045  str += QString(_("Year: %1")).arg(calendar_text()) + qendl();
1046  str +=
1047  QString(_("Turn: %1")).arg(QString::number(game.info.turn)) + qendl();
1048 
1049  if (nullptr != client.conn.playing) {
1050  const struct research *presearch = research_get(client_player());
1051  int perturn = get_bulbs_per_turn(nullptr, nullptr, nullptr);
1052  int upkeep = client_player()->client.tech_upkeep;
1053 
1054  str += QString(_("Gold: %1"))
1055  .arg(QString::number(client.conn.playing->economic.gold))
1056  + qendl();
1057  str += QString(_("Net Income: %1"))
1058  .arg(QString::number(
1060  + qendl();
1061  // TRANS: Gold, luxury, and science rates are in percentage values.
1062  str += QString(_("National budget: Gold:%1% Luxury:%2% Science:%3%"))
1063  .arg(QString::number(client.conn.playing->economic.tax),
1064  QString::number(client.conn.playing->economic.luxury),
1065  QString::number(client.conn.playing->economic.science))
1066  + qendl();
1067 
1068  str += QString(_("Researching %1: %2"))
1070  presearch, presearch->researching),
1072  + qendl();
1073  // perturn is defined as: (bulbs produced) - upkeep
1074  if (game.info.tech_upkeep_style != TECH_UPKEEP_NONE) {
1075  str += QString(_("Bulbs per turn: %1 - %2 = %3"))
1076  .arg(QString::number(perturn + upkeep),
1077  QString::number(upkeep), QString::number(perturn))
1078  + qendl();
1079  } else {
1080  fc_assert(upkeep == 0);
1081  str += QString(_("Bulbs per turn: %1")).arg(QString::number(perturn))
1082  + qendl();
1083  }
1084  {
1085  int history_perturn = nation_history_gain(client.conn.playing);
1087  {
1088  history_perturn += city_history_gain(pcity);
1089  }
1091  str += QString(_("Culture: %1 (%2/turn)"))
1092  .arg(QString::number(client.conn.playing->client.culture),
1093  QString::number(history_perturn))
1094  + qendl();
1095  }
1096  }
1097 
1098  if (game.info.global_warming) {
1099  int chance, rate;
1100  global_warming_scaled(&chance, &rate, 100);
1101  str += QString(_("Global warming chance: %1% (%2%/turn)"))
1102  .arg(QString::number(chance), QString::number(rate))
1103  + qendl();
1104  } else {
1105  str += QString(_("Global warming deactivated.")) + qendl();
1106  }
1107 
1108  if (game.info.nuclear_winter) {
1109  int chance, rate;
1110  nuclear_winter_scaled(&chance, &rate, 100);
1111  str += QString(_("Nuclear winter chance: %1% (%2%/turn)"))
1112  .arg(QString::number(chance), QString::number(rate))
1113  + qendl();
1114  } else {
1115  str += QString(_("Nuclear winter deactivated.")) + qendl();
1116  }
1117 
1118  if (nullptr != client.conn.playing) {
1119  str += QString(_("Government: %1"))
1121  + qendl();
1122  }
1123 
1124  return str.trimmed();
1125 }
1126 
1132 bool get_units_upgrade_info(char *buf, size_t bufsz,
1133  const std::vector<unit *> &punits)
1134 {
1135  if (punits.empty()) {
1136  fc_snprintf(buf, bufsz, _("No units to upgrade!"));
1137  return false;
1138  } else if (punits.size() == 1) {
1139  return (UU_OK == unit_upgrade_info(punits.front(), buf, bufsz));
1140  } else {
1141  int upgrade_cost = 0;
1142  int num_upgraded = 0;
1143  int min_upgrade_cost = FC_INFINITY;
1144 
1145  for (const auto punit : punits) {
1146  if (unit_owner(punit) == client_player()
1147  && UU_OK == unit_upgrade_test(punit, false)) {
1148  const struct unit_type *from_unittype = unit_type_get(punit);
1149  const struct unit_type *to_unittype =
1150  can_upgrade_unittype(client.conn.playing, from_unittype);
1151  int cost = unit_upgrade_price(unit_owner(punit), from_unittype,
1152  to_unittype);
1153 
1154  num_upgraded++;
1155  upgrade_cost += cost;
1156  min_upgrade_cost = MIN(min_upgrade_cost, cost);
1157  }
1158  }
1159  if (num_upgraded == 0) {
1160  fc_snprintf(buf, bufsz, _("None of these units may be upgraded."));
1161  return false;
1162  } else {
1163  /* This may trigger sometimes if you don't have enough money for
1164  * a full upgrade. If you have enough to upgrade at least one, it
1165  * will do it. */
1166  /* Construct prompt in several parts to allow separate pluralisation
1167  * by localizations */
1168  char tbuf[MAX_LEN_MSG], ubuf[MAX_LEN_MSG];
1169  fc_snprintf(tbuf, ARRAY_SIZE(tbuf),
1170  PL_("Treasury contains %d gold.",
1171  "Treasury contains %d gold.",
1172  client_player()->economic.gold),
1173  client_player()->economic.gold);
1174  /* TRANS: this whole string is a sentence fragment that is only ever
1175  * used by including it in another string (search comments for this
1176  * string to find it) */
1177  fc_snprintf(ubuf, ARRAY_SIZE(ubuf),
1178  PL_("Upgrade %d unit", "Upgrade %d units", num_upgraded),
1179  num_upgraded);
1180  /* TRANS: This is complicated. The first %s is a pre-pluralised
1181  * sentence fragment "Upgrade %d unit(s)"; the second is pre-pluralised
1182  * "Treasury contains %d gold." So the whole thing reads
1183  * "Upgrade 13 units for 1000 gold?\nTreasury contains 2000 gold." */
1184  fc_snprintf(
1185  buf, bufsz,
1186  PL_("%s for %d gold?\n%s", "%s for %d gold?\n%s", upgrade_cost),
1187  ubuf, upgrade_cost, tbuf);
1188  return true;
1189  }
1190  }
1191 }
1192 
1197 const QString get_spaceship_descr(struct player_spaceship *pship)
1198 {
1199  struct player_spaceship ship;
1200  QString str;
1201 
1202  if (!pship) {
1203  pship = &ship;
1204  memset(&ship, 0, sizeof(ship));
1205  }
1206  // TRANS: spaceship text; should have constant width.
1207  str += QString(_("Population: %1"))
1208  .arg(QString::number(pship->population))
1209  + qendl();
1210  // TRANS: spaceship text; should have constant width.
1211  str += QString(_("Support: %1 %"))
1212  .arg(QString::number(
1213  static_cast<int>(pship->support_rate * 100.0)))
1214  + qendl();
1215  // TRANS: spaceship text; should have constant width.
1216  str +=
1217  QString(_("Energy: %1 %"))
1218  .arg(QString::number(static_cast<int>(pship->energy_rate * 100.0)))
1219  + qendl();
1220  // TRANS: spaceship text; should have constant width.
1221  str += QString(PL_("Mass: %1 ton", "Mass: %1 tons",
1222  pship->mass))
1223  .arg(QString::number(pship->mass))
1224  + qendl();
1225  if (pship->propulsion > 0) {
1226  // TRANS: spaceship text; should have constant width.
1227  str += QString(_("Travel time: %1 years"))
1228  .arg(QString::number(static_cast<float>(
1229  0.1 * (static_cast<int>(pship->travel_time * 10.0)))))
1230  + qendl();
1231  } else {
1232  // TRANS: spaceship text; should have constant width.
1233  str += QStringLiteral("%1").arg(_("Travel time: N/A "))
1234  + qendl();
1235  }
1236  // TRANS: spaceship text; should have constant width.
1237  str += QString(_("Success prob.: %1 %"))
1238  .arg(QString::number(
1239  static_cast<int>(pship->success_rate * 100.0)))
1240  + qendl();
1241  // TRANS: spaceship text; should have constant width.
1242  str += QString(_("Year of arrival: %1"))
1243  .arg((pship->state == SSHIP_LAUNCHED)
1244  ? textyear((pship->launch_year
1245  + static_cast<int>(pship->travel_time)))
1246  : "- ")
1247  + qendl();
1248 
1249  return str.trimmed();
1250 }
1251 
1256 QString get_score_text(const struct player *pplayer)
1257 {
1258  QString str;
1259 
1260  if (pplayer->score.game > 0 || nullptr == client.conn.playing
1261  || pplayer == client.conn.playing) {
1262  str = QStringLiteral("%1").arg(QString::number(pplayer->score.game));
1263  } else {
1264  str = QStringLiteral("?");
1265  }
1266 
1267  return str.trimmed();
1268 }
1269 
1274 const QString get_act_sel_action_custom_text(struct action *paction,
1275  const struct act_prob prob,
1276  const struct unit *actor_unit,
1277  const struct city *target_city)
1278 {
1279  struct city *actor_homecity = unit_home(actor_unit);
1280  QString custom;
1281  if (!action_prob_possible(prob)) {
1282  // No info since impossible.
1283  return nullptr;
1284  }
1285 
1286  fc_assert_ret_val((action_get_target_kind(paction) != ATK_CITY
1287  || target_city != nullptr),
1288  nullptr);
1289 
1290  if (action_has_result(paction, ACTRES_TRADE_ROUTE)) {
1291  int revenue = get_caravan_enter_city_trade_bonus(
1292  actor_homecity, target_city, client_player(), actor_unit->carrying,
1293  true);
1294 
1295  custom = QString(
1296  /* TRANS: Estimated one time bonus and recurring revenue for
1297  * the Establish Trade _Route action. */
1298  _("%1 one time bonus + %2 trade"))
1299  .arg(QString::number(revenue),
1300  QString::number(trade_base_between_cities(
1301  actor_homecity, target_city)));
1302  } else if (action_has_result(paction, ACTRES_MARKETPLACE)) {
1303  int revenue = get_caravan_enter_city_trade_bonus(
1304  actor_homecity, target_city, client_player(), actor_unit->carrying,
1305  false);
1306 
1307  custom = QString(
1308  /* TRANS: Estimated one time bonus for the Enter Marketplace
1309  * action. */
1310  _("%1 one time bonus"))
1311  .arg(QString::number(revenue));
1312  } else if ((action_has_result(paction, ACTRES_HELP_WONDER)
1313  || action_has_result(paction, ACTRES_RECYCLE_UNIT))
1314  && city_owner(target_city) == client.conn.playing) {
1315  /* Can only give remaining production for domestic and existing
1316  * cities. */
1317  int cost = city_production_build_shield_cost(target_city);
1318  custom = QString(_("%1 remaining"))
1319  .arg(QString::number(cost - target_city->shield_stock));
1320  } else {
1321  // No info to add.
1322  return nullptr;
1323  }
1324 
1325  return custom;
1326 }
1327 
1333 const QString act_sel_action_tool_tip(const struct action *paction,
1334  const struct act_prob prob)
1335 {
1336  Q_UNUSED(paction)
1337  return action_prob_explain(prob);
1338 }
1339 
1340 namespace /* anonymous */ {
1341 
1345 QString text_happiness_effect_details(const city *pcity, effect_type effect)
1346 {
1347  auto effects = effect_list_new();
1348  get_city_bonus_effects(effects, pcity, nullptr, effect);
1349 
1350  // TRANS: Precedes a list of active effects, pluralized on its length.
1351  QString str = PL_(
1352  "The following contribution is active:",
1353  "The following contributions are active:", effect_list_size(effects));
1354  str += QStringLiteral("<ul>");
1355 
1356  char help_text_buffer[MAX_LEN_PACKET];
1357 
1358  effect_list_iterate(effects, peffect)
1359  {
1360  str += QStringLiteral("<li>");
1361  if (requirement_vector_size(&peffect->reqs) == 0) {
1362  // TRANS: Describes an effect without requirements; %1 is its value
1363  str += QString(_("%1 by default"))
1364  .arg(effect_type_unit_text(peffect->type, peffect->value));
1365  } else {
1366  help_text_buffer[0] = '\0';
1367  get_effect_req_text(peffect, help_text_buffer,
1368  sizeof(help_text_buffer));
1369  // TRANS: Describes an effect; %1 is its value and %2 the requirements
1370  str += QString(_("%1 from %2"))
1371  .arg(effect_type_unit_text(peffect->type, peffect->value))
1372  .arg(help_text_buffer);
1373  }
1374  str += QStringLiteral("</li>");
1375  }
1377  effect_list_destroy(effects);
1378 
1379  str += QStringLiteral("</ul>");
1380 
1381  return str;
1382 }
1383 } // anonymous namespace
1384 
1389 QString text_happiness_buildings(const struct city *pcity)
1390 {
1391  if (const auto effects = get_effects(EFT_MAKE_CONTENT);
1392  effect_list_size(effects) == 0) {
1393  return QString(); // Disabled in the ruleset.
1394  }
1395 
1396  auto str = QStringLiteral("<p>");
1397  str += _("Infrastructure can have an effect on citizen happiness.");
1398  str += QStringLiteral(" ");
1399 
1400  int bonus = get_city_bonus(pcity, EFT_MAKE_CONTENT);
1401  if (bonus <= 0) {
1402  // TRANS: Comes after "Infrastructure can have an effect on citizen
1403  // happiness"
1404  str += _("This city doesn't receive any such bonus.");
1405  return str + QStringLiteral("</p>");
1406  }
1407 
1408  // TRANS: Comes after "Infrastructure can have an effect on citizen
1409  // happiness"
1410  str +=
1411  QString(
1412  PL_("In this city, it can make up to <b>%1 citizen<b> content.",
1413  "In this city, it can make up to <b>%1 citizens<b> content.",
1414  bonus))
1415  .arg(bonus);
1416 
1417  // Add a list of active effects
1418  str += QStringLiteral("</p><p>");
1419  str += text_happiness_effect_details(pcity, EFT_MAKE_CONTENT);
1420 
1421  return str + QStringLiteral("</ul></p>");
1422 }
1423 
1427 QString text_happiness_nationality(const struct city *pcity)
1428 {
1429  if (auto effects = get_effects(EFT_ENEMY_CITIZEN_UNHAPPY_PCT);
1430  !game.info.citizen_nationality || effect_list_size(effects) == 0) {
1431  // Disabled in the ruleset
1432  return QString();
1433  }
1434 
1435  auto str = QStringLiteral("<p>");
1436  str +=
1437  _("The presence of enemy citizens can create additional unhappiness.");
1438  str += QStringLiteral(" ");
1439 
1440  int pct = get_city_bonus(pcity, EFT_ENEMY_CITIZEN_UNHAPPY_PCT);
1441  if (pct == 0) {
1442  str += _("However, it is not the case in this city.");
1443  return str + QStringLiteral("</p>");
1444  }
1445 
1446  // This is not exactly correct, but gives a first idea.
1447  int num = std::ceil(100. / pct);
1448  str += QString(PL_("For every %1 citizen of an enemy nation, one citizen "
1449  "becomes unhappy.",
1450  "For every %1 citizens of an enemy nation, one citizen "
1451  "becomes unhappy.",
1452  num))
1453  .arg(num);
1454  str += QStringLiteral("</p><p>");
1455 
1456  int enemies = 0;
1457  const auto owner = city_owner(pcity);
1458  citizens_foreign_iterate(pcity, pslot, nationality)
1459  {
1460  if (pplayers_at_war(owner, player_slot_get_player(pslot))) {
1461  enemies += nationality;
1462  }
1463  }
1465 
1466  if (enemies == 0) {
1467  str += _("There is <b>no enemy citizen</b> in this city.");
1468  } else {
1469  auto unhappy = enemies * pct / 100;
1470  // TRANS: "There is 1 enemy citizen in this city, resulting in <b>2
1471  // additional unhappy citizens.</b>" (first half)
1472  str +=
1473  QString(PL_("There is %1 enemy citizen in this city, ",
1474  "There are %1 enemy citizens in this city, ", enemies))
1475  .arg(enemies);
1476  // TRANS: "There is 1 enemy citizen in this city, resulting in <b>2
1477  // additional unhappy citizens.</b>" (second half)
1478  str += QString(PL_("resulting in <b>%1 additional unhappy citizen.</b>",
1479  "resulting in <b>%1 additional unhappy citizens.</b>",
1480  unhappy))
1481  .arg(unhappy);
1482  }
1483 
1484  return str + QStringLiteral("</p>");
1485 }
1486 
1490 QString text_happiness_wonders(const struct city *pcity)
1491 {
1492  int effects_count = effect_list_size(get_effects(EFT_MAKE_HAPPY))
1493  + effect_list_size(get_effects(EFT_NO_UNHAPPY))
1494  + effect_list_size(get_effects(EFT_FORCE_CONTENT));
1495  if (effects_count == 0) {
1496  // Disabled in the ruleset
1497  return QString();
1498  }
1499 
1500  auto str = QStringLiteral("<p>");
1501  bool wrote_something = false;
1502 
1503  int happy_bonus = get_city_bonus(pcity, EFT_MAKE_HAPPY);
1504  if (happy_bonus > 0) {
1505  if (happy_bonus == 1) {
1506  str += _("Up to one content citizen in this city can be made happy.");
1507  } else {
1508  str +=
1509  QString(
1510  PL_("Up to %1 unhappy or content citizen in this city can be "
1511  "made happy (unhappy citizens count double).",
1512  "Up to %1 unhappy or content citizens in this city "
1513  "can be made happy (unhappy citizens count double).",
1514  happy_bonus))
1515  .arg(happy_bonus);
1516  }
1517 
1518  // Add a list of active effects
1519  str += QStringLiteral("</p><p>");
1520  str += text_happiness_effect_details(pcity, EFT_MAKE_HAPPY);
1521  str += QStringLiteral("</p><p>");
1522  wrote_something = true;
1523  }
1524 
1525  if (get_city_bonus(pcity, EFT_NO_UNHAPPY) > 0) {
1526  str += _("No citizens in this city can ever be unhappy or angry. "
1527  "Any unhappy or angry citizen are automatically made content.");
1528  } else if (int bonus = get_city_bonus(pcity, EFT_FORCE_CONTENT);
1529  bonus > 0) {
1530  str += QStringLiteral("</p><p>");
1531  str +=
1532  QString(PL_("Up to %1 unhappy or angry citizen in this city can be "
1533  "made content.",
1534  "Up to %1 unhappy or angry citizens in this city can be "
1535  "made content.",
1536  bonus))
1537  .arg(bonus);
1538 
1539  // Add a list of active effects
1540  str += QStringLiteral("</p><p>");
1541  str += text_happiness_effect_details(pcity, EFT_FORCE_CONTENT);
1542  wrote_something = true;
1543  }
1544 
1545  if (!wrote_something) {
1546  // Make sure there's always something printed.
1547  str += _("Happiness is currently not changed at this stage.");
1548  }
1549 
1550  return str + QStringLiteral("</p>");
1551 }
1552 
1553 namespace /* anonymous */ {
1554 
1558 QString text_happiness_cities_rules(const player *pplayer, int base_content,
1559  int basis, int step,
1560  bool depends_on_empire_size)
1561 {
1562  auto str = QString();
1563 
1564  bool next_citizens_are_angry = false;
1565  if (base_content == 0) {
1566  str += _("All cities start with all citizens unhappy.");
1567  next_citizens_are_angry = game.info.angrycitizen;
1568  } else {
1569  str += QString(PL_("All cities start with %1 content citizen.",
1570  "All cities start with %1 content citizens.",
1571  base_content))
1572  .arg(base_content);
1573  }
1574  if (depends_on_empire_size) {
1575  if (basis > 0) {
1576  str += QStringLiteral(" ");
1577  if (next_citizens_are_angry) {
1578  str += QString(PL_("Once you have more than %1 city, a citizen "
1579  "becomes angry.",
1580  "Once you have more than %1 cities, a citizen "
1581  "becomes angry.",
1582  basis))
1583  .arg(basis);
1584  } else if (base_content == 1) {
1585  // TRANS: Comes after "All cities start with 1 content citizen."
1586  // "it" is the citizen.
1587  str +=
1588  QString(
1589  PL_("Once you have more than %1 city, it becomes unhappy.",
1590  "Once you have more than %1 cities, it becomes unhappy.",
1591  basis))
1592  .arg(basis);
1593  next_citizens_are_angry = game.info.angrycitizen;
1594  } else if (base_content > 1) {
1595  // TRANS: Comes after "All cities start with N content citizens."
1596  str += QString(PL_("Once you have more than %1 city, a citizen "
1597  "becomes unhappy.",
1598  "Once you have more than %1 cities, a citizen "
1599  "becomes unhappy.",
1600  basis))
1601  .arg(basis);
1602  }
1603  }
1604 
1605  if (step > 0) {
1606  str += QStringLiteral(" ");
1607  if (next_citizens_are_angry) {
1608  str += QString(PL_("Afterwards, for every %1 additional city, a "
1609  "citizen becomes angry.",
1610  "Afterwards, for every %1 additional cities, a "
1611  "citizen becomes angry.",
1612  step))
1613  .arg(step);
1614  } else {
1615  str += QString(PL_("Afterwards, for every %1 additional city, a "
1616  "content citizen becomes unhappy.",
1617  "Afterwards, for every %1 additional cities, a "
1618  "content citizen becomes unhappy.",
1619  step))
1620  .arg(step);
1621 
1622  if (game.info.angrycitizen) {
1623  str += QStringLiteral(" ");
1624  str += _("If there are no more content citizens, an unhappy "
1625  "citizen becomes angry instead.");
1626  }
1627  }
1628  }
1629  }
1630  return str;
1631 }
1632 
1636 QString text_happiness_cities_apply_rules(int cities, int max_content)
1637 {
1638  if (max_content > 0) {
1639  // TRANS: Pluralized in "%2 content citizens"
1640  return QString(PL_("You have %1 cities, resulting in a maximum of %2 "
1641  "content citizen.",
1642  "You have %1 cities, resulting in a maximum of %2 "
1643  "content citizens.",
1644  max_content))
1645  .arg(cities)
1646  .arg(max_content);
1647  } else if (max_content == 0) {
1648  return QString(PL_("You have %1 city, thus all citizens are unhappy.",
1649  "You have %1 cities, thus all citizens are unhappy.",
1650  cities))
1651  .arg(cities);
1652  } else {
1653  // TRANS: Pluralized in "%2 angry citizens"
1654  return QString(PL_("You have %1 cities, resulting in a maximum of "
1655  "%2 angry citizen.",
1656  "You have %1 cities, resulting in a maximum of "
1657  "%2 angry citizens.",
1658  max_content))
1659  .arg(cities)
1660  .arg(-max_content);
1661  }
1662 }
1663 
1667 QString text_happiness_cities_content(int size, int max_content)
1668 {
1669  if (max_content >= size) {
1670  // Very good
1671  return QString(_("In this city of size %1, <b>all citizens are "
1672  "content.</b>"))
1673  .arg(size);
1674  } else if (max_content > 0) {
1675  // Good
1676  // TRANS: Pluralized in "citizens are content"
1677  return QString(
1678  PL_("In this city of size %1, <b>%2 citizen is content.</b>",
1679  "In this city of size %1, <b>%2 citizens are "
1680  "content.</b>",
1681  max_content))
1682  .arg(size)
1683  .arg(max_content);
1684  } else if (max_content == 0) {
1685  // Still ok
1686  return QString(
1687  "In this city of size %1, <b>all citizens are unhappy.</b>")
1688  .arg(size);
1689  } else if (-max_content < size) {
1690  // Somewhat bad
1691  return QString(
1692  PL_(
1693  // TRANS: Pluralized in "citizens are angry"
1694  "In this city of size %1, <b>%2 citizen is angry.</b>",
1695  "In this city of size %1, <b>%2 citizens are angry.</b>",
1696  -max_content))
1697  .arg(size)
1698  .arg(-max_content);
1699  } else {
1700  // Very bad
1701  return QString(
1702  _("In this city of size %1, <b>all citizens are angry.</b>"))
1703  .arg(size);
1704  }
1705 }
1706 
1711 QString text_happiness_more_cities(int base_content, int basis, int step,
1712  int max_content, int size, int cities)
1713 {
1714  // Actual content in this city (negative if there are angry citizens
1715  // instead)
1716  int content = std::min<int>(max_content, size);
1717  if (!game.info.angrycitizen && content < 0) {
1718  content = 0;
1719  }
1720  // How many citizens unhappy about the empire size we'll have when the
1721  // next unhappy appears
1722  int unhappy_for_next_threshold = base_content - content + 1;
1723  // How many cities we'll have when the next unhappy appears
1724  int cities_to_next_threshold =
1725  basis + (unhappy_for_next_threshold - 1) * step + 1;
1726  // ...or how many more we need
1727  cities_to_next_threshold -= cities;
1728 
1729  if (cities_to_next_threshold > 0) {
1730  if (content > 0) {
1731  return QString(PL_("With %1 more city, a content citizen would become "
1732  "unhappy.",
1733  "With %1 more cities, a content citizen would "
1734  "become unhappy.",
1735  cities_to_next_threshold))
1736  .arg(QString::number(cities_to_next_threshold));
1737  } else if (game.info.angrycitizen) {
1738  // We maxed out the number of unhappy citizens, but they can get
1739  // angry instead.
1740  return QString(
1741  PL_("With %1 more city, a citizen would become angry.",
1742  "With %1 more cities, a citizen would become angry.",
1743  cities_to_next_threshold))
1744  .arg(QString::number(cities_to_next_threshold));
1745  }
1746  }
1747  return _("Having more cities would not create more unhappiness.");
1748 }
1749 } // anonymous namespace
1750 
1754 QString text_happiness_cities(const struct city *pcity)
1755 {
1756  struct player *pplayer = city_owner(pcity);
1757  int cities = city_list_size(pplayer->cities);
1758  int base_content = get_player_bonus(pplayer, EFT_CITY_UNHAPPY_SIZE);
1759  int basis = get_player_bonus(pplayer, EFT_EMPIRE_SIZE_BASE);
1760  int step = get_player_bonus(pplayer, EFT_EMPIRE_SIZE_STEP);
1761  bool depends_on_empire_size = (basis + step > 0);
1762 
1763  while (depends_on_empire_size && basis <= 0) {
1764  // In this case, we get one unhappy immediately when we build the first
1765  // city. So it's equivalent to removing one content.
1766  base_content--;
1767  if (step > 0) {
1768  // The first unhappy appears at a different size. Normalize...
1769  basis += step;
1770  } else {
1771  // This was fake! The ruleset author did something strange.
1772  depends_on_empire_size = false;
1773  break;
1774  }
1775  }
1776 
1777  // First explain the rules -- see player_base_citizen_happiness
1778  auto str = QStringLiteral("<p>");
1779  str += text_happiness_cities_rules(pplayer, base_content, basis, step,
1780  depends_on_empire_size);
1781 
1782  // Now add the status of this city.
1783  str += QStringLiteral("</p><p>");
1784  auto max_content = player_base_citizen_happiness(city_owner(pcity));
1785  if (!game.info.angrycitizen) {
1786  // No angry citizens: max_content can't go negative
1787  max_content = CLIP(0, max_content, MAX_CITY_SIZE);
1788  }
1789  // If the penalty is enabled, explain it.
1790  if (depends_on_empire_size) {
1791  str += text_happiness_cities_apply_rules(cities, max_content);
1792  }
1793 
1794  auto size = city_size_get(pcity);
1795  str += QStringLiteral(" ");
1796  str += text_happiness_cities_content(size, max_content);
1797 
1798  // Finally, add something about building more cities.
1799  if (depends_on_empire_size) {
1800  str += QStringLiteral(" ");
1801  str += text_happiness_more_cities(base_content, basis, step, max_content,
1802  size, cities);
1803  }
1804 
1805  return str + QStringLiteral("</p>");
1806 }
1807 
1811 QString text_happiness_units(const struct city *pcity)
1812 {
1813  auto str = QString();
1814 
1815  /*
1816  * First part: martial law
1817  */
1818  int martial_law_max = get_city_bonus(pcity, EFT_MARTIAL_LAW_MAX);
1819  int martial_law_each = get_city_bonus(pcity, EFT_MARTIAL_LAW_EACH);
1820  if (martial_law_each > 0 && martial_law_max >= 0) {
1821  str += QStringLiteral("<p>");
1822  // The rules
1823  if (martial_law_max == 0) {
1824  str += _("Every military unit in the city may impose martial law.");
1825  } else {
1826  str +=
1827  QString(PL_("%1 military unit in the city may impose martial law.",
1828  "Up to %1 military units in the city may impose "
1829  "martial law.",
1830  martial_law_max))
1831  .arg(martial_law_max);
1832  }
1833 
1834  str += QStringLiteral(" ");
1835  str += QString(PL_("Each of them makes %1 unhappy citizen content.",
1836  "Each of them makes %1 unhappy citizens content.",
1837  martial_law_each))
1838  .arg(martial_law_each);
1839 
1840  str += QStringLiteral("</p><p>");
1841 
1842  int count = 0;
1843  unit_list_iterate(pcity->tile->units, punit)
1844  {
1845  if ((count < martial_law_max || martial_law_max == 0)
1846  && is_military_unit(punit)
1847  && unit_owner(punit) == city_owner(pcity)) {
1848  count++;
1849  }
1850  }
1852 
1853  str +=
1854  QString(PL_("%1 military unit in this city imposes the martial law.",
1855  "%1 military units in this city impose the martial law.",
1856  count))
1857  .arg(count);
1858  str += QStringLiteral(" ");
1859  str += QString(PL_("<b>%1 citizen</b> is made happier as a result.",
1860  "<b>%1 citizens</b> are made happier as a result.",
1861  count * martial_law_each))
1862  .arg(count * martial_law_each);
1863 
1864  str += QStringLiteral("</p>");
1865  }
1866 
1867  /*
1868  * Second part: military unhappiness
1869  *
1870  * Had to say anything here because this is unit dependent (and I don't
1871  * want to build a list of unit types or so, this is shown elsewhere).
1872  */
1873  str += QStringLiteral("<p>");
1874 
1875  auto pplayer = city_owner(pcity);
1876  int unhappy_factor = get_player_bonus(pplayer, EFT_UNHAPPY_FACTOR);
1877  if (unhappy_factor == 0) {
1878  str += _("Military units have no happiness effect.");
1879  return str + QStringLiteral("</p>");
1880  }
1881 
1882  str += _("Military units in the field may cause unhappiness.");
1883 
1884  // Special rule: ignore the first N military unhappy
1885  int made_content = get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL);
1886  if (made_content > 0) {
1887  str += QStringLiteral(" ");
1888  str += QString(PL_("With respect to normal, %1 fewer citizen will be "
1889  "unhappy about military units.",
1890  "With respect to normal, %1 fewer citizens will be "
1891  "unhappy about military units.",
1892  made_content))
1893  .arg(made_content);
1894  }
1895 
1896  // Special rule: ignore N military unhappy per unit
1897  // Let's hope ruleset authors don't combine them too often, the sentences
1898  // are very similar.
1899  int made_content_each = get_city_bonus(pcity, EFT_MAKE_CONTENT_MIL_PER);
1900  if (made_content_each > 0) {
1901  str += QStringLiteral(" ");
1902  str += QString(PL_("With respect to normal, %1 fewer citizen will be "
1903  "unhappy per each military unit.",
1904  "With respect to normal, %1 fewer citizens will be "
1905  "unhappy per each military unit.",
1906  made_content_each))
1907  .arg(made_content_each);
1908  }
1909 
1910  // And finally how many unhappy we get in this city
1911  int count = 0, happy_upkeep = 0;
1912  unit_list_iterate(pcity->units_supported, punit)
1913  {
1914  int dummy = 0;
1915  if (auto n = city_unit_unhappiness(punit, &dummy); n > 0) {
1916  count++;
1917  happy_upkeep += n;
1918  }
1919  }
1921 
1922  str += QStringLiteral("</p><p>");
1923  if (count > 0) {
1924  // TRANS: "This city supports %1 agressive military units, resulting in
1925  // up to X unhappy citizens." (first part)
1926  str += QString(PL_("This city supports %1 agressive military unit, ",
1927  "This city supports %1 agressive military units, ",
1928  count))
1929  .arg(count);
1930  // TRANS: "This city supports X agressive military units, resulting in up
1931  // to %1 unhappy citizens." (second part)
1932  str +=
1933  QString(
1934  PL_("resulting in up to <b>%1 additional unhappy citizen.</b>",
1935  "resulting in up to <b>%1 additional unhappy citizens.</b>",
1936  happy_upkeep))
1937  .arg(happy_upkeep);
1938  } else {
1939  str += _("Currently, military units do not cause additional unhappiness "
1940  "in this city.");
1941  }
1942 
1943  return str + QStringLiteral("</p>");
1944 }
1945 
1949 QString text_happiness_luxuries(const struct city *pcity)
1950 {
1951  auto str = QStringLiteral("<p>");
1952 
1953  // Explain the rules
1954  str += QString(_("For each %1 luxury good produced in a city, a citizen "
1955  "becomes happier."))
1956  .arg(game.info.happy_cost);
1957  str += QStringLiteral(" ");
1958 
1959  // Give the basis for calculation. Shortcut the rest if there's not enough
1960  // to help a single citizen.
1961  auto luxuries = pcity->prod[O_LUXURY];
1962  if (luxuries == 0) {
1963  str += _("This city generates no luxury goods.");
1964  return str + QStringLiteral("</p>");
1965  } else if (luxuries < game.info.happy_cost) {
1966  str += QString(PL_("This city generates a total of %1 luxury good, not "
1967  "enough to have an effect.",
1968  "This city generates a total of %1 luxury goods, not "
1969  "enough to have an effect.",
1970  luxuries))
1971  .arg(luxuries);
1972  return str + QStringLiteral("</p>");
1973  }
1974 
1975  str += QString(PL_("This city generates a total of %1 luxury good.",
1976  "This city generates a total of %1 luxury goods.",
1977  luxuries))
1978  .arg(luxuries);
1979 
1980  str += QStringLiteral("</p><p>");
1981 
1982  auto made_happy = pcity->feel[CITIZEN_HAPPY][FEELING_LUXURY]
1983  - pcity->feel[CITIZEN_HAPPY][FEELING_BASE];
1984  auto made_content = pcity->feel[CITIZEN_CONTENT][FEELING_LUXURY]
1985  - pcity->feel[CITIZEN_CONTENT][FEELING_BASE];
1986  auto made_unhappy = pcity->feel[CITIZEN_UNHAPPY][FEELING_LUXURY]
1987  - pcity->feel[CITIZEN_UNHAPPY][FEELING_BASE];
1988  int citizens_affected = std::max(0, made_happy) + std::max(0, made_content)
1989  + std::max(0, made_unhappy);
1990  int upgrades = made_happy * 3 + made_content * 2 + made_unhappy * 1;
1991  int cost = upgrades * game.info.happy_cost;
1992 
1993  if (cost < luxuries) {
1994  str +=
1995  QString(PL_("%1 citizen is made happier using %2 luxury good(s).",
1996  "%1 citizens are made happier using %2 luxury good(s).",
1997  citizens_affected))
1998  .arg(citizens_affected)
1999  .arg(cost);
2000  if (luxuries - cost > 0) {
2001  str += QStringLiteral(" ");
2002  str += QString(PL_("%1 luxury good is not used.",
2003  "%1 luxury goods are not used.", luxuries - cost))
2004  .arg(luxuries - cost);
2005  }
2006  } else {
2007  str += QString(PL_("All available luxury goods are used to make %1 "
2008  "citizen happier.",
2009  "All available luxury goods are used to make %1 "
2010  "citizens happier.",
2011  citizens_affected))
2012  .arg(citizens_affected);
2013  }
2014 
2015  return str + QStringLiteral("</p>");
2016 }
bool action_prob_possible(const struct act_prob probability)
Returns TRUE iff the given action probability belongs to an action that may be possible.
Definition: actions.cpp:5380
const QString action_prob_explain(const struct act_prob prob)
Explain an action probability in a way suitable for a tool tip for the button that starts it.
Definition: actions.cpp:1504
enum action_target_kind action_get_target_kind(const struct action *paction)
Get the target kind of an action.
Definition: actions.cpp:1198
bool action_has_result(const struct action *paction, enum action_result result)
Returns TRUE iff performing the specified action has the specified result.
Definition: actions.cpp:1248
bool is_action_possible_on_unit(action_id act_id, const unit *target_unit)
Checks if there is any hopes that the action is possible against the target unit (by chacking the tar...
Definition: actions.cpp:5752
QString strvec_to_and_list(const QVector< QString > &psv)
Definition: astring.cpp:43
QString qendl()
Definition: astring.cpp:65
const char * calendar_text()
Produce a statically allocated textual representation of the current calendar time.
Definition: calendar.cpp:137
const char * textyear(int year)
Produce a statically allocated textual representation of the given year.
Definition: calendar.cpp:116
#define citizens_foreign_iterate_end
Definition: citizens.h:55
#define citizens_foreign_iterate(_pcity, _pslot, _nationality)
Definition: citizens.h:49
struct output_type * get_output_type(Output_type_id output)
Return the output type for this index.
Definition: city.cpp:611
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
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Return TRUE iff the city has this building in it.
Definition: city.cpp:1189
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
int player_base_citizen_happiness(const struct player *pplayer)
Give base happiness in any city owned by pplayer.
Definition: city.cpp:2062
int city_airlift_max(const struct city *pcity)
A city's maximum airlift capacity.
Definition: city.cpp:2819
bool city_is_occupied(const struct city *pcity)
Returns TRUE iff the city is occupied.
Definition: city.cpp:1584
const char * city_name_get(const struct city *pcity)
Return the name of the city.
Definition: city.cpp:1077
int city_unit_unhappiness(const unit *punit, int *free_unhappy)
Query unhappiness caused by a given unit.
Definition: city.cpp:2921
int city_tile_output(const struct city *pcity, const struct tile *ptile, bool is_celebrating, Output_type_id otype)
Calculate the output for the tile.
Definition: city.cpp:1230
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
#define city_list_iterate(citylist, pcity)
Definition: city.h:482
@ 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
#define city_list_iterate_end
Definition: city.h:484
@ FEELING_LUXURY
Definition: city.h:252
@ FEELING_BASE
Definition: city.h:251
bool client_has_player()
Either controlling or observing.
bool client_is_global_observer()
Returns whether client is global observer.
struct player * client_player()
Either controlling or observing.
struct civclient client
QString concat_tile_activity_text(struct tile *ptile)
Creates the activity progress text for the given tile.
enum known_type client_tile_get_known(const struct tile *ptile)
A tile's "known" field is used by the server to store whether each player knows the tile.
Definition: climap.cpp:29
void nuclear_winter_scaled(int *chance, int *rate, int max)
Return nuclear winter chance and rate of change, scaled to max.
Definition: climisc.cpp:308
void global_warming_scaled(int *chance, int *rate, int max)
Return global warming chance and rate of change, scaled to max.
Definition: climisc.cpp:299
struct city * get_nearest_city(const struct unit *punit, int *sq_dist)
Find city nearest to given unit and optionally return squared city distance Parameter sq_dist may be ...
Definition: climisc.cpp:980
double unit_win_chance(const struct unit *attacker, const struct unit *defender)
Returns a double in the range [0;1] indicating the attackers chance of winning.
Definition: combat.cpp:408
#define MAX_LEN_PACKET
Definition: connection.h:41
std::vector< unit * > & get_units_in_focus()
Returns list of units currently in focus.
Definition: control.cpp:169
unit * find_visible_unit(const ::tile *ptile)
Return a pointer to a visible unit, if there is one.
Definition: control.cpp:749
int city_history_gain(const struct city *pcity)
How much history city gains this turn.
Definition: culture.cpp:31
int nation_history_gain(const struct player *pplayer)
How much nation-wide history player gains this turn.
Definition: culture.cpp:54
struct effect_list * effects[EFT_COUNT]
Definition: effects.cpp:102
int get_player_output_bonus(const struct player *pplayer, const struct output_type *poutput, enum effect_type effect_type)
Returns the player effect bonus of an output.
Definition: effects.cpp:760
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
QString effect_type_unit_text(effect_type type, int value)
Returns a string describing an effect value as interpreted in the context of an effect_type,...
Definition: effects.cpp:1058
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
const effect_list * get_effects()
Get a list of all effects.
Definition: effects.cpp:117
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
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Returns the effect bonus for a player.
Definition: effects.cpp:673
#define effect_list_iterate_end
Definition: effects.h:349
#define effect_list_iterate(effect_list, peffect)
Definition: effects.h:347
const char * extra_name_translation(const struct extra_type *pextra)
Return the (translated) name of the extra type.
Definition: extras.cpp:165
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_type_iterate_end
Definition: extras.h:285
int Tech_type_id
Definition: fc_types.h:294
#define MAX_LEN_NAME
Definition: fc_types.h:61
@ O_SHIELD
Definition: fc_types.h:86
@ O_FOOD
Definition: fc_types.h:85
@ O_TRADE
Definition: fc_types.h:87
@ O_SCIENCE
Definition: fc_types.h:90
@ O_LUXURY
Definition: fc_types.h:89
@ O_LAST
Definition: fc_types.h:91
@ BORDERS_DISABLED
Definition: fc_types.h:863
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
const char * population_to_text(int thousand_citizen)
Return a prettily formatted string containing the population text.
Definition: game.cpp:699
int civ_population(const struct player *pplayer)
Count the # of thousand citizen in a civilisation.
Definition: game.cpp:72
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 can_unit_move_now(const struct unit *punit)
Returns if unit can move now.
Definition: goto.cpp:56
const char * government_name_for_player(const struct player *pplayer)
Return the (translated) name of the given government of a player.
Definition: government.cpp:147
Impr_type_id improvement_count()
Return the number of improvements.
bool is_improvement_visible(const struct impr_type *pimprove)
Return TRUE if the improvement should be visible to others without spying.
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
#define improvement_iterate_end
Definition: improvement.h:199
#define improvement_iterate(_p)
Definition: improvement.h:193
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define nat_x
#define nat_y
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition: map.h:111
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition: map.h:164
const char * move_points_text_full(int mp, bool reduce, const char *prefix, const char *none, bool align)
Render positive movement points as text, including fractional movement points, scaled by SINGLE_MOVE.
Definition: movement.cpp:797
int unit_move_rate(const struct unit *punit)
This function calculates the move rate of the unit.
Definition: movement.cpp:78
const char * nation_adjective_for_player(const struct player *pplayer)
Return the (translated) adjective for the given nation of a player.
Definition: nation.cpp:146
#define MAX_LEN_MSG
Definition: packets.h:37
struct city_list * cities
Definition: packhand.cpp:122
struct player * player_by_number(const int player_id)
Return struct player pointer for the given player index.
Definition: player.cpp:768
int player_get_expected_income(const struct player *pplayer)
Return the expected net income of the player this turn.
Definition: player.cpp:1194
int player_count()
Return the number of players.
Definition: player.cpp:739
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players can attack each other.
Definition: player.cpp:1317
struct city * player_city_by_number(const struct player *pplayer, int city_id)
If the specified player owns the city with the specified id, return pointer to the city struct.
Definition: player.cpp:1113
struct player * player_slot_get_player(const struct player_slot *pslot)
Returns the team corresponding to the slot.
Definition: player.cpp:384
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Return TRUE iff the player can see units in the city.
Definition: player.cpp:1045
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Returns diplomatic state type between two players.
Definition: player.cpp:288
#define is_ai(plr)
Definition: player.h:227
int research_goal_unknown_techs(const struct research *presearch, Tech_type_id goal)
Returns the number of technologies the player need to research to get the goal technology.
Definition: research.cpp:745
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Returns if the given tech has to be researched to reach the goal.
Definition: research.cpp:794
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
QString research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Store the translated name of the given tech (including A_FUTURE) in 'buf'.
Definition: research.cpp:257
int research_goal_bulbs_required(const struct research *presearch, Tech_type_id goal)
Function to determine cost (in bulbs) of reaching goal technology.
Definition: research.cpp:767
#define research_players_iterate(_presearch, _pplayer)
Definition: research.h:151
#define research_players_iterate_end
Definition: research.h:155
void format_time_duration(time_t t, char *buf, int maxlen)
Convenience function to nicely format a time_t seconds value in to a string with hours,...
Definition: shared.cpp:1187
#define CLIP(lower, current, upper)
Definition: shared.h:51
#define ARRAY_SIZE(x)
Definition: shared.h:79
#define MIN(x, y)
Definition: shared.h:49
#define FC_INFINITY
Definition: shared.h:32
#define MAX(x, y)
Definition: shared.h:48
@ SSHIP_LAUNCHED
Definition: spaceship.h:80
int step
Definition: specpq.h:83
size_t size
Definition: specvec.h:64
Definition: city.h:291
struct player * owner
Definition: city.h:294
int airlift
Definition: city.h:349
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition: city.h:302
struct tile * tile
Definition: city.h:293
int shield_stock
Definition: city.h:339
int prod[O_LAST]
Definition: city.h:327
struct unit_list * units_supported
Definition: city.h:377
struct packet_game_info info
Definition: game.h:80
struct connection conn
Definition: client_main.h:89
struct player * playing
Definition: connection.h:142
enum diplstate_type type
Definition: player.h:193
int game
Definition: player.h:103
double energy_rate
Definition: spaceship.h:111
double success_rate
Definition: spaceship.h:112
double support_rate
Definition: spaceship.h:110
double travel_time
Definition: spaceship.h:113
enum spaceship_state state
Definition: spaceship.h:105
Definition: player.h:231
struct city_list * cities
Definition: player.h:263
struct player::@65::@68 client
char username[MAX_LEN_NAME]
Definition: player.h:234
struct team * team
Definition: player.h:243
struct unit_list * units
Definition: player.h:264
struct player_economic economic
Definition: player.h:266
char name[MAX_LEN_NAME]
Definition: player.h:233
struct player_score score
Definition: player.h:265
struct nation_type * nation
Definition: player.h:242
Tech_type_id researching
Definition: research.h:45
struct research::@71::@73 client
int bulbs_researched
Definition: research.h:46
Definition: team.cpp:35
Definition: tile.h:42
bv_extras extras
Definition: tile.h:47
struct unit_list * units
Definition: tile.h:50
int defense_strength
Definition: unittype.h:480
int firepower
Definition: unittype.h:490
int hp
Definition: unittype.h:489
int attack_strength
Definition: unittype.h:479
Definition: unit.h:134
time_t action_timestamp
Definition: unit.h:203
int moves_left
Definition: unit.h:147
int id
Definition: unit.h:141
int hp
Definition: unit.h:148
QString name
Definition: unit.h:143
int homecity
Definition: unit.h:142
struct goods_type * carrying
Definition: unit.h:183
int veteran
Definition: unit.h:149
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
#define fc_strdup(str)
Definition: support.h:111
struct team * team_by_number(const int team_id)
Return struct team pointer for the given team index.
Definition: team.cpp:373
const char * team_name_translation(const struct team *pteam)
Returns the name (translated) of the team.
Definition: team.cpp:393
int team_count()
Return the current number of teams.
Definition: team.cpp:354
struct advance * valid_advance_by_number(const Tech_type_id id)
Returns pointer when the advance "exists" in this game, returns nullptr otherwise.
Definition: tech.cpp:154
#define A_UNSET
Definition: tech.h:41
const char * get_infrastructure_text(bv_extras extras)
Return a (static) string with extra(s) name(s): eg: "Mine" eg: "Road/Farmland" This only includes "in...
Definition: terrain.cpp:394
QString text_happiness_wonders(const struct city *pcity)
Describing wonders that affect happiness.
Definition: text.cpp:1490
QString get_score_text(const struct player *pplayer)
Return text giving the score of the player.
Definition: text.cpp:1256
static void get_full_username(char *buf, int buflen, const struct player *pplayer)
For AIs, fill the buffer with their player name prefixed with "AI".
Definition: text.cpp:88
const QString get_nearest_city_text(struct city *pcity, int sq_dist)
Returns the text describing the city and its distance.
Definition: text.cpp:522
const QString science_dialog_text()
Returns the text to display in the science dialog.
Definition: text.cpp:812
const QString get_act_sel_action_custom_text(struct action *paction, const struct act_prob prob, const struct unit *actor_unit, const struct city *target_city)
Returns custom part of the action selection dialog button text for the specified action (given that t...
Definition: text.cpp:1274
#define FAR_CITY_SQUARE_DIST
Definition: text.cpp:518
const QString get_science_target_text()
Get the short science-target text.
Definition: text.cpp:887
const QString unit_description(const unit *punit)
Returns the unit description.
Definition: text.cpp:551
int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs)
Return total expected bulbs.
Definition: text.cpp:714
const QString act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Get information about starting the action in the current situation.
Definition: text.cpp:1333
QString text_happiness_luxuries(const struct city *pcity)
Describing luxuries that affect happiness.
Definition: text.cpp:1949
const QString popup_info_text(struct tile *ptile)
Text to popup on a middle-click in the mapview.
Definition: text.cpp:137
QString text_happiness_cities(const struct city *pcity)
Describing city factors that affect happiness.
Definition: text.cpp:1754
QString text_happiness_buildings(const struct city *pcity)
Describe buildings that affect happiness (or rather, anything with a Make_Content effect).
Definition: text.cpp:1389
bool get_units_upgrade_info(char *buf, size_t bufsz, const std::vector< unit * > &punits)
Return text about upgrading these unit lists.
Definition: text.cpp:1132
static int turns_to_tech_loss(const struct research *presearch, int per_turn)
Return turns until an advance is lost due to tech upkeep.
Definition: text.cpp:794
const QString get_spaceship_descr(struct player_spaceship *pship)
Returns a description of the given spaceship.
Definition: text.cpp:1197
const QString get_info_label_text_popup()
Return the text for the popup label on the info panel.
Definition: text.cpp:1036
const QString get_tile_output_text(const struct tile *ptile)
Return a (static) string with a tile's food/prod/trade.
Definition: text.cpp:52
QString text_happiness_nationality(const struct city *pcity)
Describing nationality effects that affect happiness.
Definition: text.cpp:1427
int turns_to_research_done(const struct research *presearch, int per_turn)
Return turns until research complete.
Definition: text.cpp:761
const QString get_info_label_text(bool moreinfo)
Return the text for the label on the info panel.
Definition: text.cpp:981
static void get_full_nation(char *buf, int buflen, const struct player *pplayer)
Fill the buffer with the player's nation name (in adjective form) and optionally add the player's tea...
Definition: text.cpp:112
const QString get_science_goal_text(Tech_type_id goal)
Set the science-goal-label text as if we're researching the given goal.
Definition: text.cpp:927
QString text_happiness_units(const struct city *pcity)
Describe units that affect happiness.
Definition: text.cpp:1811
const QString get_airlift_text(const std::vector< unit * > &units, const struct city *pdest)
Describe the airlift capacity of a city for the given units (from their current positions).
Definition: text.cpp:612
static int turns_per_advance(const struct research *presearch, int per_turn)
Return turns per advance (based on currently researched advance).
Definition: text.cpp:780
const char * tile_get_info_text(const struct tile *ptile, bool include_nuisances, int linebreaks)
Return a (static) string with tile name describing terrain and extras of some categories.
Definition: tile.cpp:799
bool tile_has_visible_extra(const struct tile *ptile, const struct extra_type *pextra)
Returns TRUE if the given tile has a road of given type on it.
Definition: tile.cpp:948
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_index(_pt_)
Definition: tile.h:70
@ TILE_UNKNOWN
Definition: tile.h:29
#define tile_continent(_tile)
Definition: tile.h:74
#define tile_owner(_tile)
Definition: tile.h:78
bool can_cities_trade(const struct city *pc1, const struct city *pc2)
Return TRUE iff the two cities are capable of trade; i.e., if a caravan from one city can enter the o...
int trade_base_between_cities(const struct city *pc1, const struct city *pc2)
Return the trade that exists between these cities, assuming they have a trade route.
int get_caravan_enter_city_trade_bonus(const struct city *pc1, const struct city *pc2, const player *seen_as, struct goods_type *pgood, const bool establish_trade)
Returns the revenue trade bonus - you get this when establishing a trade route and also when you simp...
bool can_establish_trade_route(const struct city *pc1, const struct city *pc2)
Returns TRUE iff the two cities can establish a trade route.
enum unit_upgrade_result unit_upgrade_test(const struct unit *punit, bool is_free)
Tests if the unit could be updated.
Definition: unit.cpp:1826
void unit_upkeep_astr(const struct unit *punit, QString &s)
Append a line of text describing the unit's upkeep to the astring.
Definition: unit.cpp:1174
bool is_military_unit(const struct unit *punit)
Military units are capable of enforcing martial law.
Definition: unit.cpp:300
int unit_bribe_cost(struct unit *punit, struct player *briber)
Calculate how expensive it is to bribe the unit.
Definition: unit.cpp:2061
enum unit_upgrade_result unit_upgrade_info(const struct unit *punit, char *buf, size_t bufsz)
Find the result of trying to upgrade the unit, and a message that most callers can use directly.
Definition: unit.cpp:1900
enum unit_airlift_result test_unit_can_airlift_to(const struct player *restriction, const struct unit *punit, const struct city *pdest_city)
Determines if punit can be airlifted to dest_city now! So punit needs to be in a city now.
Definition: unit.cpp:75
void unit_activity_astr(const struct unit *punit, QString &s)
Append text describing the unit's current activity to the given astring.
Definition: unit.cpp:1096
struct player * unit_nationality(const struct unit *punit)
Return the nationality of the unit.
Definition: unit.cpp:1190
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_owner(_pu)
Definition: unit.h:370
@ UU_OK
Definition: unit.h:49
#define unit_home(_pu_)
Definition: unit.h:369
unit_airlift_result
Definition: unit.h:59
@ AR_SRC_NO_FLIGHTS
Definition: unit.h:71
@ AR_OK_SRC_UNKNOWN
Definition: unit.h:62
@ AR_OK_DST_UNKNOWN
Definition: unit.h:63
@ AR_NO_MOVES
Definition: unit.h:65
@ AR_BAD_DST_CITY
Definition: unit.h:70
@ AR_NOT_IN_CITY
Definition: unit.h:68
@ AR_OCCUPIED
Definition: unit.h:67
@ AR_OK
Definition: unit.h:61
@ AR_DST_NO_FLIGHTS
Definition: unit.h:72
@ AR_WRONG_UNITTYPE
Definition: unit.h:66
@ AR_BAD_SRC_CITY
Definition: unit.h:69
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Return whether this player can upgrade this unit type (to any other unit type).
Definition: unittype.cpp:1379
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
const char * utype_veteran_name_translation(const struct unit_type *punittype, int level)
Return translated name of the given veteran level.
Definition: unittype.cpp:2239
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Return TRUE iff units of the given type can do the specified generalized (ruleset defined) action ena...
Definition: unittype.cpp:386
int unit_upgrade_price(const struct player *pplayer, const struct unit_type *from, const struct unit_type *to)
Return the cost (gold) of upgrading a single unit of the specified type to the new type.
Definition: unittype.cpp:1407