Freeciv-3.3: /fast/freeciv/nightly/main/client/text.c Source File

Freeciv-3.3

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