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/********************************************************************/
53static 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/********************************************************************/
65static const char *cr_entry_nation(const struct city *pcity,
66 const void *data)
67{
69}
70
71/********************************************************************/
75static 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/********************************************************************/
89static 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/********************************************************************/
105static 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/********************************************************************/
122static 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",
132 return buf;
133}
134
135/********************************************************************/
140static 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",
147 return buf;
148}
149
150/********************************************************************/
153static 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/********************************************************************/
165static 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/********************************************************************/
183static 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/********************************************************************/
203static 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",
210 return buf;
211}
212
213/********************************************************************/
218static 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",
225
226 return buf;
227}
228
229/********************************************************************/
234static 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",
241
242 return buf;
243}
244
245/********************************************************************/
250static const char *cr_entry_specialists(const struct city *pcity,
251 const void *data)
252{
253 return specialists_string(pcity->specialists);
254}
255
256/********************************************************************/
261static 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",
269
270 return buf;
271}
272
273/********************************************************************/
278static 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
285 /* What about allied units? Should we just count them? */
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 }
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/********************************************************************/
316static 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
323 /* What about allied units? Should we just count them? */
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
332 defense_best[i + 1] = tmp;
333 }
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/********************************************************************/
354static const char *cr_entry_supported(const struct city *pcity,
355 const void *data)
356{
357 static char buf[8];
359
360 fc_snprintf(buf, sizeof(buf), "%2d", num_supported);
361
362 return buf;
363}
364
365/********************************************************************/
370static 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/********************************************************************/
386static 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/********************************************************************/
404static 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/********************************************************************/
419static 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/********************************************************************/
434static 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/********************************************************************/
449static 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/********************************************************************/
466static 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/********************************************************************/
485static 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/********************************************************************/
500static 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/********************************************************************/
515static 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,
532
533 return buf;
534}
535
536/********************************************************************/
541static 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/********************************************************************/
556static 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
563 num++;
564 value += proute->value;
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/********************************************************************/
581static 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/********************************************************************/
596static 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
605 if (city_production_has_flag(pcity, IF_GOLD)) {
606 fc_snprintf(buf, sizeof(buf), "%s (%d)%s",
608 MAX(0, pcity->surplus[O_SHIELD]), from_worklist);
609 } else {
610 fc_snprintf(buf, sizeof(buf), "%s (--)%s",
613 }
614 } else {
615 fc_snprintf(buf, sizeof(buf), "%s (%d/%s)%s",
617 pcity->shield_stock,
620 }
621
622 return buf;
623}
624
625/********************************************************************/
630static 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
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/********************************************************************/
665static 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/********************************************************************/
680static 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/********************************************************************/
695static 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/********************************************************************/
713static 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/********************************************************************/
728static 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
744 { TRUE, -15, NULL, N_("?city:Name"), N_("City Name"),
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"),
752 { FALSE, 1, NULL, NULL, N_("Concise *=Celebrating, X=Disorder"),
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"),
786
787 { TRUE, 10, N_("Surplus"), N_("?food/production/trade:F/P/T"),
788 N_("Surplus: Food, Production, Trade"),
790 { FALSE, 3, NULL, N_("?Food surplus [short]:+F"), N_("Surplus: Food"),
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"),
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"),
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"),
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"),
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"),
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
846
847/********************************************************************/
851{
852 return num_creport_cols;
853}
854
855/********************************************************************/
859{
860 return &(city_report_specs[i].show);
861}
862
863/********************************************************************/
867{
869}
870
871/********************************************************************/
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
884 + specialist_count() + 1;
888 p = &city_report_specs[0];
889
891 "%s", _("Specialists: "));
894
895 p->show = FALSE;
896 p->width = 2;
897 p->title1 = Q_("?specialist:S");
900 _("Specialists: %s"), specialist_plural_translation(s));
902 "%s%s", (sp == 0) ? "" : ", ",
905 p->data = s;
908 p++;
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");
920 p->title2 = sp_summary;
922 p->data = NULL;
924 p->tagname = "specialists";
925 p++;
926 }
927
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
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. */
963struct datum {
964 union {
969};
970#define SPECVEC_TAG datum
971#include "specvec.h"
972
973/********************************************************************/
976static 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/********************************************************************/
991static void init_datum_number(struct datum *dat, float val)
992{
993 dat->is_numeric = TRUE;
994 dat->val.numeric_value = val;
995}
996
997/********************************************************************/
1001static void free_datum(struct datum *dat)
1002{
1003 if (!dat->is_numeric) {
1004 free(dat->val.string_value);
1005 }
1006}
1007
1008/********************************************************************/
1014static 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/********************************************************************/
1042static 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/********************************************************************/
1065static 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) {
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 */
1095 }
1096 }
1097
1098 /* if we have anything leftover then it's a string */
1099 if (str != string_start) {
1100 struct datum d;
1101
1103 datum_vector_append(data, d);
1104 }
1105}
1106
1107/********************************************************************/
1110static 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/********************************************************************/
1123int 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/********************************************************************/
1150bool 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}
#define str
Definition astring.c:76
#define n
Definition astring.c:77
int city_granary_size(int city_size)
Definition city.c:2132
int city_build_slots(const struct city *pcity)
Definition city.c:2932
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Definition city.c:727
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:820
bool city_unhappy(const struct city *pcity)
Definition city.c:1626
bool city_celebrating(const struct city *pcity)
Definition city.c:1645
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2870
static int cmp(int v1, int v2)
Definition city.c:325
bool city_production_is_genus(const struct city *pcity, enum impr_genus_id genus)
Definition city.c:717
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1996
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:700
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
@ CITIZEN_ANGRY
Definition city.h:271
@ CITIZEN_HAPPY
Definition city.h:268
@ CITIZEN_CONTENT
Definition city.h:269
@ CITIZEN_UNHAPPY
Definition city.h:270
#define city_owner(_pcity_)
Definition city.h:563
@ FEELING_FINAL
Definition city.h:284
char * city_production_cost_str(const struct city *pcity)
static const char * cr_entry_hstate_concise(const struct city *pcity, const void *data)
Definition cityrepdata.c:89
static const char * cr_entry_tradeplus(const struct city *pcity, const void *data)
static const char * cr_entry_specialist(const struct city *pcity, const void *data)
static const char * cr_entry_present(const struct city *pcity, const void *data)
static const char * cr_entry_hstate_verbose(const struct city *pcity, const void *data)
int num_city_report_spec(void)
static void init_datum_string(struct datum *dat, const char *left, const char *right)
static const char * cr_entry_nation(const struct city *pcity, const void *data)
Definition cityrepdata.c:65
static const char * cr_entry_luxury(const struct city *pcity, const void *data)
static const char * cr_entry_gold(const struct city *pcity, const void *data)
static const char * cr_entry_building(const struct city *pcity, const void *data)
static const char * cr_entry_culture(const struct city *pcity, const void *data)
static void split_string(struct datum_vector *data, const char *str)
static const char * cr_entry_plague_risk(const struct city *pcity, const void *data)
static const char * cr_entry_trade_routes(const struct city *pcity, const void *data)
void init_city_report_game_data(void)
static const char * cr_entry_size(const struct city *pcity, const void *data)
Definition cityrepdata.c:75
static void free_data(struct datum_vector *data)
static const char * cr_entry_foodplus(const struct city *pcity, const void *data)
static const char * cr_entry_science(const struct city *pcity, const void *data)
static int data_compare(const struct datum_vector *a, const struct datum_vector *b)
static const char * cr_entry_pollution(const struct city *pcity, const void *data)
static const struct city_report_spec base_city_report_specs[]
#define FUNC_TAG(var)
static const char * cr_entry_defense(const struct city *pcity, const void *data)
static const char * cr_entry_cityname(const struct city *pcity, const void *data)
Definition cityrepdata.c:53
static const char * cr_entry_continent(const struct city *pcity, const void *data)
static const char * cr_entry_performance(const struct city *pcity, const void *data)
static const char * cr_entry_build_cost(const struct city *pcity, const void *data)
static const char * cr_entry_growturns(const struct city *pcity, const void *data)
bool can_city_sell_universal(const struct city *pcity, const struct universal *target)
static const char * cr_entry_unhappy(const struct city *pcity, const void *data)
static const char * cr_entry_workers(const struct city *pcity, const void *data)
struct city_report_spec * city_report_specs
static const char * cr_entry_angry(const struct city *pcity, const void *data)
int cityrepfield_compare(const char *str1, const char *str2)
static const char * cr_entry_attack(const struct city *pcity, const void *data)
const char * city_report_spec_tagname(int i)
static const char * cr_entry_build_slots(const struct city *pcity, const void *data)
static void free_datum(struct datum *dat)
static const char * cr_entry_corruption(const struct city *pcity, const void *data)
static const char * cr_entry_specialists(const struct city *pcity, const void *data)
static const char * cr_entry_supported(const struct city *pcity, const void *data)
static const char * cr_entry_resources(const struct city *pcity, const void *data)
static void init_datum_number(struct datum *dat, float val)
static const char * cr_entry_cma(const struct city *pcity, const void *data)
static int datum_compare(const struct datum *a, const struct datum *b)
static const char * cr_entry_prodplus(const struct city *pcity, const void *data)
bool * city_report_spec_show_ptr(int i)
static const char * cr_entry_history(const struct city *pcity, const void *data)
static const char * cr_entry_content(const struct city *pcity, const void *data)
static int num_creport_cols
static const char * cr_entry_happy(const struct city *pcity, const void *data)
static const char * cr_entry_waste(const struct city *pcity, const void *data)
static const char * cr_entry_output(const struct city *pcity, const void *data)
#define NUM_CREPORT_COLS
Definition cityrepdata.h:25
const char * cmafec_get_short_descr_of_city(const struct city *pcity)
Definition cma_fec.c:221
char * resources
Definition comments.c:37
char * incite_cost
Definition comments.c:75
int city_history_gain(const struct city *pcity)
Definition culture.c:37
static void attack(QVariant data1, QVariant data2)
Definition dialogs.cpp:3009
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
#define SP_MAX
Definition fc_types.h:409
@ O_SHIELD
Definition fc_types.h:101
@ O_FOOD
Definition fc_types.h:101
@ O_TRADE
Definition fc_types.h:101
@ O_SCIENCE
Definition fc_types.h:101
@ O_LUXURY
Definition fc_types.h:101
@ O_GOLD
Definition fc_types.h:101
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:62
static struct cma_dialog * cma
bool can_city_sell_building(const struct city *pcity, const struct impr_type *pimprove)
#define fc_assert(condition)
Definition log.h:176
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
struct client_options gui_options
Definition options.c:71
int len
Definition packhand.c:127
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
const char * specialists_abbreviation_string(void)
Definition specialist.c:174
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:155
Specialist_type_id specialist_count(void)
Definition specialist.c:71
const char * specialist_abbreviation_translation(const struct specialist *sp)
Definition specialist.c:164
const char * specialists_string(const citizens *specialist_list)
Definition specialist.c:199
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
size_t size
Definition specvec.h:72
const char * tagname
Definition cityrepdata.h:35
const char *(* func)(const struct city *pcity, const void *data)
Definition cityrepdata.h:34
const char * title2
Definition cityrepdata.h:31
const char * explanation
Definition cityrepdata.h:32
const char * title1
Definition cityrepdata.h:30
Definition city.h:320
int surplus[O_LAST]
Definition city.h:355
int food_stock
Definition city.h:367
int history
Definition city.h:410
int pollution
Definition city.h:369
int waste[O_LAST]
Definition city.h:356
struct worklist worklist
Definition city.h:401
int culture
Definition city.h:465
int buy_cost
Definition city.h:466
citizens feel[CITIZEN_LAST][FEELING_LAST]
Definition city.h:333
citizens specialists[SP_MAX]
Definition city.h:336
struct tile * tile
Definition city.h:322
int shield_stock
Definition city.h:368
int prod[O_LAST]
Definition city.h:358
struct unit_list * units_supported
Definition city.h:406
struct city::@17::@20 client
struct packet_game_info info
Definition game.h:89
bool concise_city_production
Definition options.h:163
union datum::@130 val
float numeric_value
bool is_numeric
char * string_value
struct unit_list * units
Definition tile.h:58
Continent_id continent
Definition tile.h:54
int defense_strength
Definition unittype.h:516
int attack_strength
Definition unittype.h:515
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
const struct impr_type * building
Definition fc_types.h:714
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66