Freeciv-3.1
Loading...
Searching...
No Matches
text.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2002 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <string.h>
20#include <math.h> /* ceil */
21
22/* utility */
23#include "astring.h"
24#include "bitvector.h"
25#include "fcintl.h"
26#include "log.h"
27#include "support.h"
28
29/* common */
30#include "calendar.h"
31#include "citizens.h"
32#include "clientutils.h"
33#include "combat.h"
34#include "culture.h"
35#include "fc_types.h" /* LINE_BREAK */
36#include "game.h"
37#include "government.h"
38#include "map.h"
39#include "research.h"
40#include "traderoutes.h"
41#include "unitlist.h"
42
43/* client */
44#include "client_main.h"
45#include "climap.h"
46#include "climisc.h"
47#include "control.h"
48#include "goto.h"
49#include "helpdata.h"
50
51#include "text.h"
52
53
54static int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs);
55static const char *format_duration(int duration);
56
57/************************************************************************/
62const char *get_tile_output_text(const struct tile *ptile)
63{
64 static struct astring str = ASTRING_INIT;
65 int i;
66 char output_text[O_LAST][16];
67
68 for (i = 0; i < O_LAST; i++) {
69 int before_penalty = 0;
70 int x = city_tile_output(NULL, ptile, FALSE, i);
71
72 if (NULL != client.conn.playing) {
75 EFT_OUTPUT_PENALTY_TILE);
76 }
77
78 if (before_penalty > 0 && x > before_penalty) {
79 fc_snprintf(output_text[i], sizeof(output_text[i]), "%d(-1)", x);
80 } else {
81 fc_snprintf(output_text[i], sizeof(output_text[i]), "%d", x);
82 }
83 }
84
85 astr_set(&str, "%s/%s/%s", output_text[O_FOOD],
86 output_text[O_SHIELD], output_text[O_TRADE]);
87
88 return astr_str(&str);
89}
90
91/************************************************************************/
95static inline void get_full_username(char *buf, int buflen,
96 const struct player *pplayer)
97{
98 if (!buf || buflen < 1) {
99 return;
100 }
101
102 if (!pplayer) {
103 buf[0] = '\0';
104 return;
105 }
106
107 if (is_ai(pplayer)) {
108 /* TRANS: "AI <player name>" */
109 fc_snprintf(buf, buflen, _("AI %s"), pplayer->name);
110 } else {
111 fc_strlcpy(buf, pplayer->username, buflen);
112 }
113}
114
115/************************************************************************/
119static inline void get_full_nation(char *buf, int buflen,
120 const struct player *pplayer)
121{
122 if (!buf || buflen < 1) {
123 return;
124 }
125
126 if (!pplayer) {
127 buf[0] = '\0';
128 return;
129 }
130
131 if (pplayer->team) {
132 /* TRANS: "<nation adjective>, team <team name>" */
133 fc_snprintf(buf, buflen, _("%s, team %s"),
135 team_name_translation(pplayer->team));
136 } else {
137 fc_strlcpy(buf, nation_adjective_for_player(pplayer), buflen);
138 }
139}
140
141/************************************************************************/
146const char *popup_info_text(struct tile *ptile)
147{
148 const char *activity_text;
149 struct city *pcity = tile_city(ptile);
150 struct unit *punit = find_visible_unit(ptile);
151 const char *diplo_nation_plural_adjectives[DS_LAST] =
152 {"" /* unused, DS_ARMISTICE */, Q_("?nation:Hostile"),
153 "" /* unused, DS_CEASEFIRE */,
154 Q_("?nation:Peaceful"), Q_("?nation:Friendly"),
155 Q_("?nation:Mysterious"), Q_("?nation:Friendly(team)")};
156 const char *diplo_city_adjectives[DS_LAST] =
157 {"" /* unused, DS_ARMISTICE */, Q_("?city:Hostile"),
158 "" /* unused, DS_CEASEFIRE */,
159 Q_("?city:Peaceful"), Q_("?city:Friendly"), Q_("?city:Mysterious"),
160 Q_("?city:Friendly(team)")};
161 static struct astring str = ASTRING_INIT;
162 char username[MAX_LEN_NAME + 32];
163 char nation[2 * MAX_LEN_NAME + 32];
164 int tile_x, tile_y, nat_x, nat_y;
165 bool first;
166
167 astr_clear(&str);
168 index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
169 astr_add_line(&str, _("Location: (%d, %d) [%d]"),
170 tile_x, tile_y, tile_continent(ptile));
172 astr_add_line(&str, _("Native coordinates: (%d, %d)"),
173 nat_x, nat_y);
174
175 if (client_tile_get_known(ptile) == TILE_UNKNOWN) {
176 astr_add(&str, _("Unknown"));
177 return astr_str(&str);
178 }
179 astr_add_line(&str, _("Terrain: %s"), tile_get_info_text(ptile, TRUE, 0));
180 astr_add_line(&str, _("Food/Prod/Trade: %s"),
181 get_tile_output_text(ptile));
182 first = TRUE;
183 extra_type_iterate(pextra) {
184 if (pextra->category == ECAT_BONUS && tile_has_visible_extra(ptile, pextra)) {
185 if (!first) {
186 astr_add(&str, ",%s", extra_name_translation(pextra));
187 } else {
189 first = FALSE;
190 }
191 }
193 if (BORDERS_DISABLED != game.info.borders && !pcity) {
194 struct player *owner = tile_owner(ptile);
195
198
199 if (NULL != client.conn.playing && owner == client.conn.playing) {
200 astr_add_line(&str, _("Our territory"));
201 } else if (NULL != owner && NULL == client.conn.playing) {
202 /* TRANS: "Territory of <username> (<nation + team>)" */
203 astr_add_line(&str, _("Territory of %s (%s)"), username, nation);
204 } else if (NULL != owner) {
206 owner);
207
208 if (ds->type == DS_CEASEFIRE) {
209 int turns = ds->turns_left;
210
212 /* TRANS: "Territory of <username> (<nation + team>)
213 * (<number> turn cease-fire)" */
214 PL_("Territory of %s (%s) (%d turn cease-fire)",
215 "Territory of %s (%s) (%d turn cease-fire)",
216 turns),
217 username, nation, turns);
218 } else if (ds->type == DS_ARMISTICE) {
219 int turns = ds->turns_left;
220
222 /* TRANS: "Territory of <username> (<nation + team>)
223 * (<number> turn armistice)" */
224 PL_("Territory of %s (%s) (%d turn armistice)",
225 "Territory of %s (%s) (%d turn armistice)",
226 turns),
227 username, nation, turns);
228 } else {
229 int type = ds->type;
230
231 /* TRANS: "Territory of <username>
232 * (<nation + team> | <diplomatic state>)" */
233 astr_add_line(&str, _("Territory of %s (%s | %s)"),
234 username, nation,
235 diplo_nation_plural_adjectives[type]);
236 }
237 } else {
238 astr_add_line(&str, _("Unclaimed territory"));
239 }
240 }
241 if (pcity) {
242 /* Look at city owner, not tile owner (the two should be the same, if
243 * borders are in use). */
244 struct player *owner = city_owner(pcity);
245 const char *improvements[improvement_count()];
246 int has_improvements = 0;
247
250
251 if (NULL == client.conn.playing || owner == client.conn.playing) {
252 /* TRANS: "City: <city name> | <username> (<nation + team>)" */
253 astr_add_line(&str, _("City: %s | %s (%s)"),
254 city_name_get(pcity), username, nation);
255 } else {
256 struct player_diplstate *ds
258 if (ds->type == DS_CEASEFIRE) {
259 int turns = ds->turns_left;
260
261 /* TRANS: "City: <city name> | <username>
262 * (<nation + team>, <number> turn cease-fire)" */
263 astr_add_line(&str, PL_("City: %s | %s (%s, %d turn cease-fire)",
264 "City: %s | %s (%s, %d turn cease-fire)",
265 turns),
266 city_name_get(pcity), username, nation, turns);
267 } else if (ds->type == DS_ARMISTICE) {
268 int turns = ds->turns_left;
269
270 /* TRANS: "City: <city name> | <username>
271 * (<nation + team>, <number> turn armistice)" */
272 astr_add_line(&str, PL_("City: %s | %s (%s, %d turn armistice)",
273 "City: %s | %s (%s, %d turn armistice)",
274 turns),
275 city_name_get(pcity), username, nation, turns);
276 } else {
277 /* TRANS: "City: <city name> | <username>
278 * (<nation + team>, <diplomatic state>)" */
279 astr_add_line(&str, _("City: %s | %s (%s, %s)"),
280 city_name_get(pcity), username, nation,
281 diplo_city_adjectives[ds->type]);
282 }
283 }
285 int count = unit_list_size(ptile->units);
286
287 if (count > 0) {
288 /* TRANS: preserve leading space */
289 astr_add(&str, PL_(" | Occupied with %d unit.",
290 " | Occupied with %d units.", count), count);
291 } else {
292 /* TRANS: preserve leading space */
293 astr_add(&str, _(" | Not occupied."));
294 }
295 } else {
296 if (city_is_occupied(pcity)) {
297 /* TRANS: preserve leading space */
298 astr_add(&str, _(" | Occupied."));
299 } else {
300 /* TRANS: preserve leading space */
301 astr_add(&str, _(" | Not occupied."));
302 }
303 }
304 improvement_iterate(pimprove) {
305 if (is_improvement_visible(pimprove)
306 && city_has_building(pcity, pimprove)) {
307 improvements[has_improvements++] =
309 }
311
312 if (0 < has_improvements) {
313 struct astring list = ASTRING_INIT;
314
315 astr_build_and_list(&list, improvements, has_improvements);
316 /* TRANS: %s is a list of "and"-separated improvements. */
317 astr_add_line(&str, _(" with %s."), astr_str(&list));
318 astr_free(&list);
319 }
320
321 unit_list_iterate(get_units_in_focus(), pfocus_unit) {
322 struct city *hcity = game_city_by_number(pfocus_unit->homecity);
323
324 if (utype_can_do_action(unit_type_get(pfocus_unit), ACTION_TRADE_ROUTE)
325 && can_cities_trade(hcity, pcity)
326 && can_establish_trade_route(hcity, pcity)) {
327 /* TRANS: "Trade from Warsaw: 5" */
328 astr_add_line(&str, _("Trade from %s: %d"),
329 city_name_get(hcity),
330 trade_base_between_cities(hcity, pcity));
331 }
333 }
334 {
335 const char *infratext = get_infrastructure_text(ptile->extras);
336
337 if (*infratext != '\0') {
338 astr_add_line(&str, _("Infrastructure: %s"), infratext);
339 }
340 }
341 activity_text = concat_tile_activity_text(ptile);
342 if (strlen(activity_text) > 0) {
343 astr_add_line(&str, _("Activity: %s"), activity_text);
344 }
345 if (punit && !pcity) {
346 struct player *owner = unit_owner(punit);
347 const struct unit_type *ptype = unit_type_get(punit);
348
349 get_full_username(username, sizeof(username), owner);
350 get_full_nation(nation, sizeof(nation), owner);
351
352 if (!client_player() || owner == client_player()) {
353 struct city *hcity = player_city_by_number(owner, punit->homecity);
354
355 /* TRANS: "Unit: <unit type> | <username> (<nation + team>)" */
356 astr_add_line(&str, _("Unit: %s | %s (%s)"),
357 utype_name_translation(ptype), username, nation);
358
361 if (hcity != NULL) {
362 /* TRANS: on own line immediately following \n, "from <city> |
363 * <nationality> people" */
364 astr_add_line(&str, _("from %s | %s people"), city_name_get(hcity),
366 } else {
367 /* TRANS: Nationality of the people comprising a unit, if
368 * different from owner. */
369 astr_add_line(&str, _("%s people"),
371 }
372 } else if (hcity != NULL) {
373 /* TRANS: on own line immediately following \n, ... <city> */
374 astr_add_line(&str, _("from %s"), city_name_get(hcity));
375 }
376 } else if (NULL != owner) {
378 owner);
379 if (ds->type == DS_CEASEFIRE) {
380 int turns = ds->turns_left;
381
382 /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
383 * <number> turn cease-fire)" */
384 astr_add_line(&str, PL_("Unit: %s | %s (%s, %d turn cease-fire)",
385 "Unit: %s | %s (%s, %d turn cease-fire)",
386 turns),
388 username, nation, turns);
389 } else if (ds->type == DS_ARMISTICE) {
390 int turns = ds->turns_left;
391
392 /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
393 * <number> turn armistice)" */
394 astr_add_line(&str, PL_("Unit: %s | %s (%s, %d turn armistice)",
395 "Unit: %s | %s (%s, %d turn armistice)",
396 turns),
398 username, nation, turns);
399 } else {
400 /* TRANS: "Unit: <unit type> | <username> (<nation + team>,
401 * <diplomatic state>)" */
402 astr_add_line(&str, _("Unit: %s | %s (%s, %s)"),
403 utype_name_translation(ptype), username, nation,
404 diplo_city_adjectives[ds->type]);
405 }
406 }
407
408 unit_list_iterate(get_units_in_focus(), pfocus_unit) {
409 int att_chance = FC_INFINITY, def_chance = FC_INFINITY;
410 bool found = FALSE;
411 struct civ_map *nmap = &(wld.map);
412
413 unit_list_iterate(ptile->units, tile_unit) {
414 if (unit_owner(tile_unit) != unit_owner(pfocus_unit)) {
415 int att = unit_win_chance(nmap, pfocus_unit, tile_unit) * 100;
416 int def = (1.0 - unit_win_chance(nmap, tile_unit, pfocus_unit)) * 100;
417
418 found = TRUE;
419
420 /* Presumably the best attacker and defender will be used. */
421 att_chance = MIN(att, att_chance);
422 def_chance = MIN(def, def_chance);
423 }
425
426 if (found) {
427 /* TRANS: "Chance to win: A:95% D:46%" */
428 astr_add_line(&str, _("Chance to win: A:%d%% D:%d%%"),
429 att_chance, def_chance);
430 }
432
433 /* TRANS: A is attack power, D is defense power, FP is firepower,
434 * HP is hitpoints (current and max). */
435 astr_add_line(&str, _("A:%d D:%d FP:%d HP:%d/%d"),
436 ptype->attack_strength, ptype->defense_strength,
437 ptype->firepower, punit->hp, ptype->hp);
438 {
439 const char *veteran_name =
441 if (veteran_name) {
442 astr_add(&str, " (%s)", veteran_name);
443 }
444 }
445
448 /* Show bribe cost for own units. */
449 astr_add_line(&str, _("Probable bribe cost: %d"),
450 unit_bribe_cost(punit, NULL));
451 } else {
452 /* We can only give an (lower) boundary for units of other players. */
453 astr_add_line(&str, _("Estimated bribe cost: > %d"),
455 }
456
457 if ((NULL == client.conn.playing || owner == client.conn.playing)
458 && unit_list_size(ptile->units) >= 2) {
459 /* TRANS: "5 more" units on this tile */
460 astr_add(&str, _(" (%d more)"), unit_list_size(ptile->units) - 1);
461 }
462 }
463
465 return astr_str(&str);
466}
467
468#define FAR_CITY_SQUARE_DIST (2*(6*6))
469/************************************************************************/
474const char *get_nearest_city_text(struct city *pcity, int sq_dist)
475{
476 static struct astring str = ASTRING_INIT;
477
478 astr_clear(&str);
479
480 /* Just to be sure */
481 if (!pcity) {
482 sq_dist = -1;
483 }
484
485 astr_add(&str, (sq_dist >= FAR_CITY_SQUARE_DIST)
486 /* TRANS: on own line immediately following \n, ... <city> */
487 ? _("far from %s")
488 : (sq_dist > 0)
489 /* TRANS: on own line immediately following \n, ... <city> */
490 ? _("near %s")
491 : (sq_dist == 0)
492 /* TRANS: on own line immediately following \n, ... <city> */
493 ? _("in %s")
494 : "%s",
495 pcity
496 ? city_name_get(pcity)
497 : "");
498
499 return astr_str(&str);
500}
501
502/************************************************************************/
508const char *unit_description(struct unit *punit)
509{
510 int pcity_near_dist;
511 struct player *owner = unit_owner(punit);
512 struct player *nationality = unit_nationality(punit);
513 struct city *pcity =
515 struct city *pcity_near = get_nearest_city(punit, &pcity_near_dist);
516 const struct unit_type *ptype = unit_type_get(punit);
517 static struct astring str = ASTRING_INIT;
518 const struct player *pplayer = client_player();
519
520 astr_clear(&str);
521
522 astr_add(&str, "%s", utype_name_translation(ptype));
523
524 {
525 const char *veteran_name =
527 if (veteran_name) {
528 astr_add(&str, " (%s)", veteran_name);
529 }
530 }
531
532 if (pplayer == owner) {
534 } else {
535 astr_add(&str, "\n");
536 }
538
539 if (pcity) {
540 /* TRANS: on own line immediately following \n, ... <city> */
541 astr_add_line(&str, _("from %s"), city_name_get(pcity));
542 } else {
543 astr_add(&str, "\n");
544 }
546 if (nationality != NULL && owner != nationality) {
547 /* TRANS: Nationality of the people comprising a unit, if
548 * different from owner. */
549 astr_add_line(&str, _("%s people"),
550 nation_adjective_for_player(nationality));
551 } else {
552 astr_add(&str, "\n");
553 }
554 }
555
556 astr_add_line(&str, "%s",
557 get_nearest_city_text(pcity_near, pcity_near_dist));
558#ifdef FREECIV_DEBUG
559 astr_add_line(&str, "Unit ID: %d", punit->id);
560#endif
561
562 return astr_str(&str);
563}
564
565/************************************************************************/
578const char *get_airlift_text(const struct unit_list *punits,
579 const struct city *pdest)
580{
581 static struct astring str = ASTRING_INIT;
582 bool src = (pdest == NULL);
583 enum texttype { AL_IMPOSSIBLE, AL_UNKNOWN, AL_FINITE, AL_INFINITE }
584 best = AL_IMPOSSIBLE;
585 int cur = 0, max = 0;
586
587 unit_list_iterate(punits, punit) {
588 enum texttype this = AL_IMPOSSIBLE;
589 enum unit_airlift_result result;
590
591 /* NULL will tell us about the capability of airlifting from source */
592 result = test_unit_can_airlift_to(&(wld.map), client_player(), punit, pdest);
593
594 switch (result) {
595 case AR_NO_MOVES:
597 case AR_OCCUPIED:
598 case AR_NOT_IN_CITY:
599 case AR_BAD_SRC_CITY:
600 case AR_BAD_DST_CITY:
601 /* No chance of an airlift. */
602 this = AL_IMPOSSIBLE;
603 break;
604 case AR_OK:
609 /* May or may not be able to airlift now, but there's a chance we could
610 * later */
611 {
612 const struct city *pcity = src ? tile_city(unit_tile(punit)) : pdest;
613
614 fc_assert_ret_val(pcity != NULL, fc_strdup("-"));
615 if (!src && ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)
617 /* No restrictions on destination (and we can infer this even for
618 * other players' cities). */
619 this = AL_INFINITE;
620 } else if (src && ((game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)
622 this = AL_INFINITE;
623 } else if (client_player() == city_owner(pcity)) {
624 /* A city we know about. */
625 int this_cur = pcity->airlift, this_max = city_airlift_max(pcity);
626
627 if (this_max <= 0) {
628 /* City known not to be airlift-capable. */
629 this = AL_IMPOSSIBLE;
630 } else {
631 if (src
632 && (game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
633 /* Unlimited capacity. */
634 this = AL_INFINITE;
635 } else if (!src
636 && (game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
637 this = AL_INFINITE;
638 } else {
639 /* Limited capacity (possibly zero right now). */
640 this = AL_FINITE;
641 /* Store the numbers. This whole setup assumes that numeric
642 * capacity isn't unit-dependent. */
643 if (best == AL_FINITE) {
644 fc_assert(cur == this_cur && max == this_max);
645 }
646 cur = this_cur;
647 max = this_max;
648 }
649 }
650 } else {
651 /* Unknown capacity. */
652 this = AL_UNKNOWN;
653 }
654 }
655 break;
656 }
657
658 /* Now take the most optimistic view. */
659 best = MAX(best, this);
661
662 switch (best) {
663 case AL_IMPOSSIBLE:
664 return NULL;
665 case AL_UNKNOWN:
666 astr_set(&str, "?");
667 break;
668 case AL_FINITE:
669 astr_set(&str, "%d/%d", cur, max);
670 break;
671 case AL_INFINITE:
672 astr_set(&str, _("Yes"));
673 break;
674 }
675
676 return astr_str(&str);
677}
678
679/************************************************************************/
682static int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs)
683{
684 const struct research *presearch;
685 int ours = 0, theirs = 0;
686 bool team = FALSE;
687
688 if (!client_has_player()) {
689 return 0;
690 }
691 presearch = research_get(client_player());
692
693 /* Sum up science */
694 research_players_iterate(presearch, pplayer) {
695 if (pplayer == client_player()) {
696 city_list_iterate(pplayer->cities, pcity) {
697 ours += pcity->surplus[O_SCIENCE];
699 } else {
700 team = TRUE;
701 theirs -= pplayer->client.tech_upkeep;
702 }
704
705 if (team) {
706 theirs += presearch->client.total_bulbs_prod - ours;
707 }
708 ours -= client_player()->client.tech_upkeep;
709
710 if (pours) {
711 *pours = ours;
712 }
713 if (pteam) {
714 *pteam = team;
715 }
716 if (ptheirs) {
717 *ptheirs = theirs;
718 }
719
720 return ours + theirs;
721}
722
723/************************************************************************/
726static int turns_to_research_done(const struct research *presearch,
727 int per_turn)
728{
729 if (per_turn > 0) {
730 return ceil((double)(presearch->client.researching_cost
731 - presearch->bulbs_researched) / per_turn);
732 } else {
733 return -1;
734 }
735}
736
737/************************************************************************/
741static int turns_per_advance(const struct research *presearch, int per_turn)
742{
743 if (per_turn > 0) {
744 return MAX(1, ceil((double)presearch->client.researching_cost) / per_turn);
745 } else {
746 return -1;
747 }
748}
749
750/************************************************************************/
754static int turns_to_tech_loss(const struct research *presearch, int per_turn)
755{
756 if (per_turn >= 0 || game.info.techloss_forgiveness == -1) {
757 /* With techloss_forgiveness == -1, we'll never lose a tech, just
758 * get further into debt. */
759 return -1;
760 } else {
761 int bulbs_to_loss = presearch->bulbs_researched
762 + (presearch->client.researching_cost
764
765 return ceil((double)bulbs_to_loss / -per_turn);
766 }
767}
768
769/************************************************************************/
774const char *science_dialog_text(void)
775{
776 bool team;
777 int ours, theirs, perturn, upkeep;
778 static struct astring str = ASTRING_INIT;
779 struct astring ourbuf = ASTRING_INIT, theirbuf = ASTRING_INIT;
780 struct research *research;
781
782 astr_clear(&str);
783
784 perturn = get_bulbs_per_turn(&ours, &team, &theirs);
785
787 upkeep = client_player()->client.tech_upkeep;
788
789 if (NULL == client.conn.playing || (ours == 0 && theirs == 0
790 && upkeep == 0)) {
791 return _("Progress: no research");
792 }
793
794 if (A_UNSET == research->researching) {
795 astr_add(&str, _("Progress: no research"));
796 } else {
797 int turns;
798
799 if ((turns = turns_per_advance(research, perturn)) >= 0) {
800 astr_add(&str, PL_("Progress: %d turn/advance",
801 "Progress: %d turns/advance",
802 turns), turns);
803 } else if ((turns = turns_to_tech_loss(research, perturn)) >= 0) {
804 /* FIXME: turns to next loss is not a good predictor of turns to
805 * following loss, due to techloss_restore etc. But it'll do. */
806 astr_add(&str, PL_("Progress: %d turn/advance loss",
807 "Progress: %d turns/advance loss",
808 turns), turns);
809 } else {
810 /* no forward progress -- no research, or tech loss disallowed */
811 if (perturn < 0) {
812 astr_add(&str, _("Progress: decreasing!"));
813 } else {
814 astr_add(&str, _("Progress: none"));
815 }
816 }
817 }
818 astr_set(&ourbuf, PL_("%d bulb/turn", "%d bulbs/turn", ours), ours);
819 if (team) {
820 /* Techpool version */
821 astr_set(&theirbuf,
822 /* TRANS: This is appended to "%d bulb/turn" text */
823 PL_(", %d bulb/turn from team",
824 ", %d bulbs/turn from team", theirs), theirs);
825 } else {
826 astr_clear(&theirbuf);
827 }
828 astr_add(&str, " (%s%s)", astr_str(&ourbuf), astr_str(&theirbuf));
829 astr_free(&ourbuf);
830 astr_free(&theirbuf);
831
832 if (game.info.tech_upkeep_style != TECH_UPKEEP_NONE) {
833 /* perturn is defined as: (bulbs produced) - upkeep */
834 astr_add_line(&str, _("Bulbs produced per turn: %d"), perturn + upkeep);
835 /* TRANS: keep leading space; appended to "Bulbs produced per turn: %d" */
836 astr_add(&str, _(" (needed for technology upkeep: %d)"), upkeep);
837 }
838
839 return astr_str(&str);
840}
841
842/************************************************************************/
853const char *get_science_target_text(double *percent)
854{
856 static struct astring str = ASTRING_INIT;
857
858 if (!research) {
859 return "-";
860 }
861
862 astr_clear(&str);
863 if (research->researching == A_UNSET) {
864 astr_add(&str, _("%d/- (never)"), research->bulbs_researched);
865 if (percent) {
866 *percent = 0.0;
867 }
868 } else {
869 int total = research->client.researching_cost;
870 int done = research->bulbs_researched;
871 int perturn = get_bulbs_per_turn(NULL, NULL, NULL);
872 int turns;
873
874 if ((turns = turns_to_research_done(research, perturn)) >= 0) {
875 astr_add(&str, PL_("%d/%d (%d turn)", "%d/%d (%d turns)", turns),
876 done, total, turns);
877 } else if ((turns = turns_to_tech_loss(research, perturn)) >= 0) {
878 astr_add(&str, PL_("%d/%d (%d turn to loss)",
879 "%d/%d (%d turns to loss)", turns),
880 done, total, turns);
881 } else {
882 /* no forward progress -- no research, or tech loss disallowed */
883 astr_add(&str, _("%d/%d (never)"), done, total);
884 }
885 if (percent) {
886 *percent = (double)done / (double)total;
887 *percent = CLIP(0.0, *percent, 1.0);
888 }
889 }
890
891 return astr_str(&str);
892}
893
894/************************************************************************/
900{
901 const struct research *research = research_get(client_player());
902 int steps = research_goal_unknown_techs(research, goal);
903 int bulbs_needed = research_goal_bulbs_required(research, goal);
904 int turns;
905 int perturn = get_bulbs_per_turn(NULL, NULL, NULL);
906 static struct astring str = ASTRING_INIT;
907 struct astring buf1 = ASTRING_INIT,
908 buf2 = ASTRING_INIT,
909 buf3 = ASTRING_INIT;
910
911 if (!research) {
912 return "-";
913 }
914
915 astr_clear(&str);
916
918 || research->researching == goal) {
919 bulbs_needed -= research->bulbs_researched;
920 }
921
922 astr_set(&buf1,
923 PL_("%d step", "%d steps", steps), steps);
924 astr_set(&buf2,
925 PL_("%d bulb", "%d bulbs", bulbs_needed), bulbs_needed);
926 if (perturn > 0) {
927 turns = (bulbs_needed + perturn - 1) / perturn;
928 astr_set(&buf3,
929 PL_("%d turn", "%d turns", turns), turns);
930 } else {
931 astr_set(&buf3, _("never"));
932 }
933 astr_add_line(&str, "(%s - %s - %s)",
934 astr_str(&buf1), astr_str(&buf2), astr_str(&buf3));
935 astr_free(&buf1);
936 astr_free(&buf2);
937 astr_free(&buf3);
938
939 return astr_str(&str);
940}
941
942/************************************************************************/
950const char *get_info_label_text(bool moreinfo)
951{
952 static struct astring str = ASTRING_INIT;
953
954 astr_clear(&str);
955
956 if (NULL != client.conn.playing) {
957 astr_add_line(&str, _("Population: %s"),
959 }
960 astr_add_line(&str, _("Year: %s (T%d)"),
962
963 if (NULL != client.conn.playing) {
964 astr_add_line(&str, _("Gold: %d (%+d)"),
967 astr_add_line(&str, _("Tax: %d Lux: %d Sci: %d"),
971 }
972 if (game.info.phase_mode == PMT_PLAYERS_ALTERNATE) {
973 if (game.info.phase < 0 || game.info.phase >= player_count()) {
974 astr_add_line(&str, _("Moving: Nobody"));
975 } else {
976 astr_add_line(&str, _("Moving: %s"),
978 }
979 } else if (game.info.phase_mode == PMT_TEAMS_ALTERNATE) {
980 if (game.info.phase < 0 || game.info.phase >= team_count()) {
981 astr_add_line(&str, _("Moving: Nobody"));
982 } else {
983 astr_add_line(&str, _("Moving: %s"),
985 }
986 }
987
988 if (moreinfo) {
989 astr_add_line(&str, _("(Click for more info)"));
990 }
991
992 return astr_str(&str);
993}
994
995/************************************************************************/
1003{
1004 static struct astring str = ASTRING_INIT;
1005
1006 astr_clear(&str);
1007
1008 if (NULL != client.conn.playing) {
1009 astr_add_line(&str, _("%s People"),
1011 }
1012 astr_add_line(&str, _("Year: %s"), calendar_text());
1013 astr_add_line(&str, _("Turn: %d"), game.info.turn);
1014
1015 if (NULL != client.conn.playing) {
1016 const struct research *presearch = research_get(client_player());
1017 int perturn = get_bulbs_per_turn(NULL, NULL, NULL);
1018 int upkeep = client_player()->client.tech_upkeep;
1019
1020 astr_add_line(&str, _("Gold: %d"),
1022 astr_add_line(&str, _("Net Income: %d"),
1024 /* TRANS: Gold, luxury, and science rates are in percentage values. */
1025 astr_add_line(&str, _("Tax rates: Gold:%d%% Luxury:%d%% Science:%d%%"),
1029 astr_add_line(&str, _("Researching %s: %s"),
1031 presearch->researching),
1033 /* perturn is defined as: (bulbs produced) - upkeep */
1034 if (game.info.tech_upkeep_style != TECH_UPKEEP_NONE) {
1035 astr_add_line(&str, _("Bulbs per turn: %d - %d = %d"), perturn + upkeep,
1036 upkeep, perturn);
1037 } else {
1038 fc_assert(upkeep == 0);
1039 astr_add_line(&str, _("Bulbs per turn: %d"), perturn);
1040 }
1041 {
1042 int history_perturn = nation_history_gain(client.conn.playing);
1043
1045 history_perturn += city_history_gain(pcity);
1047 astr_add_line(&str, _("Culture: %d (%+d/turn)"),
1048 client.conn.playing->client.culture, history_perturn);
1049 }
1050 }
1051
1052 /* See also get_global_warming_tooltip() and get_nuclear_winter_tooltip(). */
1053
1054 if (game.info.global_warming) {
1055 int chance, rate;
1056 global_warming_scaled(&chance, &rate, 100);
1057 astr_add_line(&str, _("Global warming chance: %d%% (%+d%%/turn)"),
1058 chance, rate);
1059 } else {
1060 astr_add_line(&str, _("Global warming deactivated."));
1061 }
1062
1063 if (game.info.nuclear_winter) {
1064 int chance, rate;
1065 nuclear_winter_scaled(&chance, &rate, 100);
1066 astr_add_line(&str, _("Nuclear winter chance: %d%% (%+d%%/turn)"),
1067 chance, rate);
1068 } else {
1069 astr_add_line(&str, _("Nuclear winter deactivated."));
1070 }
1071
1072 if (NULL != client.conn.playing) {
1073 astr_add_line(&str, _("Government: %s"),
1075 }
1076
1077 return astr_str(&str);
1078}
1079
1080/************************************************************************/
1087const char *get_unit_info_label_text1(struct unit_list *punits)
1088{
1089 static struct astring str = ASTRING_INIT;
1090
1091 astr_clear(&str);
1092
1093 if (punits) {
1094 int count = unit_list_size(punits);
1095
1096 if (count == 1) {
1097 astr_add(&str, "%s", unit_name_translation(unit_list_get(punits, 0)));
1098 } else {
1099 astr_add(&str, PL_("%d unit", "%d units", count), count);
1100 }
1101 }
1102 return astr_str(&str);
1103}
1104
1105/************************************************************************/
1112const char *get_unit_info_label_text2(struct unit_list *punits, int linebreaks)
1113{
1114 static struct astring str = ASTRING_INIT;
1115 int count;
1116
1117 astr_clear(&str);
1118
1119 if (!punits) {
1120 return "";
1121 }
1122
1123 count = unit_list_size(punits);
1124
1125 /* This text should always have the same number of lines if
1126 * 'linebreaks' has no flags at all. Otherwise the GUI widgets may be
1127 * confused and try to resize themselves. If caller asks for
1128 * conditional 'linebreaks', it should take care of these problems
1129 * itself. */
1130
1131 /* Line 1. Goto or activity text. */
1132 if (count > 0 && hover_state != HOVER_NONE) {
1133 int min, max;
1134
1135 if (!goto_get_turns(&min, &max)) {
1136 /* TRANS: Impossible to reach goto target tile */
1137 astr_add_line(&str, "%s", Q_("?goto:Unreachable"));
1138 } else if (min == max) {
1139 astr_add_line(&str, _("Turns to target: %d"), max);
1140 } else {
1141 astr_add_line(&str, _("Turns to target: %d to %d"), min, max);
1142 }
1143 } else if (count == 1) {
1144 struct astring addition = ASTRING_INIT;
1145
1146 unit_activity_astr(unit_list_get(punits, 0), &addition);
1147 astr_add_line(&str, "%s", astr_str(&addition));
1148 astr_free(&addition);
1149 } else if (count > 1) {
1150 astr_add_line(&str, PL_("%d unit selected",
1151 "%d units selected",
1152 count),
1153 count);
1154 } else {
1155 astr_add_line(&str, _("No units selected."));
1156 }
1157
1158 /* Lines 2, 3, 4, and possible 5 vary. */
1159 if (count == 1) {
1160 struct unit *punit = unit_list_get(punits, 0);
1161 struct player *owner = unit_owner(punit);
1162 struct city *pcity = player_city_by_number(owner,
1163 punit->homecity);
1164
1166 linebreaks));
1167 {
1168 const char *infratext = get_infrastructure_text(unit_tile(punit)->extras);
1169
1170 if (*infratext != '\0') {
1171 astr_add_line(&str, "%s", infratext);
1172 } else {
1173 astr_add_line(&str, " ");
1174 }
1175 }
1176 if (pcity) {
1177 astr_add_line(&str, "%s", city_name_get(pcity));
1178 } else {
1179 astr_add_line(&str, " ");
1180 }
1181
1183 struct player *nationality = unit_nationality(punit);
1184
1185 /* Line 5, nationality text */
1186 if (nationality != NULL && owner != nationality) {
1187 /* TRANS: Nationality of the people comprising a unit, if
1188 * different from owner. */
1189 astr_add_line(&str, _("%s people"),
1190 nation_adjective_for_player(nationality));
1191 } else {
1192 astr_add_line(&str, " ");
1193 }
1194 }
1195
1196 } else if (count > 1) {
1197 int mil = 0, nonmil = 0;
1198 int types_count[U_LAST], i;
1199 struct unit_type *top[3];
1200
1201 memset(types_count, 0, sizeof(types_count));
1202 unit_list_iterate(punits, punit) {
1203 if (unit_has_type_flag(punit, UTYF_CIVILIAN)) {
1204 nonmil++;
1205 } else {
1206 mil++;
1207 }
1208 types_count[utype_index(unit_type_get(punit))]++;
1210
1211 top[0] = top[1] = top[2] = NULL;
1212 unit_type_iterate(utype) {
1213 if (!top[2]
1214 || types_count[utype_index(top[2])] < types_count[utype_index(utype)]) {
1215 top[2] = utype;
1216
1217 if (!top[1]
1218 || types_count[utype_index(top[1])] < types_count[utype_index(top[2])]) {
1219 top[2] = top[1];
1220 top[1] = utype;
1221
1222 if (!top[0]
1223 || types_count[utype_index(top[0])] < types_count[utype_index(utype)]) {
1224 top[1] = top[0];
1225 top[0] = utype;
1226 }
1227 }
1228 }
1230
1231 for (i = 0; i < 2; i++) {
1232 if (top[i] && types_count[utype_index(top[i])] > 0) {
1233 if (utype_has_flag(top[i], UTYF_CIVILIAN)) {
1234 nonmil -= types_count[utype_index(top[i])];
1235 } else {
1236 mil -= types_count[utype_index(top[i])];
1237 }
1238 astr_add_line(&str, "%d: %s",
1239 types_count[utype_index(top[i])],
1240 utype_name_translation(top[i]));
1241 } else {
1242 astr_add_line(&str, " ");
1243 }
1244 }
1245
1246 if (top[2] && types_count[utype_index(top[2])] > 0
1247 && types_count[utype_index(top[2])] == nonmil + mil) {
1248 astr_add_line(&str, "%d: %s", types_count[utype_index(top[2])],
1249 utype_name_translation(top[2]));
1250 } else if (nonmil > 0 && mil > 0) {
1251 astr_add_line(&str, _("Others: %d civil; %d military"), nonmil, mil);
1252 } else if (nonmil > 0) {
1253 astr_add_line(&str, _("Others: %d civilian"), nonmil);
1254 } else if (mil > 0) {
1255 astr_add_line(&str, _("Others: %d military"), mil);
1256 } else {
1257 astr_add_line(&str, " ");
1258 }
1259
1261 astr_add_line(&str, " ");
1262 }
1263 } else {
1264 astr_add_line(&str, " ");
1265 astr_add_line(&str, " ");
1266 astr_add_line(&str, " ");
1267
1269 astr_add_line(&str, " ");
1270 }
1271 }
1272
1273 /* Line 5/6. Debug text. */
1274#ifdef FREECIV_DEBUG
1275 if (count == 1) {
1276 astr_add_line(&str, "(Unit ID %d)", unit_list_get(punits, 0)->id);
1277 } else {
1278 astr_add_line(&str, " ");
1279 }
1280#endif /* FREECIV_DEBUG */
1281
1282 return astr_str(&str);
1283}
1284
1285/************************************************************************/
1290bool get_units_upgrade_info(char *buf, size_t bufsz,
1291 struct unit_list *punits)
1292{
1293 if (unit_list_size(punits) == 0) {
1294 fc_snprintf(buf, bufsz, _("No units to upgrade!"));
1295 return FALSE;
1296 } else if (unit_list_size(punits) == 1) {
1297 return (UU_OK == unit_upgrade_info(&(wld.map), unit_list_front(punits), buf, bufsz));
1298 } else {
1299 int upgrade_cost = 0;
1300 int num_upgraded = 0;
1301 int min_upgrade_cost = FC_INFINITY;
1302
1303 unit_list_iterate(punits, punit) {
1305 && UU_OK == unit_upgrade_test(&(wld.map), punit, FALSE)) {
1306 const struct unit_type *from_unittype = unit_type_get(punit);
1307 const struct unit_type *to_unittype = can_upgrade_unittype(client.conn.playing,
1308 from_unittype);
1310 from_unittype, to_unittype);
1311
1312 num_upgraded++;
1313 upgrade_cost += cost;
1314 min_upgrade_cost = MIN(min_upgrade_cost, cost);
1315 }
1317 if (num_upgraded == 0) {
1318 fc_snprintf(buf, bufsz, _("None of these units may be upgraded."));
1319 return FALSE;
1320 } else {
1321 /* This may trigger sometimes if you don't have enough money for
1322 * a full upgrade. If you have enough to upgrade at least one, it
1323 * will do it. */
1324 /* Construct prompt in several parts to allow separate pluralisation
1325 * by localizations */
1326 char tbuf[MAX_LEN_MSG], ubuf[MAX_LEN_MSG];
1327
1328 fc_snprintf(tbuf, ARRAY_SIZE(tbuf), PL_("Treasury contains %d gold.",
1329 "Treasury contains %d gold.",
1330 client_player()->economic.gold),
1331 client_player()->economic.gold);
1332 /* TRANS: this whole string is a sentence fragment that is only ever
1333 * used by including it in another string (search comments for this
1334 * string to find it) */
1335 fc_snprintf(ubuf, ARRAY_SIZE(ubuf), PL_("Upgrade %d unit",
1336 "Upgrade %d units",
1337 num_upgraded),
1338 num_upgraded);
1339 /* TRANS: This is complicated. The first %s is a pre-pluralised
1340 * sentence fragment "Upgrade %d unit(s)"; the second is pre-pluralised
1341 * "Treasury contains %d gold." So the whole thing reads
1342 * "Upgrade 13 units for 1000 gold?\nTreasury contains 2000 gold." */
1343 fc_snprintf(buf, bufsz, PL_("%s for %d gold?\n%s",
1344 "%s for %d gold?\n%s", upgrade_cost),
1345 ubuf, upgrade_cost, tbuf);
1346 return TRUE;
1347 }
1348 }
1349}
1350
1351/************************************************************************/
1356bool get_units_disband_info(char *buf, size_t bufsz,
1357 struct unit_list *punits)
1358{
1359 if (unit_list_size(punits) == 0) {
1360 fc_snprintf(buf, bufsz, _("No units to disband!"));
1361 return FALSE;
1362 } else if (unit_list_size(punits) == 1) {
1363 if (!unit_can_do_action(unit_list_front(punits),
1364 ACTION_DISBAND_UNIT)) {
1365 fc_snprintf(buf, bufsz, _("%s refuses to disband!"),
1366 unit_name_translation(unit_list_front(punits)));
1367 return FALSE;
1368 } else {
1369 /* TRANS: %s is a unit type */
1370 fc_snprintf(buf, bufsz, _("Disband %s?"),
1371 unit_name_translation(unit_list_front(punits)));
1372 return TRUE;
1373 }
1374 } else {
1375 int count = 0;
1376
1377 unit_list_iterate(punits, punit) {
1378 if (unit_can_do_action(punit, ACTION_DISBAND_UNIT)) {
1379 count++;
1380 }
1382 if (count == 0) {
1383 fc_snprintf(buf, bufsz, _("None of these units may be disbanded."));
1384 return FALSE;
1385 } else {
1386 /* TRANS: %d is never 0 or 1 */
1387 fc_snprintf(buf, bufsz, PL_("Disband %d unit?",
1388 "Disband %d units?", count), count);
1389 return TRUE;
1390 }
1391 }
1392}
1393
1394/************************************************************************/
1400const char *get_bulb_tooltip(void)
1401{
1402 static struct astring str = ASTRING_INIT;
1403
1404 astr_clear(&str);
1405
1406 astr_add_line(&str, _("Shows your progress in "
1407 "researching the current technology."));
1408
1409 if (NULL != client.conn.playing) {
1411
1412 if (research->researching == A_UNSET) {
1413 astr_add_line(&str, _("No research target."));
1414 } else {
1415 int turns;
1416 int perturn = get_bulbs_per_turn(NULL, NULL, NULL);
1417 struct astring buf1 = ASTRING_INIT, buf2 = ASTRING_INIT;
1418
1419 if ((turns = turns_to_research_done(research, perturn)) >= 0) {
1420 astr_set(&buf1, PL_("%d turn", "%d turns", turns), turns);
1421 } else if ((turns = turns_to_tech_loss(research, perturn)) >= 0) {
1422 astr_set(&buf1, PL_("%d turn to loss", "%d turns to loss", turns),
1423 turns);
1424 } else {
1425 if (perturn < 0) {
1426 astr_set(&buf1, _("Decreasing"));
1427 } else {
1428 astr_set(&buf1, _("No progress"));
1429 }
1430 }
1431
1432 /* TRANS: <perturn> bulbs/turn */
1433 astr_set(&buf2, PL_("%d bulb/turn", "%d bulbs/turn", perturn), perturn);
1434
1435 /* TRANS: <tech>: <amount>/<total bulbs> */
1436 astr_add_line(&str, _("%s: %d/%d (%s, %s)."),
1441 astr_str(&buf1), astr_str(&buf2));
1442
1443 astr_free(&buf1);
1444 astr_free(&buf2);
1445 }
1446 }
1447
1448 return astr_str(&str);
1449}
1450
1451/************************************************************************/
1458{
1459 static struct astring str = ASTRING_INIT;
1460
1461 astr_clear(&str);
1462
1463 if (!game.info.global_warming) {
1464 astr_add_line(&str, _("Global warming deactivated."));
1465 } else {
1466 int chance, rate;
1467
1468 global_warming_scaled(&chance, &rate, 100);
1469 astr_add_line(&str, _("Shows the progress of global warming:"));
1470 astr_add_line(&str, _("Pollution rate: %d%%"), rate);
1471 astr_add_line(&str, _("Chance of catastrophic warming each turn: %d%%"),
1472 chance);
1473 }
1474
1475 return astr_str(&str);
1476}
1477
1478/************************************************************************/
1485{
1486 static struct astring str = ASTRING_INIT;
1487
1488 astr_clear(&str);
1489
1490 if (!game.info.nuclear_winter) {
1491 astr_add_line(&str, _("Nuclear winter deactivated."));
1492 } else {
1493 int chance, rate;
1494
1495 nuclear_winter_scaled(&chance, &rate, 100);
1496 astr_add_line(&str, _("Shows the progress of nuclear winter:"));
1497 astr_add_line(&str, _("Fallout rate: %d%%"), rate);
1498 astr_add_line(&str, _("Chance of catastrophic winter each turn: %d%%"),
1499 chance);
1500 }
1501
1502 return astr_str(&str);
1503}
1504
1505/************************************************************************/
1511const char *get_government_tooltip(void)
1512{
1513 static struct astring str = ASTRING_INIT;
1514
1515 astr_clear(&str);
1516
1517 astr_add_line(&str, _("Shows your current government:"));
1518
1519 if (NULL != client.conn.playing) {
1520 astr_add_line(&str, "%s",
1522 }
1523
1524 return astr_str(&str);
1525}
1526
1527/************************************************************************/
1533const char *get_spaceship_descr(struct player_spaceship *pship)
1534{
1535 struct player_spaceship ship;
1536 static struct astring str = ASTRING_INIT;
1537
1538 astr_clear(&str);
1539
1540 if (!pship) {
1541 pship = &ship;
1542 memset(&ship, 0, sizeof(ship));
1543 }
1544
1545 /* TRANS: spaceship text; should have constant width. */
1546 astr_add_line(&str, _("Population: %5d"), pship->population);
1547
1548 /* TRANS: spaceship text; should have constant width. */
1549 astr_add_line(&str, _("Support: %5d %%"),
1550 (int) (pship->support_rate * 100.0));
1551
1552 /* TRANS: spaceship text; should have constant width. */
1553 astr_add_line(&str, _("Energy: %5d %%"),
1554 (int) (pship->energy_rate * 100.0));
1555
1556 /* TRANS: spaceship text; should have constant width. */
1557 astr_add_line(&str, PL_("Mass: %5d ton",
1558 "Mass: %5d tons",
1559 pship->mass), pship->mass);
1560
1561 if (pship->propulsion > 0) {
1562 /* TRANS: spaceship text; should have constant width. */
1563 astr_add_line(&str, _("Travel time: %5.1f years"),
1564 (float) (0.1 * ((int) (pship->travel_time * 10.0))));
1565 } else {
1566 /* TRANS: spaceship text; should have constant width. */
1567 astr_add_line(&str, "%s", _("Travel time: N/A "));
1568 }
1569
1570 /* TRANS: spaceship text; should have constant width. */
1571 astr_add_line(&str, _("Success prob.: %5d %%"),
1572 (int) (pship->success_rate * 100.0));
1573
1574 /* TRANS: spaceship text; should have constant width. */
1575 astr_add_line(&str, _("Year of arrival: %8s"),
1576 (pship->state == SSHIP_LAUNCHED)
1577 ? textyear((int) (pship->launch_year +
1578 (int) pship->travel_time))
1579 : "- ");
1580
1581 return astr_str(&str);
1582}
1583
1584/************************************************************************/
1590const char *get_timeout_label_text(void)
1591{
1592 static struct astring str = ASTRING_INIT;
1593
1594 astr_clear(&str);
1595
1597 int wt = get_seconds_to_new_turn();
1598
1599 if (wt <= 0) {
1600 astr_add(&str, "%s", Q_("?timeout:wait"));
1601 } else {
1602 astr_add(&str, "%s: %s", Q_("?timeout:eta"), format_duration(wt));
1603 }
1604 } else {
1605 if (current_turn_timeout() <= 0) {
1606 astr_add(&str, "%s", Q_("?timeout:off"));
1607 } else {
1609 }
1610 }
1611
1612 return astr_str(&str);
1613}
1614
1615/************************************************************************/
1623static const char *format_duration(int duration)
1624{
1625 static struct astring str = ASTRING_INIT;
1626
1627 astr_clear(&str);
1628
1629 if (duration < 0) {
1630 duration = 0;
1631 }
1632 if (duration < 60) {
1633 astr_add(&str, Q_("?seconds:%02ds"), duration);
1634 } else if (duration < 3600) { /* < 60 minutes */
1635 astr_add(&str, Q_("?mins/secs:%02dm %02ds"), duration / 60, duration % 60);
1636 } else if (duration < 360000) { /* < 100 hours */
1637 astr_add(&str, Q_("?hrs/mns:%02dh %02dm"), duration / 3600, (duration / 60) % 60);
1638 } else if (duration < 8640000) { /* < 100 days */
1639 astr_add(&str, Q_("?dys/hrs:%02dd %02dh"), duration / 86400,
1640 (duration / 3600) % 24);
1641 } else {
1642 astr_add(&str, "%s", Q_("?duration:overflow"));
1643 }
1644
1645 return astr_str(&str);
1646}
1647
1648/************************************************************************/
1654const char *get_ping_time_text(const struct player *pplayer)
1655{
1656 static struct astring str = ASTRING_INIT;
1657
1658 astr_clear(&str);
1659
1660 conn_list_iterate(pplayer->connections, pconn) {
1661 if (!pconn->observer
1662 /* Certainly not needed, but safer. */
1663 && 0 == strcmp(pconn->username, pplayer->username)) {
1664 if (pconn->ping_time >= 0) {
1665 double ping_time_in_ms = 1000 * pconn->ping_time;
1666
1667 astr_add(&str, _("%6d.%02d ms"), (int) ping_time_in_ms,
1668 ((int) (ping_time_in_ms * 100.0)) % 100);
1669 }
1670 break;
1671 }
1673
1674 return astr_str(&str);
1675}
1676
1677/************************************************************************/
1683const char *get_score_text(const struct player *pplayer)
1684{
1685 static struct astring str = ASTRING_INIT;
1686
1687 astr_clear(&str);
1688
1689 if (pplayer->score.game >= 0) {
1690 astr_add(&str, "%d", pplayer->score.game);
1691 } else {
1692 astr_add(&str, "?");
1693 }
1694
1695 return astr_str(&str);
1696}
1697
1698/************************************************************************/
1705const char *get_report_title(const char *report_name)
1706{
1707 static struct astring str = ASTRING_INIT;
1708 const struct player *pplayer = client_player();
1709
1710 astr_clear(&str);
1711
1712 astr_add_line(&str, "%s", report_name);
1713
1714 if (pplayer != NULL) {
1715 char buf[4 * MAX_LEN_NAME];
1716
1717 /* TRANS: <nation adjective> <government name>.
1718 * E.g. "Polish Republic". */
1719 astr_add_line(&str, Q_("?nationgovernment:%s %s"),
1722
1723 /* TRANS: Just appending 2 strings, using the correct localized
1724 * syntax. */
1725 astr_add_line(&str, _("%s - %s"),
1726 ruler_title_for_player(pplayer, buf, sizeof(buf)),
1727 calendar_text());
1728 } else {
1729 /* TRANS: "Observer - 1985 AD" */
1730 astr_add_line(&str, _("Observer - %s"),
1731 calendar_text());
1732 }
1733
1734 return astr_str(&str);
1735}
1736
1737/**********************************************************************/
1743const char *get_act_sel_action_custom_text(struct action *paction,
1744 const struct act_prob prob,
1745 const struct unit *actor_unit,
1746 const struct city *target_city)
1747{
1748 static struct astring custom = ASTRING_INIT;
1749
1750 struct city *actor_homecity = unit_home(actor_unit);
1751
1752 if (!action_prob_possible(prob)) {
1753 /* No info since impossible. */
1754 return NULL;
1755 }
1756
1757 fc_assert_ret_val((action_get_target_kind(paction) != ATK_CITY
1758 || target_city != NULL),
1759 NULL);
1760
1761 if (action_has_result(paction, ACTRES_TRADE_ROUTE)) {
1762 int revenue = get_caravan_enter_city_trade_bonus(actor_homecity,
1765 TRUE);
1766
1767 if (revenue > 0) {
1768 astr_set(&custom,
1769 /* TRANS: Estimated one time bonus and recurring revenue for
1770 * the Establish Trade _Route action. */
1771 _("%d one time bonus + %d trade"),
1772 revenue,
1773 trade_base_between_cities(actor_homecity, target_city));
1774 } else {
1775 astr_set(&custom,
1776 /* TRANS: Estimated recurring revenue for
1777 * the Establish Trade _Route action. */
1778 _("%d trade"),
1779 trade_base_between_cities(actor_homecity, target_city));
1780 }
1781 } else if (action_has_result(paction, ACTRES_MARKETPLACE)) {
1782 int revenue = get_caravan_enter_city_trade_bonus(actor_homecity,
1785 FALSE);
1786
1787 if (revenue > 0) {
1788 astr_set(&custom,
1789 /* TRANS: Estimated one time bonus for the Enter Marketplace
1790 * action. */
1791 _("%d one time bonus"), revenue);
1792 } else {
1793 /* No info to add. */
1794 return NULL;
1795 }
1796 } else if ((action_has_result(paction, ACTRES_HELP_WONDER)
1797 || action_has_result(paction, ACTRES_DISBAND_UNIT_RECOVER))
1799 /* Can only give remaining production for domestic and existing
1800 * cities. */
1802
1803 astr_set(&custom, _("%d remaining"), cost - target_city->shield_stock);
1804 } else {
1805 /* No info to add. */
1806 return NULL;
1807 }
1808
1809 return astr_str(&custom);
1810}
1811
1812/**********************************************************************/
1820const char *act_sel_action_tool_tip(const struct action *paction,
1821 const struct act_prob prob)
1822{
1823 return action_prob_explain(prob);
1824}
1825
1826/************************************************************************/
1831const char *text_happiness_buildings(const struct city *pcity)
1832{
1833 struct effect_list *plist = effect_list_new();
1834 static struct astring str = ASTRING_INIT;
1835
1836 get_city_bonus_effects(plist, pcity, NULL, EFT_MAKE_CONTENT);
1837 if (0 < effect_list_size(plist)) {
1838 struct astring effects = ASTRING_INIT;
1839
1841 astr_set(&str, _("Buildings: %s."), astr_str(&effects));
1843 } else {
1844 astr_set(&str, _("Buildings: None."));
1845 }
1846 effect_list_destroy(plist);
1847
1848 /* Add line breaks after 80 characters. */
1849 astr_break_lines(&str, 80);
1850
1851 return astr_str(&str);
1852}
1853
1854/************************************************************************/
1859const char *text_happiness_nationality(const struct city *pcity)
1860{
1861 static struct astring str = ASTRING_INIT;
1862 int enemies = 0;
1863
1864 astr_clear(&str);
1865
1866 astr_add_line(&str, _("Nationality: "));
1867
1869 if (get_city_bonus(pcity, EFT_ENEMY_CITIZEN_UNHAPPY_PCT) > 0) {
1870 struct player *owner = city_owner(pcity);
1871
1872 citizens_foreign_iterate(pcity, pslot, nationality) {
1874 enemies += nationality;
1875 }
1877
1878 if (enemies > 0) {
1879 astr_add(&str, PL_("%d enemy nationalist", "%d enemy nationalists", enemies),
1880 enemies);
1881 }
1882 }
1883
1884 if (enemies == 0) {
1885 /* TRANS: No enemy nationalities, as there's no enemies present. */
1886 astr_add(&str, _("None."));
1887 }
1888 } else {
1889 /* TRANS: No nationalities present. */
1890 astr_add(&str, _("Disabled."));
1891 }
1892
1893 return astr_str(&str);
1894}
1895
1896/************************************************************************/
1901const char *text_happiness_wonders(const struct city *pcity)
1902{
1903 struct effect_list *plist = effect_list_new();
1904 static struct astring str = ASTRING_INIT;
1905
1906 get_city_bonus_effects(plist, pcity, NULL, EFT_MAKE_HAPPY);
1907 get_city_bonus_effects(plist, pcity, NULL, EFT_FORCE_CONTENT);
1908 get_city_bonus_effects(plist, pcity, NULL, EFT_NO_UNHAPPY);
1909 if (0 < effect_list_size(plist)) {
1910 struct astring effects = ASTRING_INIT;
1911
1913 astr_set(&str, _("Wonders: %s."), astr_str(&effects));
1915 } else {
1916 astr_set(&str, _("Wonders: None."));
1917 }
1918
1919 /* Add line breaks after 80 characters. */
1920 astr_break_lines(&str, 80);
1921 effect_list_destroy(plist);
1922
1923 return astr_str(&str);
1924}
1925
1926/************************************************************************/
1931const char *text_happiness_cities(const struct city *pcity)
1932{
1933 struct player *pplayer = city_owner(pcity);
1934 int cities = city_list_size(pplayer->cities);
1935 int content = get_player_bonus(pplayer, EFT_CITY_UNHAPPY_SIZE);
1936 int basis = get_player_bonus(pplayer, EFT_EMPIRE_SIZE_BASE);
1937 int step = get_player_bonus(pplayer, EFT_EMPIRE_SIZE_STEP);
1938 static struct astring str = ASTRING_INIT;
1939
1940 astr_clear(&str);
1941
1942 if (basis+step <= 0) {
1943 /* Special case where penalty is disabled; see
1944 * player_content_citizens(). */
1946 PL_("Cities: %d total, but no penalty for empire size.",
1947 "Cities: %d total, but no penalty for empire size.",
1948 cities),
1949 cities);
1951 /* TRANS: %d is number of citizens */
1952 PL_("%d content per city.",
1953 "%d content per city.", content),
1954 content);
1955 } else {
1956 /* Can have up to and including 'basis' cities without penalty */
1957 int excess = MAX(cities - basis, 0);
1958 int penalty;
1959 int unhappy, angry;
1960 int last, next;
1961
1962 if (excess > 0) {
1963 if (step > 0) {
1964 penalty = 1 + (excess - 1) / step;
1965 } else {
1966 penalty = 1;
1967 }
1968 } else {
1969 penalty = 0;
1970 }
1971
1972 unhappy = MIN(penalty, content);
1973 angry = game.info.angrycitizen ? MAX(penalty-content, 0) : 0;
1974 if (penalty >= 1) {
1975 /* 'last' is when last actual malcontent appeared, will saturate
1976 * if no angry citizens */
1977 last = basis + (unhappy+angry-1)*step;
1978 if (!game.info.angrycitizen && unhappy == content) {
1979 /* Maxed out unhappy citizens, so no more penalties */
1980 next = 0;
1981 } else {
1982 /* Angry citizens can continue appearing indefinitely */
1983 next = last + step;
1984 }
1985 } else {
1986 last = 0;
1987 next = basis;
1988 }
1989
1991 /* TRANS: sentence fragment, will have text appended */
1992 PL_("Cities: %d total:",
1993 "Cities: %d total:", cities),
1994 cities);
1995 if (excess > 0) {
1996 astr_add(&str,
1997 /* TRANS: appended to "Cities: %d total:"; preserve leading
1998 * space. Pluralized in "nearest threshold of %d cities". */
1999 PL_(" %d over nearest threshold of %d city.",
2000 " %d over nearest threshold of %d cities.", last),
2001 cities - last, last);
2003 /* TRANS: Number of content [citizen(s)] ... */
2004 PL_("%d content before penalty.",
2005 "%d content before penalty.", content),
2006 content);
2008 PL_("%d additional unhappy citizen.",
2009 "%d additional unhappy citizens.", unhappy),
2010 unhappy);
2011 if (angry > 0) {
2013 PL_("%d angry citizen.",
2014 "%d angry citizens.", angry),
2015 angry);
2016 }
2017 } else {
2018 astr_add(&str,
2019 /* TRANS: appended to "Cities: %d total:"; preserve leading
2020 * space. */
2021 PL_(" not more than %d, so no empire size penalty.",
2022 " not more than %d, so no empire size penalty.", next),
2023 next);
2025 /* TRANS: %d is number of citizens */
2026 PL_("%d content per city.",
2027 "%d content per city.", content),
2028 content);
2029 }
2030 if (next >= cities && penalty < content) {
2032 PL_("With %d more city, another citizen will become "
2033 "unhappy.",
2034 "With %d more cities, another citizen will become "
2035 "unhappy.",
2036 next + 1 - cities),
2037 next + 1 - cities);
2038 } else if (next >= cities) {
2039 /* We maxed out the number of unhappy citizens, but they can get
2040 * angry instead. */
2043 PL_("With %d more city, another citizen will become "
2044 "angry.",
2045 "With %d more cities, another citizen will become "
2046 "angry.",
2047 next + 1 - cities),
2048 next + 1 - cities);
2049 } else {
2050 /* Either no Empire_Size_Step, or we maxed out on unhappy citizens
2051 * and ruleset doesn't allow angry ones. */
2053 _("More cities will not cause more unhappy citizens."));
2054 }
2055 }
2056
2057 return astr_str(&str);
2058}
2059
2060/************************************************************************/
2065const char *text_happiness_units(const struct city *pcity)
2066{
2067 int mlmax = get_city_bonus(pcity, EFT_MARTIAL_LAW_MAX);
2068 int uhcfac = get_city_bonus(pcity, EFT_UNHAPPY_FACTOR);
2069 static struct astring str = ASTRING_INIT;
2070
2071 astr_clear(&str);
2072
2073 if (mlmax > 0) {
2074 int mleach = get_city_bonus(pcity, EFT_MARTIAL_LAW_EACH);
2075 if (mlmax == 100) {
2076 astr_add_line(&str, "%s", _("Unlimited martial law in effect."));
2077 } else {
2078 astr_add_line(&str, PL_("%d military unit may impose martial law.",
2079 "Up to %d military units may impose martial "
2080 "law.", mlmax), mlmax);
2081 }
2082 astr_add_line(&str, PL_("Each military unit makes %d "
2083 "unhappy citizen content.",
2084 "Each military unit makes %d "
2085 "unhappy citizens content.",
2086 mleach), mleach);
2087 } else if (uhcfac > 0) {
2089 _("Military units in the field may cause unhappiness. "));
2090 } else {
2092 _("Military units have no happiness effect. "));
2093 }
2094
2095 return astr_str(&str);
2096}
2097
2098/************************************************************************/
2103const char *text_happiness_luxuries(const struct city *pcity)
2104{
2105 static struct astring str = ASTRING_INIT;
2106
2107 astr_clear(&str);
2108
2110 _("Luxury: %d total."),
2111 pcity->prod[O_LUXURY]);
2112
2113 return astr_str(&str);
2114}
2115
2116/************************************************************************/
2120const char *production_help(const struct universal *uni, char *buf,
2121 size_t bufsize)
2122{
2123 buf[0] = '\0';
2124 int segments = 0;
2125
2126 if (uni->kind == VUT_UTYPE) {
2127 if (uni->value.utype->helptext != NULL) {
2128 strvec_iterate(uni->value.utype->helptext, text) {
2129 if (segments++) {
2130 cat_snprintf(buf, bufsize, "\n\n");
2131 }
2132 cat_snprintf(buf, bufsize, "%s", _(text));
2134 }
2135 } else {
2136 fc_assert(uni->kind == VUT_IMPROVEMENT);
2137
2138 if (uni->value.building->helptext != NULL) {
2139 strvec_iterate(uni->value.building->helptext, text) {
2140 if (segments++) {
2141 cat_snprintf(buf, bufsize, "\n\n");
2142 }
2143 cat_snprintf(buf, bufsize, "%s", _(text));
2145 }
2146 }
2147
2148 return buf;
2149}
2150
2151/************************************************************************/
2157const char *score_tooltip(const struct player *pplayer, int score)
2158{
2159 static char buf[1024];
2160 char *relation;
2161
2162 if (client.conn.playing != NULL) {
2163 if (pplayer == client.conn.playing) {
2164 relation = _(" (us)");
2165 } else if (pplayers_allied(pplayer, client.conn.playing)) {
2166 relation = _(" (an ally)");
2167 } else if (player_diplstate_get(pplayer, client.conn.playing)->type == DS_WAR) {
2168 /* Actual enemy; don't want to use pplayers_at_war() that considers also
2169 * never met players enemies. */
2170 relation = _(" (an enemy)");
2171 } else {
2172 relation = "";
2173 }
2174 } else {
2175 relation = "";
2176 }
2177
2178 if (score >= 0) {
2179 /* TRANS: %s is a Nation */
2180 fc_snprintf(buf, sizeof(buf), _("%s%s: score %d"),
2181 nation_adjective_for_player(pplayer), relation,
2182 score);
2183 } else {
2184 fc_snprintf(buf, sizeof(buf), "%s%s",
2185 nation_adjective_for_player(pplayer), relation);
2186 }
2187
2188 return buf;
2189}
const char * action_prob_explain(const struct act_prob prob)
Definition actions.c:2083
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6703
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1740
#define action_has_result(_act_, _res_)
Definition actions.h:448
void astr_free(struct astring *astr)
Definition astring.c:153
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:267
const char * astr_build_and_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:367
void astr_add_line(struct astring *astr, const char *format,...)
Definition astring.c:299
void astr_clear(struct astring *astr)
Definition astring.c:205
void astr_add(struct astring *astr, const char *format,...)
Definition astring.c:287
#define str
Definition astring.c:76
void astr_break_lines(struct astring *astr, size_t desired_len)
Definition astring.c:318
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define ASTRING_INIT
Definition astring.h:44
const char * calendar_text(void)
Definition calendar.c:141
const char * textyear(int year)
Definition calendar.c:120
#define citizens_foreign_iterate_end
Definition citizens.h:63
#define citizens_foreign_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:58
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:722
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:1216
const char * city_name_get(const struct city *pcity)
Definition city.c:1115
int city_airlift_max(const struct city *pcity)
Definition city.c:2844
struct output_type * get_output_type(Output_type_id output)
Definition city.c:633
bool city_is_occupied(const struct city *pcity)
Definition city.c:1638
int city_tile_output(const struct city *pcity, const struct tile *ptile, bool is_celebrating, Output_type_id otype)
Definition city.c:1259
#define city_list_iterate(citylist, pcity)
Definition city.h:488
#define city_owner(_pcity_)
Definition city.h:543
#define city_list_iterate_end
Definition city.h:490
bool client_is_global_observer(void)
int get_seconds_to_new_turn(void)
int get_seconds_to_turndone(void)
struct civclient client
bool is_waiting_turn_change(void)
bool client_has_player(void)
#define client_player()
const char * concat_tile_activity_text(struct tile *ptile)
enum known_type client_tile_get_known(const struct tile *ptile)
Definition climap.c:36
void nuclear_winter_scaled(int *chance, int *rate, int max)
Definition climisc.c:338
void global_warming_scaled(int *chance, int *rate, int max)
Definition climisc.c:328
struct city * get_nearest_city(const struct unit *punit, int *sq_dist)
Definition climisc.c:1112
static struct fc_sockaddr_list * list
Definition clinet.c:102
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender)
Definition combat.c:438
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define conn_list_iterate_end
Definition connection.h:115
struct unit_list * get_units_in_focus(void)
Definition control.c:177
enum cursor_hover_state hover_state
Definition control.c:89
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:823
@ HOVER_NONE
Definition control.h:26
int city_history_gain(const struct city *pcity)
Definition culture.c:37
int nation_history_gain(const struct player *pplayer)
Definition culture.c:61
struct unit * actor_unit
Definition dialogs_g.h:54
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city * target_city
Definition dialogs_g.h:55
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
struct effect_list * effects[EFT_COUNT]
Definition effects.c:120
int get_player_output_bonus(const struct player *pplayer, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:883
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:789
int get_city_bonus_effects(struct effect_list *plist, const struct city *pcity, const struct output_type *poutput, enum effect_type effect_type)
Definition effects.c:1075
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
void get_effect_list_req_text(const struct effect_list *plist, struct astring *astr)
Definition effects.c:1225
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:186
#define extra_type_iterate(_p)
Definition extras.h:291
#define extra_type_iterate_end
Definition extras.h:297
int Tech_type_id
Definition fc_types.h:347
#define MAX_LEN_NAME
Definition fc_types.h:66
@ O_SHIELD
Definition fc_types.h:91
@ O_FOOD
Definition fc_types.h:91
@ O_TRADE
Definition fc_types.h:91
@ O_SCIENCE
Definition fc_types.h:91
@ O_LUXURY
Definition fc_types.h:91
@ O_LAST
Definition fc_types.h:91
#define LINE_BREAK
Definition fc_types.h:77
@ BORDERS_DISABLED
Definition fc_types.h:891
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * population_to_text(int thousand_citizen)
Definition game.c:714
struct civ_game game
Definition game.c:57
int current_turn_timeout(void)
Definition game.c:828
struct world wld
Definition game.c:58
int civ_population(const struct player *pplayer)
Definition game.c:69
struct city * game_city_by_number(int id)
Definition game.c:102
bool goto_get_turns(int *min, int *max)
Definition goto.c:1065
const char * ruler_title_for_player(const struct player *pplayer, char *buf, size_t buf_len)
Definition government.c:390
const char * government_name_for_player(const struct player *pplayer)
Definition government.c:153
struct city * owner
Definition citydlg.c:219
GType type
Definition repodlgs.c:1312
static const int bufsz
Definition helpdlg.c:70
bool is_improvement_visible(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define nat_x
#define nat_y
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:151
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:227
#define fc_strdup(str)
Definition mem.h:43
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
#define MAX_LEN_MSG
Definition packets.h:43
struct city_list * cities
Definition packhand.c:117
struct player * player_by_number(const int player_id)
Definition player.c:840
int player_count(void)
Definition player.c:808
int player_get_expected_income(const struct player *pplayer)
Definition player.c:1262
const char * player_name(const struct player *pplayer)
Definition player.c:886
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1364
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1179
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:317
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Definition player.c:1113
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:430
#define is_ai(plr)
Definition player.h:234
int research_goal_unknown_techs(const struct research *presearch, Tech_type_id goal)
Definition research.c:747
bool research_goal_tech_req(const struct research *presearch, Tech_type_id goal, Tech_type_id tech)
Definition research.c:797
int research_goal_bulbs_required(const struct research *presearch, Tech_type_id goal)
Definition research.c:769
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:271
struct research * research_get(const struct player *pplayer)
Definition research.c:126
#define research_players_iterate(_presearch, _pplayer)
Definition research.h:168
#define research_players_iterate_end
Definition research.h:172
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
@ SSHIP_LAUNCHED
Definition spaceship.h:85
int step
Definition specpq.h:92
#define strvec_iterate(psv, str)
#define strvec_iterate_end
Definition city.h:309
int airlift
Definition city.h:365
int prod[O_LAST]
Definition city.h:346
struct packet_game_info info
Definition game.h:89
struct packet_timeout_info tinfo
Definition game.h:91
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:156
struct strvec * helptext
Definition improvement.h:82
enum borders_mode borders
enum tech_upkeep_style tech_upkeep_style
enum airlifting_style airlifting_style
enum phase_mode_type phase_mode
bool airlift_from_always_enabled
bool airlift_to_always_enabled
enum diplstate_type type
Definition player.h:201
double success_rate
Definition spaceship.h:115
double support_rate
Definition spaceship.h:113
enum spaceship_state state
Definition spaceship.h:108
struct city_list * cities
Definition player.h:281
char username[MAX_LEN_NAME]
Definition player.h:252
struct player::@69::@72 client
struct team * team
Definition player.h:261
struct conn_list * connections
Definition player.h:298
struct player_economic economic
Definition player.h:284
int culture
Definition player.h:367
char name[MAX_LEN_NAME]
Definition player.h:251
struct player_score score
Definition player.h:283
struct nation_type * nation
Definition player.h:260
Tech_type_id researching
Definition research.h:52
struct research::@75::@77 client
int total_bulbs_prod
Definition research.h:99
int researching_cost
Definition research.h:98
int bulbs_researched
Definition research.h:53
Definition team.c:40
Definition tile.h:49
bv_extras extras
Definition tile.h:54
struct unit_list * units
Definition tile.h:57
int defense_strength
Definition unittype.h:496
int firepower
Definition unittype.h:506
struct strvec * helptext
Definition unittype.h:552
int attack_strength
Definition unittype.h:495
Definition unit.h:138
int id
Definition unit.h:145
int hp
Definition unit.h:151
int homecity
Definition unit.h:146
struct goods_type * carrying
Definition unit.h:186
int veteran
Definition unit.h:152
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int team_count(void)
Definition team.c:375
struct team * team_by_number(const int team_id)
Definition team.c:400
const char * team_name_translation(const struct team *pteam)
Definition team.c:420
#define A_UNSET
Definition tech.h:48
const char * get_infrastructure_text(bv_extras extras)
Definition terrain.c:496
const char * get_government_tooltip(void)
Definition text.c:1511
const char * text_happiness_cities(const struct city *pcity)
Definition text.c:1931
static const char * format_duration(int duration)
Definition text.c:1623
static void get_full_username(char *buf, int buflen, const struct player *pplayer)
Definition text.c:95
const char * text_happiness_nationality(const struct city *pcity)
Definition text.c:1859
#define FAR_CITY_SQUARE_DIST
Definition text.c:468
const char * score_tooltip(const struct player *pplayer, int score)
Definition text.c:2157
const char * text_happiness_wonders(const struct city *pcity)
Definition text.c:1901
bool get_units_upgrade_info(char *buf, size_t bufsz, struct unit_list *punits)
Definition text.c:1290
bool get_units_disband_info(char *buf, size_t bufsz, struct unit_list *punits)
Definition text.c:1356
static int turns_to_research_done(const struct research *presearch, int per_turn)
Definition text.c:726
const char * get_airlift_text(const struct unit_list *punits, const struct city *pdest)
Definition text.c:578
const char * get_info_label_text_popup(void)
Definition text.c:1002
const char * text_happiness_units(const struct city *pcity)
Definition text.c:2065
const char * text_happiness_luxuries(const struct city *pcity)
Definition text.c:2103
const char * science_dialog_text(void)
Definition text.c:774
static int get_bulbs_per_turn(int *pours, bool *pteam, int *ptheirs)
Definition text.c:682
const char * text_happiness_buildings(const struct city *pcity)
Definition text.c:1831
const char * get_ping_time_text(const struct player *pplayer)
Definition text.c:1654
const char * get_report_title(const char *report_name)
Definition text.c:1705
static int turns_to_tech_loss(const struct research *presearch, int per_turn)
Definition text.c:754
const char * get_nuclear_winter_tooltip(void)
Definition text.c:1484
const char * get_score_text(const struct player *pplayer)
Definition text.c:1683
const char * get_science_target_text(double *percent)
Definition text.c:853
const char * get_bulb_tooltip(void)
Definition text.c:1400
const char * get_timeout_label_text(void)
Definition text.c:1590
const char * get_nearest_city_text(struct city *pcity, int sq_dist)
Definition text.c:474
const char * get_act_sel_action_custom_text(struct action *paction, const struct act_prob prob, const struct unit *actor_unit, const struct city *target_city)
Definition text.c:1743
const char * popup_info_text(struct tile *ptile)
Definition text.c:146
const char * unit_description(struct unit *punit)
Definition text.c:508
static void get_full_nation(char *buf, int buflen, const struct player *pplayer)
Definition text.c:119
const char * get_global_warming_tooltip(void)
Definition text.c:1457
const char * get_tile_output_text(const struct tile *ptile)
Definition text.c:62
const char * get_info_label_text(bool moreinfo)
Definition text.c:950
const char * production_help(const struct universal *uni, char *buf, size_t bufsize)
Definition text.c:2120
static int turns_per_advance(const struct research *presearch, int per_turn)
Definition text.c:741
const char * get_science_goal_text(Tech_type_id goal)
Definition text.c:899
const char * get_unit_info_label_text2(struct unit_list *punits, int linebreaks)
Definition text.c:1112
const char * get_unit_info_label_text1(struct unit_list *punits)
Definition text.c:1087
const char * get_spaceship_descr(struct player_spaceship *pship)
Definition text.c:1533
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1820
bool tile_has_visible_extra(const struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:902
const char * tile_get_info_text(const struct tile *ptile, bool include_nuisances, int linebreaks)
Definition tile.c:756
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:87
@ TILE_UNKNOWN
Definition tile.h:35
#define tile_continent(_tile)
Definition tile.h:91
#define tile_owner(_tile)
Definition tile.h:95
bool can_cities_trade(const struct city *pc1, const struct city *pc2)
int trade_base_between_cities(const struct city *pc1, const struct city *pc2)
int get_caravan_enter_city_trade_bonus(const struct city *pc1, const struct city *pc2, struct goods_type *pgood, const bool establish_trade)
bool can_establish_trade_route(const struct city *pc1, const struct city *pc2)
const struct unit_type * utype
Definition fc_types.h:604
const struct impr_type * building
Definition fc_types.h:598
enum unit_upgrade_result unit_upgrade_info(const struct civ_map *nmap, const struct unit *punit, char *buf, size_t bufsz)
Definition unit.c:2035
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1271
enum unit_airlift_result test_unit_can_airlift_to(const struct civ_map *nmap, const struct player *restriction, const struct unit *punit, const struct city *pdest_city)
Definition unit.c:83
int unit_bribe_cost(struct unit *punit, struct player *briber)
Definition unit.c:2288
void unit_upkeep_astr(const struct unit *punit, struct astring *astr)
Definition unit.c:1257
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:328
void unit_activity_astr(const struct unit *punit, struct astring *astr)
Definition unit.c:1174
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1972
#define unit_tile(_pu)
Definition unit.h:395
#define unit_owner(_pu)
Definition unit.h:394
@ UU_OK
Definition unit.h:61
#define unit_home(_pu_)
Definition unit.h:393
unit_airlift_result
Definition unit.h:72
@ AR_SRC_NO_FLIGHTS
Definition unit.h:84
@ AR_OK_SRC_UNKNOWN
Definition unit.h:75
@ AR_OK_DST_UNKNOWN
Definition unit.h:76
@ AR_NO_MOVES
Definition unit.h:78
@ AR_BAD_DST_CITY
Definition unit.h:83
@ AR_NOT_IN_CITY
Definition unit.h:81
@ AR_OCCUPIED
Definition unit.h:80
@ AR_OK
Definition unit.h:74
@ AR_DST_NO_FLIGHTS
Definition unit.h:85
@ AR_WRONG_UNITTYPE
Definition unit.h:79
@ AR_BAD_SRC_CITY
Definition unit.h:82
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const char * utype_veteran_name_translation(const struct unit_type *punittype, int level)
Definition unittype.c:2658
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1621
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1755
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443
int unit_upgrade_price(const struct player *pplayer, const struct unit_type *from, const struct unit_type *to)
Definition unittype.c:1783
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
#define unit_type_iterate(_p)
Definition unittype.h:841
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:848