Freeciv-3.2: /fast/freeciv/nightly/S3_2/client/cityrepdata.c Source File

Freeciv-3.2

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 "nation.h"
35#include "specialist.h"
36#include "unitlist.h"
37
38/* agents */
39#include "cma_fec.h"
40
41/* client */
42#include "citydlg_common.h" /* city_production_cost_str() */
43#include "options.h"
44
45#include "cityrepdata.h"
46
47/********************************************************************/
53 static const char *cr_entry_cityname(const struct city *pcity,
54 const void *data)
55{
56 /* We used to truncate the name to 14 bytes. This should not be needed
57 * in any modern GUI library and may give an invalid string if a
58 * multibyte character is clipped. */
59 return city_name_get(pcity);
60}
61
62/********************************************************************/
65 static const char *cr_entry_nation(const struct city *pcity,
66 const void *data)
67{
68 return nation_adjective_for_player(city_owner(pcity));
69}
70
71/********************************************************************/
75 static const char *cr_entry_size(const struct city *pcity,
76 const void *data)
77{
78 static char buf[8];
79
80 fc_snprintf(buf, sizeof(buf), "%2d", city_size_get(pcity));
81 return buf;
82}
83
84/********************************************************************/
89 static const char *cr_entry_hstate_concise(const struct city *pcity,
90 const void *data)
91{
92 static char buf[4];
93
94 fc_snprintf(buf, sizeof(buf), "%s",
95 (city_celebrating(pcity) ? "*"
96 : (city_unhappy(pcity) ? "X" : " ")));
97 return buf;
98}
99
100/********************************************************************/
105 static const char *cr_entry_hstate_verbose(const struct city *pcity,
106 const void *data)
107{
108 static char buf[32];
109
110 fc_snprintf(buf, sizeof(buf), "%s",
111 (city_celebrating(pcity) ? Q_("?city_state:Celebrating")
112 : (city_unhappy(pcity) ? Q_("?city_state:Disorder")
113 : Q_("?city_state:Peace"))));
114 return buf;
115}
116
117/********************************************************************/
122 static const char *cr_entry_workers(const struct city *pcity,
123 const void *data)
124{
125 static char buf[32];
126
127 fc_snprintf(buf, sizeof(buf), "%d/%d/%d/%d",
128 pcity->feel[CITIZEN_HAPPY][FEELING_FINAL],
129 pcity->feel[CITIZEN_CONTENT][FEELING_FINAL],
130 pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL],
131 pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]);
132 return buf;
133}
134
135/********************************************************************/
140 static const char *cr_entry_happy(const struct city *pcity,
141 const void *data)
142{
143 static char buf[8];
144
145 fc_snprintf(buf, sizeof(buf), "%2d",
146 pcity->feel[CITIZEN_HAPPY][FEELING_FINAL]);
147 return buf;
148}
149
150/********************************************************************/
153 static const char *cr_entry_culture(const struct city *pcity,
154 const void *data)
155{
156 static char buf[8];
157
158 fc_snprintf(buf, sizeof(buf), "%3d", pcity->client.culture);
159 return buf;
160}
161
162/********************************************************************/
165 static const char *cr_entry_history(const struct city *pcity,
166 const void *data)
167{
168 static char buf[20];
169 int perturn = city_history_gain(pcity);
170
171 if (perturn != 0) {
172 fc_snprintf(buf, sizeof(buf), "%3d (%+d)", pcity->history, perturn);
173 } else {
174 fc_snprintf(buf, sizeof(buf), "%3d", pcity->history);
175 }
176
177 return buf;
178}
179
180/********************************************************************/
183 static const char *cr_entry_performance(const struct city *pcity,
184 const void *data)
185{
186 static char buf[8];
187
188 /*
189 * Infer the actual performance component of culture from server-supplied
190 * values, rather than using the client's guess at EFT_PERFORMANCE.
191 * XXX: if culture ever gets more complicated than history+performance,
192 * this will need revising, possibly to use a server-supplied value.
193 */
194 fc_snprintf(buf, sizeof(buf), "%3d", pcity->client.culture - pcity->history);
195 return buf;
196}
197
198/********************************************************************/
203 static const char *cr_entry_content(const struct city *pcity,
204 const void *data)
205{
206 static char buf[8];
207
208 fc_snprintf(buf, sizeof(buf), "%2d",
209 pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]);
210 return buf;
211}
212
213/********************************************************************/
218 static const char *cr_entry_unhappy(const struct city *pcity,
219 const void *data)
220{
221 static char buf[8];
222
223 fc_snprintf(buf, sizeof(buf), "%2d",
224 pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]);
225
226 return buf;
227}
228
229/********************************************************************/
234 static const char *cr_entry_angry(const struct city *pcity,
235 const void *data)
236{
237 static char buf[8];
238
239 fc_snprintf(buf, sizeof(buf), "%2d",
240 pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]);
241
242 return buf;
243}
244
245/********************************************************************/
250 static const char *cr_entry_specialists(const struct city *pcity,
251 const void *data)
252{
253 return specialists_string(pcity->specialists);
254}
255
256/********************************************************************/
261 static const char *cr_entry_specialist(const struct city *pcity,
262 const void *data)
263{
264 static char buf[8];
265 const struct specialist *sp = data;
266
267 fc_snprintf(buf, sizeof(buf), "%2d",
268 pcity->specialists[specialist_index(sp)]);
269
270 return buf;
271}
272
273/********************************************************************/
278 static const char *cr_entry_attack(const struct city *pcity,
279 const void *data)
280{
281 static char buf[32];
282 int attack_best[4] = {-1, -1, -1, -1}, i;
283
284 unit_list_iterate(pcity->tile->units, punit) {
285 /* What about allied units? Should we just count them? */
286 attack_best[3] = unit_type_get(punit)->attack_strength;
287
288 /* Now that the element is appended to the end of the list, we simply
289 do an insertion sort. */
290 for (i = 2; i >= 0 && attack_best[i] < attack_best[i + 1]; i--) {
291 int tmp = attack_best[i];
292
293 attack_best[i] = attack_best[i + 1];
294 attack_best[i + 1] = tmp;
295 }
296 } unit_list_iterate_end;
297
298 buf[0] = '\0';
299 for (i = 0; i < 3; i++) {
300 if (attack_best[i] >= 0) {
301 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
302 attack_best[i]);
303 } else {
304 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
305 }
306 }
307
308 return buf;
309}
310
311/********************************************************************/
316 static const char *cr_entry_defense(const struct city *pcity,
317 const void *data)
318{
319 static char buf[32];
320 int defense_best[4] = {-1, -1, -1, -1}, i;
321
322 unit_list_iterate(pcity->tile->units, punit) {
323 /* What about allied units? Should we just count them? */
324 defense_best[3] = unit_type_get(punit)->defense_strength;
325
326 /* Now that the element is appended to the end of the list, we simply
327 do an insertion sort. */
328 for (i = 2; i >= 0 && defense_best[i] < defense_best[i + 1]; i--) {
329 int tmp = defense_best[i];
330
331 defense_best[i] = defense_best[i + 1];
332 defense_best[i + 1] = tmp;
333 }
334 } unit_list_iterate_end;
335
336 buf[0] = '\0';
337 for (i = 0; i < 3; i++) {
338 if (defense_best[i] >= 0) {
339 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
340 defense_best[i]);
341 } else {
342 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
343 }
344 }
345
346 return buf;
347}
348
349/********************************************************************/
354 static const char *cr_entry_supported(const struct city *pcity,
355 const void *data)
356{
357 static char buf[8];
358 int num_supported = unit_list_size(pcity->units_supported);
359
360 fc_snprintf(buf, sizeof(buf), "%2d", num_supported);
361
362 return buf;
363}
364
365/********************************************************************/
370 static const char *cr_entry_present(const struct city *pcity,
371 const void *data)
372{
373 static char buf[8];
374 int num_present = unit_list_size(pcity->tile->units);
375
376 fc_snprintf(buf, sizeof(buf), "%2d", num_present);
377
378 return buf;
379}
380
381/********************************************************************/
386 static const char *cr_entry_resources(const struct city *pcity,
387 const void *data)
388{
389 static char buf[32];
390
391 fc_snprintf(buf, sizeof(buf), "%d/%d/%d",
392 pcity->surplus[O_FOOD],
393 pcity->surplus[O_SHIELD],
394 pcity->surplus[O_TRADE]);
395
396 return buf;
397}
398
399/********************************************************************/
404 static const char *cr_entry_foodplus(const struct city *pcity,
405 const void *data)
406{
407 static char buf[8];
408
409 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_FOOD]);
410
411 return buf;
412}
413
414/********************************************************************/
419 static const char *cr_entry_prodplus(const struct city *pcity,
420 const void *data)
421{
422 static char buf[8];
423
424 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_SHIELD]);
425
426 return buf;
427}
428
429/********************************************************************/
434 static const char *cr_entry_tradeplus(const struct city *pcity,
435 const void *data)
436{
437 static char buf[8];
438
439 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_TRADE]);
440
441 return buf;
442}
443
444/********************************************************************/
449 static const char *cr_entry_output(const struct city *pcity,
450 const void *data)
451{
452 static char buf[32];
453 int goldie = pcity->surplus[O_GOLD];
454
455 fc_snprintf(buf, sizeof(buf), "%3d/%d/%d",
456 goldie, pcity->prod[O_LUXURY], pcity->prod[O_SCIENCE]);
457
458 return buf;
459}
460
461/********************************************************************/
466 static const char *cr_entry_gold(const struct city *pcity,
467 const void *data)
468{
469 static char buf[8];
470
471 if (pcity->surplus[O_GOLD] > 0) {
472 fc_snprintf(buf, sizeof(buf), "+%d", pcity->surplus[O_GOLD]);
473 } else {
474 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_GOLD]);
475 }
476
477 return buf;
478}
479
480/********************************************************************/
485 static const char *cr_entry_luxury(const struct city *pcity,
486 const void *data)
487{
488 static char buf[8];
489
490 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_LUXURY]);
491
492 return buf;
493}
494
495/********************************************************************/
500 static const char *cr_entry_science(const struct city *pcity,
501 const void *data)
502{
503 static char buf[8];
504
505 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_SCIENCE]);
506
507 return buf;
508}
509
510/********************************************************************/
515 static const char *cr_entry_growturns(const struct city *pcity,
516 const void *data)
517{
518 int turns = city_turns_to_grow(pcity);
519 char buffer[8];
520 static char buf[32];
521
522 if (turns == FC_INFINITY) {
523 /* 'never' wouldn't be easily translatable here. */
524 fc_snprintf(buffer, sizeof(buffer), "---");
525 } else {
526 /* Shrinking cities get a negative value. */
527 fc_snprintf(buffer, sizeof(buffer), "%4d", turns);
528 }
529 fc_snprintf(buf, sizeof(buf), "%s (%d/%d)",
530 buffer, pcity->food_stock,
531 city_granary_size(city_size_get(pcity)));
532
533 return buf;
534}
535
536/********************************************************************/
541 static const char *cr_entry_pollution(const struct city *pcity,
542 const void *data)
543{
544 static char buf[8];
545
546 fc_snprintf(buf, sizeof(buf), "%3d", pcity->pollution);
547
548 return buf;
549}
550
551/********************************************************************/
556 static const char *cr_entry_trade_routes(const struct city *pcity,
557 const void *data)
558{
559 static char buf[16];
560 int num = 0, value = 0;
561
562 trade_routes_iterate(pcity, proute) {
563 num++;
564 value += proute->value;
565 } trade_routes_iterate_end;
566
567 if (0 == num) {
568 sz_strlcpy(buf, "0");
569 } else {
570 fc_snprintf(buf, sizeof(buf), "%d (+%d)", num, value);
571 }
572
573 return buf;
574}
575
576/********************************************************************/
581 static const char *cr_entry_build_slots(const struct city *pcity,
582 const void *data)
583{
584 static char buf[8];
585
586 fc_snprintf(buf, sizeof(buf), "%3d", city_build_slots(pcity));
587
588 return buf;
589}
590
591/********************************************************************/
596 static const char *cr_entry_building(const struct city *pcity,
597 const void *data)
598{
599 static char buf[192];
600 const char *from_worklist =
601 worklist_is_empty(&pcity->worklist) ? "" :
602 gui_options.concise_city_production ? "+" : _("(worklist)");
603
604 if (city_production_is_genus(pcity, IG_CONVERT)) {
605 if (city_production_has_flag(pcity, IF_GOLD)) {
606 fc_snprintf(buf, sizeof(buf), "%s (%d)%s",
607 city_production_name_translation(pcity),
608 MAX(0, pcity->surplus[O_SHIELD]), from_worklist);
609 } else {
610 fc_snprintf(buf, sizeof(buf), "%s (--)%s",
611 city_production_name_translation(pcity),
612 from_worklist);
613 }
614 } else {
615 fc_snprintf(buf, sizeof(buf), "%s (%d/%s)%s",
616 city_production_name_translation(pcity),
617 pcity->shield_stock,
618 city_production_cost_str(pcity),
619 from_worklist);
620 }
621
622 return buf;
623}
624
625/********************************************************************/
630 static const char *cr_entry_build_cost(const struct city *pcity,
631 const void *data)
632{
633 char bufone[8];
634 char buftwo[8];
635 static char buf[32];
636 int price;
637 int turns;
638
639 if (city_production_is_genus(pcity, IG_CONVERT)) {
640 fc_snprintf(buf, sizeof(buf), "*");
641 return buf;
642 }
643 price = pcity->client.buy_cost;
644 turns = city_production_turns_to_build(pcity, TRUE);
645
646 if (price > 99999) {
647 fc_snprintf(bufone, sizeof(bufone), "---");
648 } else {
649 fc_snprintf(bufone, sizeof(bufone), "%d", price);
650 }
651 if (turns > 999) {
652 fc_snprintf(buftwo, sizeof(buftwo), "--");
653 } else {
654 fc_snprintf(buftwo, sizeof(buftwo), "%3d", turns);
655 }
656 fc_snprintf(buf, sizeof(buf), "%s/%s", buftwo, bufone);
657 return buf;
658}
659
660/********************************************************************/
665 static const char *cr_entry_corruption(const struct city *pcity,
666 const void *data)
667{
668 static char buf[8];
669
670 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_TRADE]));
671
672 return buf;
673}
674
675/********************************************************************/
680 static const char *cr_entry_waste(const struct city *pcity,
681 const void *data)
682{
683 static char buf[8];
684
685 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_SHIELD]));
686
687 return buf;
688}
689
690/********************************************************************/
695 static const char *cr_entry_plague_risk(const struct city *pcity,
696 const void *data)
697{
698 static char buf[8];
699
700 if (!game.info.illness_on) {
701 fc_snprintf(buf, sizeof(buf), " -.-");
702 } else {
703 fc_snprintf(buf, sizeof(buf), "%4.1f",
704 (float)city_illness_calc(pcity, NULL, NULL, NULL, NULL)/10.0);
705 }
706
707 return buf;
708}
709
710/********************************************************************/
713 static const char *cr_entry_continent(const struct city *pcity,
714 const void *data)
715{
716 static char buf[8];
717
718 fc_snprintf(buf, sizeof(buf), "%3d", pcity->tile->continent);
719
720 return buf;
721}
722
723/********************************************************************/
728 static const char *cr_entry_cma(const struct city *pcity,
729 const void *data)
730{
731 return cmafec_get_short_descr_of_city(pcity);
732}
733
734/* City report options (which columns get shown)
735 * To add a new entry, you should just have to:
736 * - add a function like those above
737 * - add an entry in the base_city_report_specs[] table
738 */
739
740/* This generates the function name and the tagname: */
741#define FUNC_TAG(var) cr_entry_##var, #var
742
743 static const struct city_report_spec base_city_report_specs[] = {
744 { TRUE, -15, NULL, N_("?city:Name"), N_("City Name"),
745 NULL, FUNC_TAG(cityname) },
746 { FALSE, -15, NULL, N_("Nation"), N_("Nation"),
747 NULL, FUNC_TAG(nation) },
748 { TRUE, 2, NULL, N_("?size [short]:Sz"), N_("Size"),
749 NULL, FUNC_TAG(size) },
750 { TRUE, -8, NULL, N_("State"), N_("Celebrating/Peace/Disorder"),
751 NULL, FUNC_TAG(hstate_verbose) },
752 { FALSE, 1, NULL, NULL, N_("Concise *=Celebrating, X=Disorder"),
753 NULL, FUNC_TAG(hstate_concise) },
754
755 { FALSE, 2, NULL, N_("?Happy workers:H"), N_("Workers: Happy"),
756 NULL, FUNC_TAG(happy) },
757 { FALSE, 2, NULL, N_("?Content workers:C"), N_("Workers: Content"),
758 NULL, FUNC_TAG(content) },
759 { FALSE, 2, NULL, N_("?Unhappy workers:U"), N_("Workers: Unhappy"),
760 NULL, FUNC_TAG(unhappy) },
761 { FALSE, 2, NULL, N_("?Angry workers:A"), N_("Workers: Angry"),
762 NULL, FUNC_TAG(angry) },
763 { TRUE, 10, N_("?city:Workers"),
764 N_("?happy/content/unhappy/angry:H/C/U/A"),
765 N_("Workers: Happy, Content, Unhappy, Angry"),
766 NULL, FUNC_TAG(workers) },
767
768 { FALSE, 8, N_("Best"), N_("attack"),
769 N_("Best attacking units"), NULL, FUNC_TAG(attack)},
770 { FALSE, 8, N_("Best"), N_("defense"),
771 N_("Best defending units"), NULL, FUNC_TAG(defense)},
772 { FALSE, 2, N_("Units"),
773 /* TRANS: Header "Number of units inside city" */
774 N_("?Present (units):Here"),
775 N_("Number of units present"), NULL, FUNC_TAG(present) },
776 { FALSE, 2, N_("Units"),
777 /* TRANS: Header "Number of units supported by given city" */
778 N_("?Supported (units):Owned"),
779 N_("Number of units supported"), NULL, FUNC_TAG(supported) },
780
781 { /* TRANS: Header "It will take this many turns before city grows" */
782 TRUE, 14, N_("?food (population):Grow"),
783 N_("?Stock/Target:(Have/Need)"),
784 N_("Turns until growth/famine"),
785 NULL, FUNC_TAG(growturns) },
786
787 { TRUE, 10, N_("Surplus"), N_("?food/production/trade:F/P/T"),
788 N_("Surplus: Food, Production, Trade"),
789 NULL, FUNC_TAG(resources) },
790 { FALSE, 3, NULL, N_("?Food surplus [short]:+F"), N_("Surplus: Food"),
791 NULL, FUNC_TAG(foodplus) },
792 { FALSE, 3, NULL, N_("?Production surplus [short]:+P"),
793 N_("Surplus: Production"), NULL, FUNC_TAG(prodplus) },
794 { FALSE, 3, NULL, N_("?Production loss (waste) [short]:-P"),
795 N_("Waste"), NULL, FUNC_TAG(waste) },
796 { FALSE, 3, NULL, N_("?Trade surplus [short]:+T"), N_("Surplus: Trade"),
797 NULL, FUNC_TAG(tradeplus) },
798 { FALSE, 3, NULL, N_("?Trade loss (corruption) [short]:-T"),
799 N_("Corruption"), NULL, FUNC_TAG(corruption) },
800
801 { TRUE, 10, N_("Economy"), N_("?gold/luxury/science:G/L/S"),
802 N_("Economy: Gold, Luxuries, Science"),
803 NULL, FUNC_TAG(output) },
804 { FALSE, 3, NULL, N_("?Gold:G"), N_("Economy: Gold"),
805 NULL, FUNC_TAG(gold) },
806 { FALSE, 3, NULL, N_("?Luxury:L"), N_("Economy: Luxury"),
807 NULL, FUNC_TAG(luxury) },
808 { FALSE, 3, NULL, N_("?Science:S"), N_("Economy: Science"),
809 NULL, FUNC_TAG(science) },
810 { FALSE, 3, NULL, N_("?Culture:Clt"), N_("Culture (History+Performance)"),
811 NULL, FUNC_TAG(culture) },
812 { FALSE, 3, NULL, N_("?History:Hst"),
813 N_("Culture: History (and gain per turn)"),
814 NULL, FUNC_TAG(history) },
815 { FALSE, 3, NULL, N_("?Performance:Prf"), N_("Culture: Performance"),
816 NULL, FUNC_TAG(performance) },
817 { FALSE, 3, NULL, N_("?Continent:C"), N_("Continent number"),
818 NULL, FUNC_TAG(continent) },
819 { FALSE, 1, N_("?number_trade_routes:n"),
820 N_("?number_trade_routes:R"),
821 N_("Number (and total value) of trade routes"),
822 NULL, FUNC_TAG(trade_routes) },
823 { FALSE, 3, NULL, N_("?pollution [short]:Pol"), N_("?stats:Pollution"),
824 NULL, FUNC_TAG(pollution) },
825 { FALSE, 4, N_("?plague risk [short]:Pla"), N_("(%)"),
826 N_("Plague risk per turn"),
827 NULL, FUNC_TAG(plague_risk) },
828 { FALSE, 15, NULL, N_("?cma:Governor"), N_("Citizen Governor"),
829 NULL, FUNC_TAG(cma) },
830
831 /* TRANS: "BS" = "build slots" */
832 { FALSE, 3, NULL, N_("BS"), N_("Maximum units buildable per turn"),
833 NULL, FUNC_TAG(build_slots) },
834 { TRUE, 9, N_("Production"), N_("Turns/Buy"),
835 /* N_("Turns or gold to complete production"), future menu needs translation */
836 N_("Production"),
837 NULL, FUNC_TAG(build_cost) },
838 { TRUE, 0, N_("Currently Building"),
839 N_("?Stock/Target:(Have/Need)"),
840 N_("Currently Building"),
841 NULL, FUNC_TAG(building) }
842};
843
844 struct city_report_spec *city_report_specs;
845 static int num_creport_cols;
846
847/********************************************************************/
850 int num_city_report_spec(void)
851{
852 return num_creport_cols;
853}
854
855/********************************************************************/
858 bool *city_report_spec_show_ptr(int i)
859{
860 return &(city_report_specs[i].show);
861}
862
863/********************************************************************/
866 const char *city_report_spec_tagname(int i)
867{
868 return city_report_specs[i].tagname;
869}
870
871/********************************************************************/
876 void init_city_report_game_data(void)
877{
878 static char sp_explanation[SP_MAX][128];
879 static char sp_explanations[SP_MAX*128];
880 struct city_report_spec *p;
881 int i;
882
883 num_creport_cols = ARRAY_SIZE(base_city_report_specs)
884 + specialist_count() + 1;
885 city_report_specs
886 = fc_realloc(city_report_specs,
887 num_creport_cols * sizeof(*city_report_specs));
888 p = &city_report_specs[0];
889
890 fc_snprintf(sp_explanations, sizeof(sp_explanations),
891 "%s", _("Specialists: "));
892 specialist_type_iterate(sp) {
893 struct specialist *s = specialist_by_number(sp);
894
895 p->show = FALSE;
896 p->width = 2;
897 p->title1 = Q_("?specialist:S");
898 p->title2 = specialist_abbreviation_translation(s);
899 fc_snprintf(sp_explanation[sp], sizeof(sp_explanation[sp]),
900 _("Specialists: %s"), specialist_plural_translation(s));
901 cat_snprintf(sp_explanations, sizeof(sp_explanations),
902 "%s%s", (sp == 0) ? "" : ", ",
903 specialist_plural_translation(s));
904 p->explanation = sp_explanation[sp];
905 p->data = s;
906 p->func = cr_entry_specialist;
907 p->tagname = specialist_rule_name(s);
908 p++;
909 } specialist_type_iterate_end;
910
911 /* Summary column for all specialists. */
912 {
913 static char sp_summary[128];
914
915 p->show = FALSE;
916 p->width = MAX(7, specialist_count() * 2 - 1);
917 p->title1 = _("Special");
918 fc_snprintf(sp_summary, sizeof(sp_summary),
919 "%s", specialists_abbreviation_string());
920 p->title2 = sp_summary;
921 p->explanation = sp_explanations;
922 p->data = NULL;
923 p->func = cr_entry_specialists;
924 p->tagname = "specialists";
925 p++;
926 }
927
928 memcpy(p, base_city_report_specs,
929 sizeof(base_city_report_specs));
930
931 for (i = 0; i < ARRAY_SIZE(base_city_report_specs); i++) {
932 if (p->title1) {
933 p->title1 = Q_(p->title1);
934 }
935 if (p->title2) {
936 p->title2 = Q_(p->title2);
937 }
938 p->explanation = Q_(p->explanation);
939 p++;
940 }
941
942 fc_assert(NUM_CREPORT_COLS == ARRAY_SIZE(base_city_report_specs)
943 + specialist_count() + 1);
944}
945
946/************************************************************************
947 The following several functions allow intelligent sorting city report
948 fields by column. This doesn't necessarily do the right thing, but
949 it's better than sorting alphabetically.
950
951 The GUI gives us two values to compare (as strings). We try to split
952 them into an array of numeric and string fields, then we compare
953 lexicographically. Two numeric fields are compared in the obvious
954 way, two character fields are compared alphabetically.
955 Arbitrarily, a numeric field is sorted before a character field
956 (for "justification" note that numbers are before letters
957 in the ASCII table).
958************************************************************************/
959
960/* A datum is one short string, or one number.
961 A datum_vector represents a long string of alternating strings and
962 numbers. */
963 struct datum {
964 union {
965 float numeric_value;
966 char *string_value;
967 } val;
968 bool is_numeric;
969};
970#define SPECVEC_TAG datum
971#include "specvec.h"
972
973/********************************************************************/
976 static void init_datum_string(struct datum *dat, const char *left,
977 const char *right)
978{
979 int len = right - left;
980
981 dat->is_numeric = FALSE;
982 dat->val.string_value = fc_malloc(len + 1);
983 memcpy(dat->val.string_value, left, len);
984 dat->val.string_value[len] = 0;
985}
986
987/********************************************************************/
991 static void init_datum_number(struct datum *dat, float val)
992{
993 dat->is_numeric = TRUE;
994 dat->val.numeric_value = val;
995}
996
997/********************************************************************/
1001 static void free_datum(struct datum *dat)
1002{
1003 if (!dat->is_numeric) {
1004 free(dat->val.string_value);
1005 }
1006}
1007
1008/********************************************************************/
1014 static int datum_compare(const struct datum *a, const struct datum *b)
1015{
1016 if (a->is_numeric == b->is_numeric) {
1017 if (a->is_numeric) {
1018 if (a->val.numeric_value == b->val.numeric_value) {
1019 return 0;
1020 } else if (a->val.numeric_value < b->val.numeric_value) {
1021 return -1;
1022 } else if (a->val.numeric_value > b->val.numeric_value) {
1023 return +1;
1024 } else {
1025 return 0; /* shrug */
1026 }
1027 } else {
1028 return strcmp(a->val.string_value, b->val.string_value);
1029 }
1030 } else {
1031 if (a->is_numeric) {
1032 return -1;
1033 } else {
1034 return 1;
1035 }
1036 }
1037}
1038
1039/********************************************************************/
1042 static int data_compare(const struct datum_vector *a,
1043 const struct datum_vector *b)
1044{
1045 int i, n;
1046
1047 n = MIN(a->size, b->size);
1048
1049 for (i = 0; i < n; i++) {
1050 int cmp = datum_compare(&a->p[i], &b->p[i]);
1051
1052 if (cmp != 0) {
1053 return cmp;
1054 }
1055 }
1056
1057 /* The first n fields match; whoever has more fields goes last.
1058 If they have equal numbers, the two really are equal. */
1059 return a->size - b->size;
1060}
1061
1062/********************************************************************/
1065 static void split_string(struct datum_vector *data, const char *str)
1066{
1067 const char *string_start;
1068
1069 datum_vector_init(data);
1070 string_start = str;
1071 while (*str) {
1072 char *endptr;
1073 float value;
1074
1075 errno = 0;
1076 value = strtof(str, &endptr);
1077 if (errno != 0 || endptr == str || !isfinite(value)) {
1078 /* that wasn't a sensible number; go on */
1079 str++;
1080 } else {
1081 /* that was a number, so stop the string we were parsing, add
1082 it (unless it's empty), then add the number we just parsed */
1083 struct datum d;
1084
1085 if (str != string_start) {
1086 init_datum_string(&d, string_start, str);
1087 datum_vector_append(data, d);
1088 }
1089
1090 init_datum_number(&d, value);
1091 datum_vector_append(data, d);
1092
1093 /* finally, update the string position pointers */
1094 string_start = str = endptr;
1095 }
1096 }
1097
1098 /* if we have anything leftover then it's a string */
1099 if (str != string_start) {
1100 struct datum d;
1101
1102 init_datum_string(&d, string_start, str);
1103 datum_vector_append(data, d);
1104 }
1105}
1106
1107/********************************************************************/
1110 static void free_data(struct datum_vector *data)
1111{
1112 int i;
1113
1114 for (i = 0; i < data->size; i++) {
1115 free_datum(&data->p[i]);
1116 }
1117 datum_vector_free(data);
1118}
1119
1120/********************************************************************/
1123 int cityrepfield_compare(const char *str1, const char *str2)
1124{
1125 struct datum_vector data1, data2;
1126 int retval;
1127
1128 if (str1 == str2) {
1129 return 0;
1130 } else if (NULL == str1) {
1131 return 1;
1132 } else if (NULL == str2) {
1133 return -1;
1134 }
1135
1136 split_string(&data1, str1);
1137 split_string(&data2, str2);
1138
1139 retval = data_compare(&data1, &data2);
1140
1141 free_data(&data1);
1142 free_data(&data2);
1143
1144 return retval;
1145}
1146
1147/********************************************************************/
1150 bool can_city_sell_universal(const struct city *pcity,
1151 const struct universal *target)
1152{
1153 return target->kind == VUT_IMPROVEMENT
1154 && can_city_sell_building(pcity, target->value.building);
1155}
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:2123
city_build_slots
int city_build_slots(const struct city *pcity)
Definition city.c:2923
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1128
city_production_has_flag
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Definition city.c:726
city_production_turns_to_build
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:819
city_unhappy
bool city_unhappy(const struct city *pcity)
Definition city.c:1618
city_celebrating
bool city_celebrating(const struct city *pcity)
Definition city.c:1637
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:2861
cmp
static int cmp(int v1, int v2)
Definition city.c:324
city_production_is_genus
bool city_production_is_genus(const struct city *pcity, enum impr_genus_id genus)
Definition city.c:716
city_turns_to_grow
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1988
city_production_name_translation
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:699
city.h
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
CITIZEN_ANGRY
@ CITIZEN_ANGRY
Definition city.h:271
CITIZEN_HAPPY
@ CITIZEN_HAPPY
Definition city.h:268
CITIZEN_CONTENT
@ CITIZEN_CONTENT
Definition city.h:269
CITIZEN_UNHAPPY
@ CITIZEN_UNHAPPY
Definition city.h:270
city_owner
#define city_owner(_pcity_)
Definition city.h:563
FEELING_FINAL
@ FEELING_FINAL
Definition city.h:284
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:89
cr_entry_tradeplus
static const char * cr_entry_tradeplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:434
cr_entry_specialist
static const char * cr_entry_specialist(const struct city *pcity, const void *data)
Definition cityrepdata.c:261
cr_entry_present
static const char * cr_entry_present(const struct city *pcity, const void *data)
Definition cityrepdata.c:370
cr_entry_hstate_verbose
static const char * cr_entry_hstate_verbose(const struct city *pcity, const void *data)
Definition cityrepdata.c:105
num_city_report_spec
int num_city_report_spec(void)
Definition cityrepdata.c:850
init_datum_string
static void init_datum_string(struct datum *dat, const char *left, const char *right)
Definition cityrepdata.c:976
cr_entry_nation
static const char * cr_entry_nation(const struct city *pcity, const void *data)
Definition cityrepdata.c:65
cr_entry_luxury
static const char * cr_entry_luxury(const struct city *pcity, const void *data)
Definition cityrepdata.c:485
cr_entry_gold
static const char * cr_entry_gold(const struct city *pcity, const void *data)
Definition cityrepdata.c:466
cr_entry_building
static const char * cr_entry_building(const struct city *pcity, const void *data)
Definition cityrepdata.c:596
cr_entry_culture
static const char * cr_entry_culture(const struct city *pcity, const void *data)
Definition cityrepdata.c:153
split_string
static void split_string(struct datum_vector *data, const char *str)
Definition cityrepdata.c:1065
cr_entry_plague_risk
static const char * cr_entry_plague_risk(const struct city *pcity, const void *data)
Definition cityrepdata.c:695
cr_entry_trade_routes
static const char * cr_entry_trade_routes(const struct city *pcity, const void *data)
Definition cityrepdata.c:556
init_city_report_game_data
void init_city_report_game_data(void)
Definition cityrepdata.c:876
cr_entry_size
static const char * cr_entry_size(const struct city *pcity, const void *data)
Definition cityrepdata.c:75
free_data
static void free_data(struct datum_vector *data)
Definition cityrepdata.c:1110
cr_entry_foodplus
static const char * cr_entry_foodplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:404
cr_entry_science
static const char * cr_entry_science(const struct city *pcity, const void *data)
Definition cityrepdata.c:500
data_compare
static int data_compare(const struct datum_vector *a, const struct datum_vector *b)
Definition cityrepdata.c:1042
cr_entry_pollution
static const char * cr_entry_pollution(const struct city *pcity, const void *data)
Definition cityrepdata.c:541
base_city_report_specs
static const struct city_report_spec base_city_report_specs[]
Definition cityrepdata.c:743
FUNC_TAG
#define FUNC_TAG(var)
Definition cityrepdata.c:741
cr_entry_defense
static const char * cr_entry_defense(const struct city *pcity, const void *data)
Definition cityrepdata.c:316
cr_entry_cityname
static const char * cr_entry_cityname(const struct city *pcity, const void *data)
Definition cityrepdata.c:53
cr_entry_continent
static const char * cr_entry_continent(const struct city *pcity, const void *data)
Definition cityrepdata.c:713
cr_entry_performance
static const char * cr_entry_performance(const struct city *pcity, const void *data)
Definition cityrepdata.c:183
cr_entry_build_cost
static const char * cr_entry_build_cost(const struct city *pcity, const void *data)
Definition cityrepdata.c:630
cr_entry_growturns
static const char * cr_entry_growturns(const struct city *pcity, const void *data)
Definition cityrepdata.c:515
can_city_sell_universal
bool can_city_sell_universal(const struct city *pcity, const struct universal *target)
Definition cityrepdata.c:1150
cr_entry_unhappy
static const char * cr_entry_unhappy(const struct city *pcity, const void *data)
Definition cityrepdata.c:218
cr_entry_workers
static const char * cr_entry_workers(const struct city *pcity, const void *data)
Definition cityrepdata.c:122
city_report_specs
struct city_report_spec * city_report_specs
Definition cityrepdata.c:844
cr_entry_angry
static const char * cr_entry_angry(const struct city *pcity, const void *data)
Definition cityrepdata.c:234
cityrepfield_compare
int cityrepfield_compare(const char *str1, const char *str2)
Definition cityrepdata.c:1123
cr_entry_attack
static const char * cr_entry_attack(const struct city *pcity, const void *data)
Definition cityrepdata.c:278
city_report_spec_tagname
const char * city_report_spec_tagname(int i)
Definition cityrepdata.c:866
cr_entry_build_slots
static const char * cr_entry_build_slots(const struct city *pcity, const void *data)
Definition cityrepdata.c:581
free_datum
static void free_datum(struct datum *dat)
Definition cityrepdata.c:1001
cr_entry_corruption
static const char * cr_entry_corruption(const struct city *pcity, const void *data)
Definition cityrepdata.c:665
cr_entry_specialists
static const char * cr_entry_specialists(const struct city *pcity, const void *data)
Definition cityrepdata.c:250
cr_entry_supported
static const char * cr_entry_supported(const struct city *pcity, const void *data)
Definition cityrepdata.c:354
cr_entry_resources
static const char * cr_entry_resources(const struct city *pcity, const void *data)
Definition cityrepdata.c:386
init_datum_number
static void init_datum_number(struct datum *dat, float val)
Definition cityrepdata.c:991
cr_entry_cma
static const char * cr_entry_cma(const struct city *pcity, const void *data)
Definition cityrepdata.c:728
datum_compare
static int datum_compare(const struct datum *a, const struct datum *b)
Definition cityrepdata.c:1014
cr_entry_prodplus
static const char * cr_entry_prodplus(const struct city *pcity, const void *data)
Definition cityrepdata.c:419
city_report_spec_show_ptr
bool * city_report_spec_show_ptr(int i)
Definition cityrepdata.c:858
cr_entry_history
static const char * cr_entry_history(const struct city *pcity, const void *data)
Definition cityrepdata.c:165
cr_entry_content
static const char * cr_entry_content(const struct city *pcity, const void *data)
Definition cityrepdata.c:203
num_creport_cols
static int num_creport_cols
Definition cityrepdata.c:845
cr_entry_happy
static const char * cr_entry_happy(const struct city *pcity, const void *data)
Definition cityrepdata.c:140
cr_entry_waste
static const char * cr_entry_waste(const struct city *pcity, const void *data)
Definition cityrepdata.c:680
cr_entry_output
static const char * cr_entry_output(const struct city *pcity, const void *data)
Definition cityrepdata.c:449
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:36
incite_cost
char * incite_cost
Definition comments.c:74
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:3009
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
SP_MAX
#define SP_MAX
Definition fc_types.h:412
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_GOLD
@ O_GOLD
Definition fc_types.h:101
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:62
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:1100
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:169
nation.h
gui_options
struct client_options gui_options
Definition options.c:71
options.h
len
int len
Definition packhand.c:127
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:320
city::surplus
int surplus[O_LAST]
Definition city.h:355
city::food_stock
int food_stock
Definition city.h:367
city::history
int history
Definition city.h:410
city::pollution
int pollution
Definition city.h:369
city::waste
int waste[O_LAST]
Definition city.h:356
city::worklist
struct worklist worklist
Definition city.h:401
city::culture
int culture
Definition city.h:465
city::buy_cost
int buy_cost
Definition city.h:466
city::feel
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition city.h:333
city::specialists
citizens specialists[SP_MAX]
Definition city.h:336
city::tile
struct tile * tile
Definition city.h:322
city::shield_stock
int shield_stock
Definition city.h:368
city::prod
int prod[O_LAST]
Definition city.h:358
city::units_supported
struct unit_list * units_supported
Definition city.h:406
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:163
datum
Definition cityrepdata.c:963
datum::val
union datum::@130 val
datum::numeric_value
float numeric_value
Definition cityrepdata.c:965
datum::is_numeric
bool is_numeric
Definition cityrepdata.c:968
datum::string_value
char * string_value
Definition cityrepdata.c:966
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:58
tile::continent
Continent_id continent
Definition tile.h:54
unit_type::defense_strength
int defense_strength
Definition unittype.h:516
unit_type::attack_strength
int attack_strength
Definition unittype.h:515
universal
Definition fc_types.h:901
universal::kind
enum universals_n kind
Definition fc_types.h:903
universal::value
universals_u value
Definition fc_types.h:902
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
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:134
trade_routes_iterate
#define trade_routes_iterate(c, proute)
Definition traderoutes.h:130
universals_u::building
const struct impr_type * building
Definition fc_types.h:717
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