Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/cityrepdata.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
cityrepdata.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 <errno.h>
19#include <math.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24/* utility */
25#include "fcintl.h"
26#include "log.h"
27#include "support.h"
28
29/* common */
30#include "city.h"
31#include "culture.h"
32#include "game.h"
33#include "map.h"
34#include "specialist.h"
35#include "unitlist.h"
36
37/* agents */
38#include "cma_fec.h"
39
40/* client */
41#include "citydlg_common.h" /* city_production_cost_str() */
42#include "options.h"
43
44#include "cityrepdata.h"
45
46/********************************************************************/
52 static const char *cr_entry_cityname(const struct city *pcity,
53 const void *data)
54{
55 /* We used to truncate the name to 14 bytes. This should not be needed
56 * in any modern GUI library and may give an invalid string if a
57 * multibyte character is clipped. */
58 return city_name_get(pcity);
59}
60
61/********************************************************************/
64 static const char *cr_entry_nation(const struct city *pcity,
65 const void *data)
66{
67 return nation_adjective_for_player(city_owner(pcity));
68}
69
70/********************************************************************/
74 static const char *cr_entry_size(const struct city *pcity,
75 const void *data)
76{
77 static char buf[8];
78
79 fc_snprintf(buf, sizeof(buf), "%2d", city_size_get(pcity));
80 return buf;
81}
82
83/********************************************************************/
88 static const char *cr_entry_hstate_concise(const struct city *pcity,
89 const void *data)
90{
91 static char buf[4];
92 fc_snprintf(buf, sizeof(buf), "%s",
93 (city_celebrating(pcity) ? "*"
94 : (city_unhappy(pcity) ? "X" : " ")));
95 return buf;
96}
97
98/********************************************************************/
103 static const char *cr_entry_hstate_verbose(const struct city *pcity,
104 const void *data)
105{
106 static char buf[32];
107
108 fc_snprintf(buf, sizeof(buf), "%s",
109 (city_celebrating(pcity) ? Q_("?city_state:Celebrating")
110 : (city_unhappy(pcity) ? Q_("?city_state:Disorder")
111 : Q_("?city_state:Peace"))));
112 return buf;
113}
114
115/********************************************************************/
120 static const char *cr_entry_workers(const struct city *pcity,
121 const void *data)
122{
123 static char buf[32];
124
125 fc_snprintf(buf, sizeof(buf), "%d/%d/%d/%d",
126 pcity->feel[CITIZEN_HAPPY][FEELING_FINAL],
127 pcity->feel[CITIZEN_CONTENT][FEELING_FINAL],
128 pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL],
129 pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]);
130 return buf;
131}
132
133/********************************************************************/
138 static const char *cr_entry_happy(const struct city *pcity,
139 const void *data)
140{
141 static char buf[8];
142 fc_snprintf(buf, sizeof(buf), "%2d",
143 pcity->feel[CITIZEN_HAPPY][FEELING_FINAL]);
144 return buf;
145}
146
147/********************************************************************/
150 static const char *cr_entry_culture(const struct city *pcity,
151 const void *data)
152{
153 static char buf[8];
154 fc_snprintf(buf, sizeof(buf), "%3d", pcity->client.culture);
155 return buf;
156}
157
158/********************************************************************/
161 static const char *cr_entry_history(const struct city *pcity,
162 const void *data)
163{
164 static char buf[20];
165 int perturn = city_history_gain(pcity);
166
167 if (perturn != 0) {
168 fc_snprintf(buf, sizeof(buf), "%3d (%+d)", pcity->history, perturn);
169 } else {
170 fc_snprintf(buf, sizeof(buf), "%3d", pcity->history);
171 }
172 return buf;
173}
174
175/********************************************************************/
178 static const char *cr_entry_performance(const struct city *pcity,
179 const void *data)
180{
181 static char buf[8];
182
183 /*
184 * Infer the actual performance component of culture from server-supplied
185 * values, rather than using the client's guess at EFT_PERFORMANCE.
186 * XXX: if culture ever gets more complicated than history+performance,
187 * this will need revising, possibly to use a server-supplied value.
188 */
189 fc_snprintf(buf, sizeof(buf), "%3d", pcity->client.culture - pcity->history);
190 return buf;
191}
192
193/********************************************************************/
198 static const char *cr_entry_content(const struct city *pcity,
199 const void *data)
200{
201 static char buf[8];
202 fc_snprintf(buf, sizeof(buf), "%2d",
203 pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]);
204 return buf;
205}
206
207/********************************************************************/
212 static const char *cr_entry_unhappy(const struct city *pcity,
213 const void *data)
214{
215 static char buf[8];
216 fc_snprintf(buf, sizeof(buf), "%2d",
217 pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]);
218 return buf;
219}
220
221/********************************************************************/
226 static const char *cr_entry_angry(const struct city *pcity,
227 const void *data)
228{
229 static char buf[8];
230 fc_snprintf(buf, sizeof(buf), "%2d",
231 pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]);
232 return buf;
233}
234
235/********************************************************************/
240 static const char *cr_entry_specialists(const struct city *pcity,
241 const void *data)
242{
243 return specialists_string(pcity->specialists);
244}
245
246/********************************************************************/
251 static const char *cr_entry_specialist(const struct city *pcity,
252 const void *data)
253{
254 static char buf[8];
255 const struct specialist *sp = data;
256
257 fc_snprintf(buf, sizeof(buf), "%2d",
258 pcity->specialists[specialist_index(sp)]);
259 return buf;
260}
261
262/********************************************************************/
267 static const char *cr_entry_attack(const struct city *pcity,
268 const void *data)
269{
270 static char buf[32];
271 int attack_best[4] = {-1, -1, -1, -1}, i;
272
273 unit_list_iterate(pcity->tile->units, punit) {
274 /* What about allied units? Should we just count them? */
275 attack_best[3] = unit_type_get(punit)->attack_strength;
276
277 /* Now that the element is appended to the end of the list, we simply
278 do an insertion sort. */
279 for (i = 2; i >= 0 && attack_best[i] < attack_best[i + 1]; i--) {
280 int tmp = attack_best[i];
281 attack_best[i] = attack_best[i + 1];
282 attack_best[i + 1] = tmp;
283 }
284 } unit_list_iterate_end;
285
286 buf[0] = '\0';
287 for (i = 0; i < 3; i++) {
288 if (attack_best[i] >= 0) {
289 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
290 attack_best[i]);
291 } else {
292 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
293 }
294 }
295
296 return buf;
297}
298
299/********************************************************************/
304 static const char *cr_entry_defense(const struct city *pcity,
305 const void *data)
306{
307 static char buf[32];
308 int defense_best[4] = {-1, -1, -1, -1}, i;
309
310 unit_list_iterate(pcity->tile->units, punit) {
311 /* What about allied units? Should we just count them? */
312 defense_best[3] = unit_type_get(punit)->defense_strength;
313
314 /* Now that the element is appended to the end of the list, we simply
315 do an insertion sort. */
316 for (i = 2; i >= 0 && defense_best[i] < defense_best[i + 1]; i--) {
317 int tmp = defense_best[i];
318
319 defense_best[i] = defense_best[i + 1];
320 defense_best[i + 1] = tmp;
321 }
322 } unit_list_iterate_end;
323
324 buf[0] = '\0';
325 for (i = 0; i < 3; i++) {
326 if (defense_best[i] >= 0) {
327 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
328 defense_best[i]);
329 } else {
330 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
331 }
332 }
333
334 return buf;
335}
336
337/********************************************************************/
342 static const char *cr_entry_supported(const struct city *pcity,
343 const void *data)
344{
345 static char buf[8];
346 int num_supported = unit_list_size(pcity->units_supported);
347
348 fc_snprintf(buf, sizeof(buf), "%2d", num_supported);
349
350 return buf;
351}
352
353/********************************************************************/
358 static const char *cr_entry_present(const struct city *pcity,
359 const void *data)
360{
361 static char buf[8];
362 int num_present = unit_list_size(pcity->tile->units);
363
364 fc_snprintf(buf, sizeof(buf), "%2d", num_present);
365
366 return buf;
367}
368
369/********************************************************************/
374 static const char *cr_entry_resources(const struct city *pcity,
375 const void *data)
376{
377 static char buf[32];
378 fc_snprintf(buf, sizeof(buf), "%d/%d/%d",
379 pcity->surplus[O_FOOD],
380 pcity->surplus[O_SHIELD],
381 pcity->surplus[O_TRADE]);
382 return buf;
383}
384
385/********************************************************************/
390 static const char *cr_entry_foodplus(const struct city *pcity,
391 const void *data)
392{
393 static char buf[8];
394 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_FOOD]);
395 return buf;
396}
397
398/********************************************************************/
403 static const char *cr_entry_prodplus(const struct city *pcity,
404 const void *data)
405{
406 static char buf[8];
407 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_SHIELD]);
408 return buf;
409}
410
411/********************************************************************/
416 static const char *cr_entry_tradeplus(const struct city *pcity,
417 const void *data)
418{
419 static char buf[8];
420 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_TRADE]);
421 return buf;
422}
423
424/********************************************************************/
429 static const char *cr_entry_output(const struct city *pcity,
430 const void *data)
431{
432 static char buf[32];
433 int goldie = pcity->surplus[O_GOLD];
434
435 fc_snprintf(buf, sizeof(buf), "%3d/%d/%d",
436 goldie, pcity->prod[O_LUXURY], pcity->prod[O_SCIENCE]);
437 return buf;
438}
439
440/********************************************************************/
445 static const char *cr_entry_gold(const struct city *pcity,
446 const void *data)
447{
448 static char buf[8];
449
450 if (pcity->surplus[O_GOLD] > 0) {
451 fc_snprintf(buf, sizeof(buf), "+%d", pcity->surplus[O_GOLD]);
452 } else {
453 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_GOLD]);
454 }
455 return buf;
456}
457
458/********************************************************************/
463 static const char *cr_entry_luxury(const struct city *pcity,
464 const void *data)
465{
466 static char buf[8];
467 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_LUXURY]);
468 return buf;
469}
470
471/********************************************************************/
476 static const char *cr_entry_science(const struct city *pcity,
477 const void *data)
478{
479 static char buf[8];
480 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_SCIENCE]);
481 return buf;
482}
483
484/********************************************************************/
489 static const char *cr_entry_growturns(const struct city *pcity,
490 const void *data)
491{
492 int turns = city_turns_to_grow(pcity);
493 char buffer[8];
494 static char buf[32];
495
496 if (turns == FC_INFINITY) {
497 /* 'never' wouldn't be easily translatable here. */
498 fc_snprintf(buffer, sizeof(buffer), "---");
499 } else {
500 /* Shrinking cities get a negative value. */
501 fc_snprintf(buffer, sizeof(buffer), "%4d", turns);
502 }
503 fc_snprintf(buf, sizeof(buf), "%s (%d/%d)",
504 buffer, pcity->food_stock,
505 city_granary_size(city_size_get(pcity)));
506 return buf;
507}
508
509/********************************************************************/
514 static const char *cr_entry_pollution(const struct city *pcity,
515 const void *data)
516{
517 static char buf[8];
518 fc_snprintf(buf, sizeof(buf), "%3d", pcity->pollution);
519 return buf;
520}
521
522/********************************************************************/
527 static const char *cr_entry_trade_routes(const struct city *pcity,
528 const void *data)
529{
530 static char buf[16];
531 int num = 0, value = 0;
532
533 trade_routes_iterate(pcity, proute) {
534 num++;
535 value += proute->value;
536 } trade_routes_iterate_end;
537
538 if (0 == num) {
539 sz_strlcpy(buf, "0");
540 } else {
541 fc_snprintf(buf, sizeof(buf), "%d (+%d)", num, value);
542 }
543 return buf;
544}
545
546/********************************************************************/
551 static const char *cr_entry_build_slots(const struct city *pcity,
552 const void *data)
553{
554 static char buf[8];
555 fc_snprintf(buf, sizeof(buf), "%3d", city_build_slots(pcity));
556 return buf;
557}
558
559/********************************************************************/
564 static const char *cr_entry_building(const struct city *pcity,
565 const void *data)
566{
567 static char buf[192];
568 const char *from_worklist =
569 worklist_is_empty(&pcity->worklist) ? "" :
570 gui_options.concise_city_production ? "+" : _("(worklist)");
571
572 if (city_production_has_flag(pcity, IF_GOLD)) {
573 fc_snprintf(buf, sizeof(buf), "%s (%d)%s",
574 city_production_name_translation(pcity),
575 MAX(0, pcity->surplus[O_SHIELD]), from_worklist);
576 } else {
577 fc_snprintf(buf, sizeof(buf), "%s (%d/%s)%s",
578 city_production_name_translation(pcity),
579 pcity->shield_stock,
580 city_production_cost_str(pcity),
581 from_worklist);
582 }
583
584 return buf;
585}
586
587/********************************************************************/
592 static const char *cr_entry_build_cost(const struct city *pcity,
593 const void *data)
594{
595 char bufone[8];
596 char buftwo[8];
597 static char buf[32];
598 int price;
599 int turns;
600
601 if (city_production_has_flag(pcity, IF_GOLD)) {
602 fc_snprintf(buf, sizeof(buf), "*");
603 return buf;
604 }
605 price = pcity->client.buy_cost;
606 turns = city_production_turns_to_build(pcity, TRUE);
607
608 if (price > 99999) {
609 fc_snprintf(bufone, sizeof(bufone), "---");
610 } else {
611 fc_snprintf(bufone, sizeof(bufone), "%d", price);
612 }
613 if (turns > 999) {
614 fc_snprintf(buftwo, sizeof(buftwo), "--");
615 } else {
616 fc_snprintf(buftwo, sizeof(buftwo), "%3d", turns);
617 }
618 fc_snprintf(buf, sizeof(buf), "%s/%s", buftwo, bufone);
619 return buf;
620}
621
622/********************************************************************/
627 static const char *cr_entry_corruption(const struct city *pcity,
628 const void *data)
629{
630 static char buf[8];
631 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_TRADE]));
632 return buf;
633}
634
635/********************************************************************/
640 static const char *cr_entry_waste(const struct city *pcity,
641 const void *data)
642{
643 static char buf[8];
644 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_SHIELD]));
645 return buf;
646}
647
648/********************************************************************/
653 static const char *cr_entry_plague_risk(const struct city *pcity,
654 const void *data)
655{
656 static char buf[8];
657 if (!game.info.illness_on) {
658 fc_snprintf(buf, sizeof(buf), " -.-");
659 } else {
660 fc_snprintf(buf, sizeof(buf), "%4.1f",
661 (float)city_illness_calc(pcity, NULL, NULL, NULL, NULL)/10.0);
662 }
663 return buf;
664}
665
666/********************************************************************/
669 static const char *cr_entry_continent(const struct city *pcity,
670 const void *data)
671{
672 static char buf[8];
673 fc_snprintf(buf, sizeof(buf), "%3d", pcity->tile->continent);
674 return buf;
675}
676
677/********************************************************************/
682 static const char *cr_entry_cma(const struct city *pcity,
683 const void *data)
684{
685 return cmafec_get_short_descr_of_city(pcity);
686}
687
688/* City report options (which columns get shown)
689 * To add a new entry, you should just have to:
690 * - add a function like those above
691 * - add an entry in the base_city_report_specs[] table
692 */
693
694/* This generates the function name and the tagname: */
695#define FUNC_TAG(var) cr_entry_##var, #var
696
697 static const struct city_report_spec base_city_report_specs[] = {
698 { TRUE, -15, NULL, N_("?city:Name"), N_("City Name"),
699 NULL, FUNC_TAG(cityname) },
700 { FALSE, -15, NULL, N_("Nation"), N_("Nation"),
701 NULL, FUNC_TAG(nation) },
702 { TRUE, 2, NULL, N_("?size [short]:Sz"), N_("Size"),
703 NULL, FUNC_TAG(size) },
704 { TRUE, -8, NULL, N_("State"), N_("Celebrating/Peace/Disorder"),
705 NULL, FUNC_TAG(hstate_verbose) },
706 { FALSE, 1, NULL, NULL, N_("Concise *=Celebrating, X=Disorder"),
707 NULL, FUNC_TAG(hstate_concise) },
708
709 { FALSE, 2, NULL, N_("?Happy workers:H"), N_("Workers: Happy"),
710 NULL, FUNC_TAG(happy) },
711 { FALSE, 2, NULL, N_("?Content workers:C"), N_("Workers: Content"),
712 NULL, FUNC_TAG(content) },
713 { FALSE, 2, NULL, N_("?Unhappy workers:U"), N_("Workers: Unhappy"),
714 NULL, FUNC_TAG(unhappy) },
715 { FALSE, 2, NULL, N_("?Angry workers:A"), N_("Workers: Angry"),
716 NULL, FUNC_TAG(angry) },
717 { TRUE, 10, N_("?city:Workers"),
718 N_("?happy/content/unhappy/angry:H/C/U/A"),
719 N_("Workers: Happy, Content, Unhappy, Angry"),
720 NULL, FUNC_TAG(workers) },
721
722 { FALSE, 8, N_("Best"), N_("attack"),
723 N_("Best attacking units"), NULL, FUNC_TAG(attack)},
724 { FALSE, 8, N_("Best"), N_("defense"),
725 N_("Best defending units"), NULL, FUNC_TAG(defense)},
726 { FALSE, 2, N_("Units"),
727 /* TRANS: Header "Number of units inside city" */
728 N_("?Present (units):Here"),
729 N_("Number of units present"), NULL, FUNC_TAG(present) },
730 { FALSE, 2, N_("Units"),
731 /* TRANS: Header "Number of units supported by given city" */
732 N_("?Supported (units):Owned"),
733 N_("Number of units supported"), NULL, FUNC_TAG(supported) },
734
735 { /* TRANS: Header "It will take this many turns before city grows" */
736 TRUE, 14, N_("?food (population):Grow"),
737 N_("?Stock/Target:(Have/Need)"),
738 N_("Turns until growth/famine"),
739 NULL, FUNC_TAG(growturns) },
740
741 { TRUE, 10, N_("Surplus"), N_("?food/production/trade:F/P/T"),
742 N_("Surplus: Food, Production, Trade"),
743 NULL, FUNC_TAG(resources) },
744 { FALSE, 3, NULL, N_("?Food surplus [short]:+F"), N_("Surplus: Food"),
745 NULL, FUNC_TAG(foodplus) },
746 { FALSE, 3, NULL, N_("?Production surplus [short]:+P"),
747 N_("Surplus: Production"), NULL, FUNC_TAG(prodplus) },
748 { FALSE, 3, NULL, N_("?Production loss (waste) [short]:-P"),
749 N_("Waste"), NULL, FUNC_TAG(waste) },
750 { FALSE, 3, NULL, N_("?Trade surplus [short]:+T"), N_("Surplus: Trade"),
751 NULL, FUNC_TAG(tradeplus) },
752 { FALSE, 3, NULL, N_("?Trade loss (corruption) [short]:-T"),
753 N_("Corruption"), NULL, FUNC_TAG(corruption) },
754
755 { TRUE, 10, N_("Economy"), N_("?gold/luxury/science:G/L/S"),
756 N_("Economy: Gold, Luxuries, Science"),
757 NULL, FUNC_TAG(output) },
758 { FALSE, 3, NULL, N_("?Gold:G"), N_("Economy: Gold"),
759 NULL, FUNC_TAG(gold) },
760 { FALSE, 3, NULL, N_("?Luxury:L"), N_("Economy: Luxury"),
761 NULL, FUNC_TAG(luxury) },
762 { FALSE, 3, NULL, N_("?Science:S"), N_("Economy: Science"),
763 NULL, FUNC_TAG(science) },
764 { FALSE, 3, NULL, N_("?Culture:Clt"), N_("Culture (History+Performance)"),
765 NULL, FUNC_TAG(culture) },
766 { FALSE, 3, NULL, N_("?History:Hst"),
767 N_("Culture: History (and gain per turn)"),
768 NULL, FUNC_TAG(history) },
769 { FALSE, 3, NULL, N_("?Performance:Prf"), N_("Culture: Performance"),
770 NULL, FUNC_TAG(performance) },
771 { FALSE, 3, NULL, N_("?Continent:C"), N_("Continent number"),
772 NULL, FUNC_TAG(continent) },
773 { FALSE, 1, N_("?number_trade_routes:n"),
774 N_("?number_trade_routes:R"),
775 N_("Number (and total value) of trade routes"),
776 NULL, FUNC_TAG(trade_routes) },
777 { FALSE, 3, NULL, N_("?pollution [short]:Pol"), N_("?stats:Pollution"),
778 NULL, FUNC_TAG(pollution) },
779 { FALSE, 4, N_("?plague risk [short]:Pla"), N_("(%)"),
780 N_("Plague risk per turn"),
781 NULL, FUNC_TAG(plague_risk) },
782 { FALSE, 15, NULL, N_("?cma:Governor"), N_("Citizen Governor"),
783 NULL, FUNC_TAG(cma) },
784
785 /* TRANS: "BS" = "build slots" */
786 { FALSE, 3, NULL, N_("BS"), N_("Maximum units buildable per turn"),
787 NULL, FUNC_TAG(build_slots) },
788 { TRUE, 9, N_("Production"), N_("Turns/Buy"),
789 /* N_("Turns or gold to complete production"), future menu needs translation */
790 N_("Production"),
791 NULL, FUNC_TAG(build_cost) },
792 { TRUE, 0, N_("Currently Building"),
793 N_("?Stock/Target:(Have/Need)"),
794 N_("Currently Building"),
795 NULL, FUNC_TAG(building) }
796};
797
798 struct city_report_spec *city_report_specs;
799 static int num_creport_cols;
800
801/********************************************************************/
804 int num_city_report_spec(void)
805{
806 return num_creport_cols;
807}
808
809/********************************************************************/
812 bool *city_report_spec_show_ptr(int i)
813{
814 return &(city_report_specs[i].show);
815}
816
817/********************************************************************/
820 const char *city_report_spec_tagname(int i)
821{
822 return city_report_specs[i].tagname;
823}
824
825/********************************************************************/
830 void init_city_report_game_data(void)
831{
832 static char sp_explanation[SP_MAX][128];
833 static char sp_explanations[SP_MAX*128];
834 struct city_report_spec *p;
835 int i;
836
837 num_creport_cols = ARRAY_SIZE(base_city_report_specs)
838 + specialist_count() + 1;
839 city_report_specs
840 = fc_realloc(city_report_specs,
841 num_creport_cols * sizeof(*city_report_specs));
842 p = &city_report_specs[0];
843
844 fc_snprintf(sp_explanations, sizeof(sp_explanations),
845 "%s", _("Specialists: "));
846 specialist_type_iterate(sp) {
847 struct specialist *s = specialist_by_number(sp);
848
849 p->show = FALSE;
850 p->width = 2;
851 p->title1 = Q_("?specialist:S");
852 p->title2 = specialist_abbreviation_translation(s);
853 fc_snprintf(sp_explanation[sp], sizeof(sp_explanation[sp]),
854 _("Specialists: %s"), specialist_plural_translation(s));
855 cat_snprintf(sp_explanations, sizeof(sp_explanations),
856 "%s%s", (sp == 0) ? "" : ", ",
857 specialist_plural_translation(s));
858 p->explanation = sp_explanation[sp];
859 p->data = s;
860 p->func = cr_entry_specialist;
861 p->tagname = specialist_rule_name(s);
862 p++;
863 } specialist_type_iterate_end;
864
865 /* Summary column for all specialists. */
866 {
867 static char sp_summary[128];
868
869 p->show = FALSE;
870 p->width = MAX(7, specialist_count() * 2 - 1);
871 p->title1 = _("Special");
872 fc_snprintf(sp_summary, sizeof(sp_summary),
873 "%s", specialists_abbreviation_string());
874 p->title2 = sp_summary;
875 p->explanation = sp_explanations;
876 p->data = NULL;
877 p->func = cr_entry_specialists;
878 p->tagname = "specialists";
879 p++;
880 }
881
882 memcpy(p, base_city_report_specs,
883 sizeof(base_city_report_specs));
884
885 for (i = 0; i < ARRAY_SIZE(base_city_report_specs); i++) {
886 if (p->title1) {
887 p->title1 = Q_(p->title1);
888 }
889 if (p->title2) {
890 p->title2 = Q_(p->title2);
891 }
892 p->explanation = Q_(p->explanation);
893 p++;
894 }
895
896 fc_assert(NUM_CREPORT_COLS == ARRAY_SIZE(base_city_report_specs)
897 + specialist_count() + 1);
898}
899
900/************************************************************************
901 The following several functions allow intelligent sorting city report
902 fields by column. This doesn't necessarily do the right thing, but
903 it's better than sorting alphabetically.
904
905 The GUI gives us two values to compare (as strings). We try to split
906 them into an array of numeric and string fields, then we compare
907 lexicographically. Two numeric fields are compared in the obvious
908 way, two character fields are compared alphabetically.
909 Arbitrarily, a numeric field is sorted before a character field
910 (for "justification" note that numbers are before letters
911 in the ASCII table).
912************************************************************************/
913
914/* A datum is one short string, or one number.
915 A datum_vector represents a long string of alternating strings and
916 numbers. */
917 struct datum {
918 union {
919 float numeric_value;
920 char *string_value;
921 } val;
922 bool is_numeric;
923};
924#define SPECVEC_TAG datum
925#include "specvec.h"
926
927/********************************************************************/
930 static void init_datum_string(struct datum *dat, const char *left,
931 const char *right)
932{
933 int len = right - left;
934
935 dat->is_numeric = FALSE;
936 dat->val.string_value = fc_malloc(len + 1);
937 memcpy(dat->val.string_value, left, len);
938 dat->val.string_value[len] = 0;
939}
940
941/********************************************************************/
945 static void init_datum_number(struct datum *dat, float val)
946{
947 dat->is_numeric = TRUE;
948 dat->val.numeric_value = val;
949}
950
951/********************************************************************/
955 static void free_datum(struct datum *dat)
956{
957 if (!dat->is_numeric) {
958 free(dat->val.string_value);
959 }
960}
961
962/********************************************************************/
968 static int datum_compare(const struct datum *a, const struct datum *b)
969{
970 if (a->is_numeric == b->is_numeric) {
971 if (a->is_numeric) {
972 if (a->val.numeric_value == b->val.numeric_value) {
973 return 0;
974 } else if (a->val.numeric_value < b->val.numeric_value) {
975 return -1;
976 } else if (a->val.numeric_value > b->val.numeric_value) {
977 return +1;
978 } else {
979 return 0; /* shrug */
980 }
981 } else {
982 return strcmp(a->val.string_value, b->val.string_value);
983 }
984 } else {
985 if (a->is_numeric) {
986 return -1;
987 } else {
988 return 1;
989 }
990 }
991}
992
993/********************************************************************/
996 static int data_compare(const struct datum_vector *a,
997 const struct datum_vector *b)
998{
999 int i, n;
1000
1001 n = MIN(a->size, b->size);
1002
1003 for (i = 0; i < n; i++) {
1004 int cmp = datum_compare(&a->p[i], &b->p[i]);
1005
1006 if (cmp != 0) {
1007 return cmp;
1008 }
1009 }
1010
1011 /* The first n fields match; whoever has more fields goes last.
1012 If they have equal numbers, the two really are equal. */
1013 return a->size - b->size;
1014}
1015
1016/********************************************************************/
1019 static void split_string(struct datum_vector *data, const char *str)
1020{
1021 const char *string_start;
1022
1023 datum_vector_init(data);
1024 string_start = str;
1025 while (*str) {
1026 char *endptr;
1027 float value;
1028
1029 errno = 0;
1030 value = strtof(str, &endptr);
1031 if (errno != 0 || endptr == str || !isfinite(value)) {
1032 /* that wasn't a sensible number; go on */
1033 str++;
1034 } else {
1035 /* that was a number, so stop the string we were parsing, add
1036 it (unless it's empty), then add the number we just parsed */
1037 struct datum d;
1038
1039 if (str != string_start) {
1040 init_datum_string(&d, string_start, str);
1041 datum_vector_append(data, d);
1042 }
1043
1044 init_datum_number(&d, value);
1045 datum_vector_append(data, d);
1046
1047 /* finally, update the string position pointers */
1048 string_start = str = endptr;
1049 }
1050 }
1051
1052 /* if we have anything leftover then it's a string */
1053 if (str != string_start) {
1054 struct datum d;
1055
1056 init_datum_string(&d, string_start, str);
1057 datum_vector_append(data, d);
1058 }
1059}
1060
1061/********************************************************************/
1064 static void free_data(struct datum_vector *data)
1065{
1066 int i;
1067
1068 for (i = 0; i < data->size; i++) {
1069 free_datum(&data->p[i]);
1070 }
1071 datum_vector_free(data);
1072}
1073
1074/********************************************************************/
1077 int cityrepfield_compare(const char *str1, const char *str2)
1078{
1079 struct datum_vector data1, data2;
1080 int retval;
1081
1082 if (str1 == str2) {
1083 return 0;
1084 } else if (NULL == str1) {
1085 return 1;
1086 } else if (NULL == str2) {
1087 return -1;
1088 }
1089
1090 split_string(&data1, str1);
1091 split_string(&data2, str2);
1092
1093 retval = data_compare(&data1, &data2);
1094
1095 free_data(&data1);
1096 free_data(&data2);
1097
1098 return retval;
1099}
1100
1101/********************************************************************/
1104 bool can_city_sell_universal(const struct city *pcity,
1105 const struct universal *target)
1106{
1107 return target->kind == VUT_IMPROVEMENT
1108 && can_city_sell_building(pcity, target->value.building);
1109}
str
#define str
Definition astring.c:76
n
#define n
Definition astring.c:77
city_granary_size
int city_granary_size(int city_size)
Definition city.c:2095
city_build_slots
int city_build_slots(const struct city *pcity)
Definition city.c:2825
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1106
city_production_has_flag
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Definition city.c:711
city_production_turns_to_build
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:804
city_unhappy
bool city_unhappy(const struct city *pcity)
Definition city.c:1591
city_celebrating
bool city_celebrating(const struct city *pcity)
Definition city.c:1610
city_illness_calc
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2763
cmp
static int cmp(int v1, int v2)
Definition city.c:319
city_turns_to_grow
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1961
city_production_name_translation
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:694
city.h
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
CITIZEN_ANGRY
@ CITIZEN_ANGRY
Definition city.h:263
CITIZEN_HAPPY
@ CITIZEN_HAPPY
Definition city.h:260
CITIZEN_CONTENT
@ CITIZEN_CONTENT
Definition city.h:261
CITIZEN_UNHAPPY
@ CITIZEN_UNHAPPY
Definition city.h:262
city_owner
#define city_owner(_pcity_)
Definition city.h:543
FEELING_FINAL
@ FEELING_FINAL
Definition city.h:276
city_production_cost_str
char * city_production_cost_str(const struct city *pcity)
Definition citydlg_common.c:224
citydlg_common.h
cr_entry_hstate_concise
static const char * cr_entry_hstate_concise(const struct city *pcity, const void *data)
Definition cityrepdata.c:88
cr_entry_tradeplus
static const char * cr_entry_tradeplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:416
cr_entry_specialist
static const char * cr_entry_specialist(const struct city *pcity, const void *data)
Definition cityrepdata.c:251
cr_entry_present
static const char * cr_entry_present(const struct city *pcity, const void *data)
Definition cityrepdata.c:358
cr_entry_hstate_verbose
static const char * cr_entry_hstate_verbose(const struct city *pcity, const void *data)
Definition cityrepdata.c:103
num_city_report_spec
int num_city_report_spec(void)
Definition cityrepdata.c:804
init_datum_string
static void init_datum_string(struct datum *dat, const char *left, const char *right)
Definition cityrepdata.c:930
cr_entry_nation
static const char * cr_entry_nation(const struct city *pcity, const void *data)
Definition cityrepdata.c:64
cr_entry_luxury
static const char * cr_entry_luxury(const struct city *pcity, const void *data)
Definition cityrepdata.c:463
cr_entry_gold
static const char * cr_entry_gold(const struct city *pcity, const void *data)
Definition cityrepdata.c:445
cr_entry_building
static const char * cr_entry_building(const struct city *pcity, const void *data)
Definition cityrepdata.c:564
cr_entry_culture
static const char * cr_entry_culture(const struct city *pcity, const void *data)
Definition cityrepdata.c:150
split_string
static void split_string(struct datum_vector *data, const char *str)
Definition cityrepdata.c:1019
cr_entry_plague_risk
static const char * cr_entry_plague_risk(const struct city *pcity, const void *data)
Definition cityrepdata.c:653
cr_entry_trade_routes
static const char * cr_entry_trade_routes(const struct city *pcity, const void *data)
Definition cityrepdata.c:527
init_city_report_game_data
void init_city_report_game_data(void)
Definition cityrepdata.c:830
cr_entry_size
static const char * cr_entry_size(const struct city *pcity, const void *data)
Definition cityrepdata.c:74
free_data
static void free_data(struct datum_vector *data)
Definition cityrepdata.c:1064
cr_entry_foodplus
static const char * cr_entry_foodplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:390
cr_entry_science
static const char * cr_entry_science(const struct city *pcity, const void *data)
Definition cityrepdata.c:476
data_compare
static int data_compare(const struct datum_vector *a, const struct datum_vector *b)
Definition cityrepdata.c:996
cr_entry_pollution
static const char * cr_entry_pollution(const struct city *pcity, const void *data)
Definition cityrepdata.c:514
base_city_report_specs
static const struct city_report_spec base_city_report_specs[]
Definition cityrepdata.c:697
FUNC_TAG
#define FUNC_TAG(var)
Definition cityrepdata.c:695
cr_entry_defense
static const char * cr_entry_defense(const struct city *pcity, const void *data)
Definition cityrepdata.c:304
cr_entry_cityname
static const char * cr_entry_cityname(const struct city *pcity, const void *data)
Definition cityrepdata.c:52
cr_entry_continent
static const char * cr_entry_continent(const struct city *pcity, const void *data)
Definition cityrepdata.c:669
cr_entry_performance
static const char * cr_entry_performance(const struct city *pcity, const void *data)
Definition cityrepdata.c:178
cr_entry_build_cost
static const char * cr_entry_build_cost(const struct city *pcity, const void *data)
Definition cityrepdata.c:592
cr_entry_growturns
static const char * cr_entry_growturns(const struct city *pcity, const void *data)
Definition cityrepdata.c:489
can_city_sell_universal
bool can_city_sell_universal(const struct city *pcity, const struct universal *target)
Definition cityrepdata.c:1104
cr_entry_unhappy
static const char * cr_entry_unhappy(const struct city *pcity, const void *data)
Definition cityrepdata.c:212
cr_entry_workers
static const char * cr_entry_workers(const struct city *pcity, const void *data)
Definition cityrepdata.c:120
city_report_specs
struct city_report_spec * city_report_specs
Definition cityrepdata.c:798
cr_entry_angry
static const char * cr_entry_angry(const struct city *pcity, const void *data)
Definition cityrepdata.c:226
cityrepfield_compare
int cityrepfield_compare(const char *str1, const char *str2)
Definition cityrepdata.c:1077
cr_entry_attack
static const char * cr_entry_attack(const struct city *pcity, const void *data)
Definition cityrepdata.c:267
city_report_spec_tagname
const char * city_report_spec_tagname(int i)
Definition cityrepdata.c:820
cr_entry_build_slots
static const char * cr_entry_build_slots(const struct city *pcity, const void *data)
Definition cityrepdata.c:551
free_datum
static void free_datum(struct datum *dat)
Definition cityrepdata.c:955
cr_entry_corruption
static const char * cr_entry_corruption(const struct city *pcity, const void *data)
Definition cityrepdata.c:627
cr_entry_specialists
static const char * cr_entry_specialists(const struct city *pcity, const void *data)
Definition cityrepdata.c:240
cr_entry_supported
static const char * cr_entry_supported(const struct city *pcity, const void *data)
Definition cityrepdata.c:342
cr_entry_resources
static const char * cr_entry_resources(const struct city *pcity, const void *data)
Definition cityrepdata.c:374
init_datum_number
static void init_datum_number(struct datum *dat, float val)
Definition cityrepdata.c:945
cr_entry_cma
static const char * cr_entry_cma(const struct city *pcity, const void *data)
Definition cityrepdata.c:682
datum_compare
static int datum_compare(const struct datum *a, const struct datum *b)
Definition cityrepdata.c:968
cr_entry_prodplus
static const char * cr_entry_prodplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:403
city_report_spec_show_ptr
bool * city_report_spec_show_ptr(int i)
Definition cityrepdata.c:812
cr_entry_history
static const char * cr_entry_history(const struct city *pcity, const void *data)
Definition cityrepdata.c:161
cr_entry_content
static const char * cr_entry_content(const struct city *pcity, const void *data)
Definition cityrepdata.c:198
num_creport_cols
static int num_creport_cols
Definition cityrepdata.c:799
cr_entry_happy
static const char * cr_entry_happy(const struct city *pcity, const void *data)
Definition cityrepdata.c:138
cr_entry_waste
static const char * cr_entry_waste(const struct city *pcity, const void *data)
Definition cityrepdata.c:640
cr_entry_output
static const char * cr_entry_output(const struct city *pcity, const void *data)
Definition cityrepdata.c:429
cityrepdata.h
NUM_CREPORT_COLS
#define NUM_CREPORT_COLS
Definition cityrepdata.h:25
cmafec_get_short_descr_of_city
const char * cmafec_get_short_descr_of_city(const struct city *pcity)
Definition cma_fec.c:221
cma_fec.h
resources
char * resources
Definition comments.c:35
city_history_gain
int city_history_gain(const struct city *pcity)
Definition culture.c:37
culture.h
attack
static void attack(QVariant data1, QVariant data2)
Definition dialogs.cpp:2917
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:73
SP_MAX
#define SP_MAX
Definition fc_types.h:379
O_SHIELD
@ O_SHIELD
Definition fc_types.h:91
O_FOOD
@ O_FOOD
Definition fc_types.h:91
O_TRADE
@ O_TRADE
Definition fc_types.h:91
O_SCIENCE
@ O_SCIENCE
Definition fc_types.h:91
O_LUXURY
@ O_LUXURY
Definition fc_types.h:91
O_GOLD
@ O_GOLD
Definition fc_types.h:91
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
_
#define _(String)
Definition fcintl.h:67
N_
#define N_(String)
Definition fcintl.h:69
game
struct civ_game game
Definition game.c:57
game.h
cma
static struct cma_dialog * cma
can_city_sell_building
bool can_city_sell_building(const struct city *pcity, const struct impr_type *pimprove)
Definition improvement.c:1072
log.h
fc_assert
#define fc_assert(condition)
Definition log.h:176
map.h
fc_realloc
#define fc_realloc(ptr, sz)
Definition mem.h:36
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
nation_adjective_for_player
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
gui_options
struct client_options gui_options
Definition options.c:71
options.h
len
int len
Definition packhand.c:125
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
specialists_abbreviation_string
const char * specialists_abbreviation_string(void)
Definition specialist.c:174
specialist_by_number
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
specialist_index
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
specialist_rule_name
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
specialist_plural_translation
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
specialist_count
Specialist_type_id specialist_count(void)
Definition specialist.c:71
specialist_abbreviation_translation
const char * specialist_abbreviation_translation(const struct specialist *sp)
Definition specialist.c:164
specialists_string
const char * specialists_string(const citizens *specialist_list)
Definition specialist.c:199
specialist.h
specialist_type_iterate_end
#define specialist_type_iterate_end
Definition specialist.h:79
specialist_type_iterate
#define specialist_type_iterate(sp)
Definition specialist.h:73
specvec.h
size
size_t size
Definition specvec.h:72
city_report_spec
Definition cityrepdata.h:27
city_report_spec::tagname
const char * tagname
Definition cityrepdata.h:35
city_report_spec::func
const char *(* func)(const struct city *pcity, const void *data)
Definition cityrepdata.h:34
city_report_spec::width
int width
Definition cityrepdata.h:29
city_report_spec::title2
const char * title2
Definition cityrepdata.h:31
city_report_spec::data
void * data
Definition cityrepdata.h:33
city_report_spec::show
bool show
Definition cityrepdata.h:28
city_report_spec::explanation
const char * explanation
Definition cityrepdata.h:32
city_report_spec::title1
const char * title1
Definition cityrepdata.h:30
city
Definition city.h:309
city::surplus
int surplus[O_LAST]
Definition city.h:343
city::food_stock
int food_stock
Definition city.h:354
city::history
int history
Definition city.h:393
city::pollution
int pollution
Definition city.h:356
city::waste
int waste[O_LAST]
Definition city.h:344
city::worklist
struct worklist worklist
Definition city.h:387
city::culture
int culture
Definition city.h:448
city::buy_cost
int buy_cost
Definition city.h:449
city::feel
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition city.h:321
city::specialists
citizens specialists[SP_MAX]
Definition city.h:324
city::tile
struct tile * tile
Definition city.h:311
city::shield_stock
int shield_stock
Definition city.h:355
city::prod
int prod[O_LAST]
Definition city.h:346
city::units_supported
struct unit_list * units_supported
Definition city.h:391
city::client
struct city::@17::@20 client
civ_game::info
struct packet_game_info info
Definition game.h:89
client_options::concise_city_production
bool concise_city_production
Definition options.h:156
datum
Definition cityrepdata.c:917
datum::numeric_value
float numeric_value
Definition cityrepdata.c:919
datum::is_numeric
bool is_numeric
Definition cityrepdata.c:922
datum::string_value
char * string_value
Definition cityrepdata.c:920
datum::val
union datum::@128 val
packet_game_info::illness_on
bool illness_on
Definition packets_gen.h:181
specialist
Definition specialist.h:29
tile::units
struct unit_list * units
Definition tile.h:57
tile::continent
Continent_id continent
Definition tile.h:53
unit_type::defense_strength
int defense_strength
Definition unittype.h:496
unit_type::attack_strength
int attack_strength
Definition unittype.h:495
universal
Definition fc_types.h:756
universal::kind
enum universals_n kind
Definition fc_types.h:758
universal::value
universals_u value
Definition fc_types.h:757
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:161
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
trade_routes_iterate_end
#define trade_routes_iterate_end
Definition traderoutes.h:133
trade_routes_iterate
#define trade_routes_iterate(c, proute)
Definition traderoutes.h:129
universals_u::building
const struct impr_type * building
Definition fc_types.h:598
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
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
worklist_is_empty
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66