Freeciv-3.4
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_getx(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",
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];
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_assert_ret_val(sp != nullptr, nullptr);
268
269 fc_snprintf(buf, sizeof(buf), "%2d",
270 pcity->specialists[specialist_index(sp)]);
271
272 return buf;
273}
274
275/********************************************************************/
280static const char *cr_entry_attack(const struct city *pcity,
281 const void *data)
282{
283 static char buf[32];
284 int attack_best[4] = {-1, -1, -1, -1}, i;
285
287 /* What about allied units? Should we just count them? */
289
290 /* Now that the element is appended to the end of the list, we simply
291 do an insertion sort. */
292 for (i = 2; i >= 0 && attack_best[i] < attack_best[i + 1]; i--) {
293 int tmp = attack_best[i];
294
295 attack_best[i] = attack_best[i + 1];
296 attack_best[i + 1] = tmp;
297 }
299
300 buf[0] = '\0';
301 for (i = 0; i < 3; i++) {
302 if (attack_best[i] >= 0) {
303 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
304 attack_best[i]);
305 } else {
306 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
307 }
308 }
309
310 return buf;
311}
312
313/********************************************************************/
318static const char *cr_entry_defense(const struct city *pcity,
319 const void *data)
320{
321 static char buf[32];
322 int defense_best[4] = {-1, -1, -1, -1}, i;
323
325 /* What about allied units? Should we just count them? */
327
328 /* Now that the element is appended to the end of the list, we simply
329 do an insertion sort. */
330 for (i = 2; i >= 0 && defense_best[i] < defense_best[i + 1]; i--) {
331 int tmp = defense_best[i];
332
334 defense_best[i + 1] = tmp;
335 }
337
338 buf[0] = '\0';
339 for (i = 0; i < 3; i++) {
340 if (defense_best[i] >= 0) {
341 cat_snprintf(buf, sizeof(buf), "%s%d", (i > 0) ? "/" : "",
342 defense_best[i]);
343 } else {
344 cat_snprintf(buf, sizeof(buf), "%s-", (i > 0) ? "/" : "");
345 }
346 }
347
348 return buf;
349}
350
351/********************************************************************/
356static const char *cr_entry_supported(const struct city *pcity,
357 const void *data)
358{
359 static char buf[8];
360 int num_supported = unit_list_size(pcity->units_supported);
361
362 fc_snprintf(buf, sizeof(buf), "%2d", num_supported);
363
364 return buf;
365}
366
367/********************************************************************/
372static const char *cr_entry_present(const struct city *pcity,
373 const void *data)
374{
375 static char buf[8];
377
378 fc_snprintf(buf, sizeof(buf), "%2d", num_present);
379
380 return buf;
381}
382
383/********************************************************************/
388static const char *cr_entry_resources(const struct city *pcity,
389 const void *data)
390{
391 static char buf[32];
392
393 fc_snprintf(buf, sizeof(buf), "%d/%d/%d",
394 pcity->surplus[O_FOOD],
395 pcity->surplus[O_SHIELD],
396 pcity->surplus[O_TRADE]);
397
398 return buf;
399}
400
401/********************************************************************/
406static const char *cr_entry_foodplus(const struct city *pcity,
407 const void *data)
408{
409 static char buf[8];
410
411 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_FOOD]);
412
413 return buf;
414}
415
416/********************************************************************/
421static const char *cr_entry_prodplus(const struct city *pcity,
422 const void *data)
423{
424 static char buf[8];
425
426 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_SHIELD]);
427
428 return buf;
429}
430
431/********************************************************************/
436static const char *cr_entry_tradeplus(const struct city *pcity,
437 const void *data)
438{
439 static char buf[8];
440
441 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_TRADE]);
442
443 return buf;
444}
445
446/********************************************************************/
451static const char *cr_entry_output(const struct city *pcity,
452 const void *data)
453{
454 static char buf[32];
455 int goldie = pcity->surplus[O_GOLD];
456
457 fc_snprintf(buf, sizeof(buf), "%3d/%d/%d",
458 goldie, pcity->prod[O_LUXURY], pcity->prod[O_SCIENCE]);
459
460 return buf;
461}
462
463/********************************************************************/
468static const char *cr_entry_gold(const struct city *pcity,
469 const void *data)
470{
471 static char buf[8];
472
473 if (pcity->surplus[O_GOLD] > 0) {
474 fc_snprintf(buf, sizeof(buf), "+%d", pcity->surplus[O_GOLD]);
475 } else {
476 fc_snprintf(buf, sizeof(buf), "%3d", pcity->surplus[O_GOLD]);
477 }
478
479 return buf;
480}
481
482/********************************************************************/
487static const char *cr_entry_luxury(const struct city *pcity,
488 const void *data)
489{
490 static char buf[8];
491
492 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_LUXURY]);
493
494 return buf;
495}
496
497/********************************************************************/
502static const char *cr_entry_science(const struct city *pcity,
503 const void *data)
504{
505 static char buf[8];
506
507 fc_snprintf(buf, sizeof(buf), "%3d", pcity->prod[O_SCIENCE]);
508
509 return buf;
510}
511
512/********************************************************************/
517static const char *cr_entry_growturns(const struct city *pcity,
518 const void *data)
519{
520 int turns = city_turns_to_grow(pcity);
521 char buffer[8];
522 static char buf[32];
523
524 if (turns == FC_INFINITY) {
525 /* 'never' wouldn't be easily translatable here. */
526 fc_snprintf(buffer, sizeof(buffer), "---");
527 } else {
528 /* Shrinking cities get a negative value. */
529 fc_snprintf(buffer, sizeof(buffer), "%4d", turns);
530 }
531 fc_snprintf(buf, sizeof(buf), "%s (%d/%d)",
532 buffer, pcity->food_stock,
534
535 return buf;
536}
537
538/********************************************************************/
543static const char *cr_entry_pollution(const struct city *pcity,
544 const void *data)
545{
546 static char buf[8];
547
548 fc_snprintf(buf, sizeof(buf), "%3d", pcity->pollution);
549
550 return buf;
551}
552
553/********************************************************************/
558static const char *cr_entry_trade_routes(const struct city *pcity,
559 const void *data)
560{
561 static char buf[16];
562 int num = 0, value = 0;
563
565 num++;
566 value += proute->value;
568
569 if (0 == num) {
570 sz_strlcpy(buf, "0");
571 } else {
572 fc_snprintf(buf, sizeof(buf), "%d (+%d)", num, value);
573 }
574
575 return buf;
576}
577
578/********************************************************************/
583static const char *cr_entry_build_slots(const struct city *pcity,
584 const void *data)
585{
586 static char buf[8];
587
588 fc_snprintf(buf, sizeof(buf), "%3d", city_build_slots(pcity));
589
590 return buf;
591}
592
593/********************************************************************/
598static const char *cr_entry_building(const struct city *pcity,
599 const void *data)
600{
601 static char buf[192];
602 const char *from_worklist =
603 worklist_is_empty(&pcity->worklist) ? "" :
604 gui_options.concise_city_production ? "+" : _("(worklist)");
605
609 fc_snprintf(buf, sizeof(buf), "%s (%d)%s",
611 MAX(0, pcity->surplus[O_SHIELD]), from_worklist);
612 } else {
613 fc_snprintf(buf, sizeof(buf), "%s (--)%s",
616 }
617 } else {
618 fc_snprintf(buf, sizeof(buf), "%s (%d/%s)%s",
620 pcity->shield_stock,
623 }
624
625 return buf;
626}
627
628/********************************************************************/
633static const char *cr_entry_build_cost(const struct city *pcity,
634 const void *data)
635{
636 char bufone[8];
637 char buftwo[8];
638 static char buf[32];
639 int price;
640 int turns;
641
643 fc_snprintf(buf, sizeof(buf), "*");
644 return buf;
645 }
646 price = pcity->client.buy_cost;
648
649 if (price > 99999) {
650 fc_snprintf(bufone, sizeof(bufone), "---");
651 } else {
652 fc_snprintf(bufone, sizeof(bufone), "%d", price);
653 }
654 if (turns > 999) {
655 fc_snprintf(buftwo, sizeof(buftwo), "--");
656 } else {
657 fc_snprintf(buftwo, sizeof(buftwo), "%3d", turns);
658 }
659 fc_snprintf(buf, sizeof(buf), "%s/%s", buftwo, bufone);
660 return buf;
661}
662
663/********************************************************************/
668static const char *cr_entry_corruption(const struct city *pcity,
669 const void *data)
670{
671 static char buf[8];
672
673 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_TRADE]));
674
675 return buf;
676}
677
678/********************************************************************/
683static const char *cr_entry_waste(const struct city *pcity,
684 const void *data)
685{
686 static char buf[8];
687
688 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_SHIELD]));
689
690 return buf;
691}
692
693/********************************************************************/
698static const char *cr_entry_plague_risk(const struct city *pcity,
699 const void *data)
700{
701 static char buf[8];
702
703 if (!game.info.illness_on) {
704 fc_snprintf(buf, sizeof(buf), " -.-");
705 } else {
706 fc_snprintf(buf, sizeof(buf), "%4.1f",
707 (float)city_illness_calc(pcity, NULL, NULL, NULL, NULL)/10.0);
708 }
709
710 return buf;
711}
712
713/********************************************************************/
716static const char *cr_entry_continent(const struct city *pcity,
717 const void *data)
718{
719 static char buf[8];
720
721 fc_snprintf(buf, sizeof(buf), "%3d", pcity->tile->continent);
722
723 return buf;
724}
725
726/********************************************************************/
731static const char *cr_entry_cma(const struct city *pcity,
732 const void *data)
733{
735}
736
737/* City report options (which columns get shown)
738 * To add a new entry, you should just have to:
739 * - add a function like those above
740 * - add an entry in the base_city_report_specs[] table
741 */
742
743/* This generates the function name and the tagname: */
744#define FUNC_TAG(var) cr_entry_##var, #var
745
747 { TRUE, -15, NULL, N_("?city:Name"), N_("City Name"),
748 NULL, FUNC_TAG(cityname) },
749 { FALSE, -15, NULL, N_("Nation"), N_("Nation"),
750 NULL, FUNC_TAG(nation) },
751 { TRUE, 2, NULL, N_("?size [short]:Sz"), N_("Size"),
752 NULL, FUNC_TAG(size) },
753 { TRUE, -8, NULL, N_("State"), N_("Celebrating/Peace/Disorder"),
755 { FALSE, 1, NULL, NULL, N_("Concise *=Celebrating, X=Disorder"),
757
758 { FALSE, 2, NULL, N_("?Happy workers:H"), N_("Workers: Happy"),
759 NULL, FUNC_TAG(happy) },
760 { FALSE, 2, NULL, N_("?Content workers:C"), N_("Workers: Content"),
761 NULL, FUNC_TAG(content) },
762 { FALSE, 2, NULL, N_("?Unhappy workers:U"), N_("Workers: Unhappy"),
763 NULL, FUNC_TAG(unhappy) },
764 { FALSE, 2, NULL, N_("?Angry workers:A"), N_("Workers: Angry"),
765 NULL, FUNC_TAG(angry) },
766 { TRUE, 10, N_("?city:Workers"),
767 N_("?happy/content/unhappy/angry:H/C/U/A"),
768 N_("Workers: Happy, Content, Unhappy, Angry"),
769 NULL, FUNC_TAG(workers) },
770
771 { FALSE, 8, N_("Best"), N_("attack"),
772 N_("Best attacking units"), NULL, FUNC_TAG(attack)},
773 { FALSE, 8, N_("Best"), N_("defense"),
774 N_("Best defending units"), NULL, FUNC_TAG(defense)},
775 { FALSE, 2, N_("Units"),
776 /* TRANS: Header "Number of units inside city" */
777 N_("?Present (units):Here"),
778 N_("Number of units present"), NULL, FUNC_TAG(present) },
779 { FALSE, 2, N_("Units"),
780 /* TRANS: Header "Number of units supported by given city" */
781 N_("?Supported (units):Owned"),
782 N_("Number of units supported"), NULL, FUNC_TAG(supported) },
783
784 { /* TRANS: Header "It will take this many turns before city grows" */
785 TRUE, 14, N_("?food (population):Grow"),
786 N_("?Stock/Target:(Have/Need)"),
787 N_("Turns until growth/famine"),
789
790 { TRUE, 10, N_("Surplus"), N_("?food/production/trade:F/P/T"),
791 N_("Surplus: Food, Production, Trade"),
793 { FALSE, 3, NULL, N_("?Food surplus [short]:+F"), N_("Surplus: Food"),
795 { FALSE, 3, NULL, N_("?Production surplus [short]:+P"),
796 N_("Surplus: Production"), NULL, FUNC_TAG(prodplus) },
797 { FALSE, 3, NULL, N_("?Production loss (waste) [short]:-P"),
798 N_("Waste"), NULL, FUNC_TAG(waste) },
799 { FALSE, 3, NULL, N_("?Trade surplus [short]:+T"), N_("Surplus: Trade"),
801 { FALSE, 3, NULL, N_("?Trade loss (corruption) [short]:-T"),
802 N_("Corruption"), NULL, FUNC_TAG(corruption) },
803
804 { TRUE, 10, N_("Economy"), N_("?gold/luxury/science:G/L/S"),
805 N_("Economy: Gold, Luxuries, Science"),
806 NULL, FUNC_TAG(output) },
807 { FALSE, 3, NULL, N_("?Gold:G"), N_("Economy: Gold"),
808 NULL, FUNC_TAG(gold) },
809 { FALSE, 3, NULL, N_("?Luxury:L"), N_("Economy: Luxury"),
810 NULL, FUNC_TAG(luxury) },
811 { FALSE, 3, NULL, N_("?Science:S"), N_("Economy: Science"),
812 NULL, FUNC_TAG(science) },
813 { FALSE, 3, NULL, N_("?Culture:Clt"), N_("Culture (History+Performance)"),
814 NULL, FUNC_TAG(culture) },
815 { FALSE, 3, NULL, N_("?History:Hst"),
816 N_("Culture: History (and gain per turn)"),
817 NULL, FUNC_TAG(history) },
818 { FALSE, 3, NULL, N_("?Performance:Prf"), N_("Culture: Performance"),
820 { FALSE, 3, NULL, N_("?Continent:C"), N_("Continent number"),
821 NULL, FUNC_TAG(continent) },
822 { FALSE, 6, N_("?number_trade_routes:Trade"),
823 N_("?number_trade_routes:Routes"),
824 N_("Number (and total value) of trade routes"),
826 { FALSE, 3, NULL, N_("?pollution [short]:Pol"), N_("?stats:Pollution"),
827 NULL, FUNC_TAG(pollution) },
828 { FALSE, 4, N_("?plague risk [short]:Pla"), N_("(%)"),
829 N_("Plague risk per turn"),
831 { FALSE, 15, NULL, N_("?cma:Governor"), N_("Citizen Governor"),
832 NULL, FUNC_TAG(cma) },
833
834 /* TRANS: "BS" = "build slots" */
835 { FALSE, 3, NULL, N_("BS"), N_("Maximum units buildable per turn"),
837 { TRUE, 9, N_("Production"), N_("Turns/Buy"),
838 /* N_("Turns or gold to complete production"), future menu needs translation */
839 N_("Production"),
840 NULL, FUNC_TAG(build_cost) },
841 { TRUE, 0, N_("Currently Building"),
842 N_("?Stock/Target:(Have/Need)"),
843 N_("Currently Building"),
844 NULL, FUNC_TAG(building) }
845};
846
849
850/********************************************************************/
854{
855 return num_creport_cols;
856}
857
858/********************************************************************/
862{
863 return &(city_report_specs[i].show);
864}
865
866/********************************************************************/
870{
872}
873
874/********************************************************************/
880{
881 static char sp_explanation[SP_MAX][128];
882 static char sp_explanations[SP_MAX*128];
883 struct city_report_spec *p;
884 int i;
885
887 + specialist_count() + 1;
891 p = &city_report_specs[0];
892
894 "%s", _("Specialists: "));
897
898 p->show = FALSE;
899 p->width = 2;
900 p->title1 = Q_("?specialist:S");
903 _("Specialists: %s"), specialist_plural_translation(s));
905 "%s%s", (sp == 0) ? "" : ", ",
908 p->data = s;
911 p++;
913
914 /* Summary column for all specialists. */
915 {
916 static char sp_summary[128];
917
918 p->show = FALSE;
919 p->width = MAX(7, specialist_count() * 2 - 1);
920 p->title1 = _("Special");
923 p->title2 = sp_summary;
925 p->data = NULL;
927 p->tagname = "specialists";
928 p++;
929 }
930
932 sizeof(base_city_report_specs));
933
934 for (i = 0; i < ARRAY_SIZE(base_city_report_specs); i++) {
935 if (p->title1) {
936 p->title1 = Q_(p->title1);
937 }
938 if (p->title2) {
939 p->title2 = Q_(p->title2);
940 }
941 p->explanation = Q_(p->explanation);
942 p++;
943 }
944
946 + specialist_count() + 1);
947}
948
949/************************************************************************
950 The following several functions allow intelligent sorting city report
951 fields by column. This doesn't necessarily do the right thing, but
952 it's better than sorting alphabetically.
953
954 The GUI gives us two values to compare (as strings). We try to split
955 them into an array of numeric and string fields, then we compare
956 lexicographically. Two numeric fields are compared in the obvious
957 way, two character fields are compared alphabetically.
958 Arbitrarily, a numeric field is sorted before a character field
959 (for "justification" note that numbers are before letters
960 in the ASCII table).
961************************************************************************/
962
963/* A datum is one short string, or one number.
964 A datum_vector represents a long string of alternating strings and
965 numbers. */
966struct datum {
967 union {
972};
973#define SPECVEC_TAG datum
974#include "specvec.h"
975
976/********************************************************************/
979static void init_datum_string(struct datum *dat, const char *left,
980 const char *right)
981{
982 int len = right - left;
983
984 dat->is_numeric = FALSE;
985 dat->val.string_value = fc_malloc(len + 1);
986 memcpy(dat->val.string_value, left, len);
987 dat->val.string_value[len] = 0;
988}
989
990/********************************************************************/
994static void init_datum_number(struct datum *dat, float val)
995{
996 dat->is_numeric = TRUE;
997 dat->val.numeric_value = val;
998}
999
1000/********************************************************************/
1004static void free_datum(struct datum *dat)
1005{
1006 if (!dat->is_numeric) {
1007 free(dat->val.string_value);
1008 }
1009}
1010
1011/********************************************************************/
1017static int datum_compare(const struct datum *a, const struct datum *b)
1018{
1019 if (a->is_numeric == b->is_numeric) {
1020 if (a->is_numeric) {
1021 if (a->val.numeric_value == b->val.numeric_value) {
1022 return 0;
1023 } else if (a->val.numeric_value < b->val.numeric_value) {
1024 return -1;
1025 } else if (a->val.numeric_value > b->val.numeric_value) {
1026 return +1;
1027 } else {
1028 return 0; /* shrug */
1029 }
1030 } else {
1031 return strcmp(a->val.string_value, b->val.string_value);
1032 }
1033 } else {
1034 if (a->is_numeric) {
1035 return -1;
1036 } else {
1037 return 1;
1038 }
1039 }
1040}
1041
1042/********************************************************************/
1045static int data_compare(const struct datum_vector *a,
1046 const struct datum_vector *b)
1047{
1048 int i, n;
1049
1050 n = MIN(a->size, b->size);
1051
1052 for (i = 0; i < n; i++) {
1053 int cmp = datum_compare(&a->p[i], &b->p[i]);
1054
1055 if (cmp != 0) {
1056 return cmp;
1057 }
1058 }
1059
1060 /* The first n fields match; whoever has more fields goes last.
1061 If they have equal numbers, the two really are equal. */
1062 return a->size - b->size;
1063}
1064
1065/********************************************************************/
1068static void split_string(struct datum_vector *data, const char *str)
1069{
1070 const char *string_start;
1071
1072 datum_vector_init(data);
1073 string_start = str;
1074 while (*str) {
1075 char *endptr;
1076 float value;
1077
1078 errno = 0;
1079 value = strtof(str, &endptr);
1080 if (errno != 0 || endptr == str || !isfinite(value)) {
1081 /* that wasn't a sensible number; go on */
1082 str++;
1083 } else {
1084 /* that was a number, so stop the string we were parsing, add
1085 it (unless it's empty), then add the number we just parsed */
1086 struct datum d;
1087
1088 if (str != string_start) {
1090 datum_vector_append(data, d);
1091 }
1092
1093 init_datum_number(&d, value);
1094 datum_vector_append(data, d);
1095
1096 /* finally, update the string position pointers */
1098 }
1099 }
1100
1101 /* if we have anything leftover then it's a string */
1102 if (str != string_start) {
1103 struct datum d;
1104
1106 datum_vector_append(data, d);
1107 }
1108}
1109
1110/********************************************************************/
1113static void free_data(struct datum_vector *data)
1114{
1115 int i;
1116
1117 for (i = 0; i < data->size; i++) {
1118 free_datum(&data->p[i]);
1119 }
1120 datum_vector_free(data);
1121}
1122
1123/********************************************************************/
1126int cityrepfield_compare(const char *str1, const char *str2)
1127{
1128 struct datum_vector data1, data2;
1129 int retval;
1130
1131 if (str1 == str2) {
1132 return 0;
1133 } else if (NULL == str1) {
1134 return 1;
1135 } else if (NULL == str2) {
1136 return -1;
1137 }
1138
1139 split_string(&data1, str1);
1140 split_string(&data2, str2);
1141
1142 retval = data_compare(&data1, &data2);
1143
1144 free_data(&data1);
1145 free_data(&data2);
1146
1147 return retval;
1148}
1149
1150/********************************************************************/
1154 const struct universal *target)
1155{
1156 return target->kind == VUT_IMPROVEMENT
1158}
#define str
Definition astring.c:76
#define n
Definition astring.c:77
const char * city_name_getx(const struct city *pcity)
Definition city.c:1166
int city_granary_size(int city_size)
Definition city.c:2199
int city_build_slots(const struct city *pcity)
Definition city.c:3000
bool city_production_has_flag(const struct city *pcity, enum impr_flag_id flag)
Definition city.c:730
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:824
bool city_unhappy(const struct city *pcity)
Definition city.c:1679
bool city_celebrating(const struct city *pcity)
Definition city.c:1698
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2938
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:720
int city_turns_to_grow(const struct city *pcity)
Definition city.c:2049
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:703
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
@ CITIZEN_ANGRY
Definition city.h:269
@ CITIZEN_HAPPY
Definition city.h:266
@ CITIZEN_CONTENT
Definition city.h:267
@ CITIZEN_UNHAPPY
Definition city.h:268
#define city_owner(_pcity_)
Definition city.h:564
@ FEELING_FINAL
Definition city.h:282
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:77
int city_history_gain(const struct city *pcity)
Definition culture.c:39
static void attack(QVariant data1, QVariant data2)
Definition dialogs.cpp:3497
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
#define SP_MAX
Definition fc_types.h:269
@ O_SHIELD
Definition fc_types.h:103
@ O_FOOD
Definition fc_types.h:103
@ O_TRADE
Definition fc_types.h:103
@ O_SCIENCE
Definition fc_types.h:103
@ O_LUXURY
Definition fc_types.h:103
@ O_GOLD
Definition fc_types.h:103
#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:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#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:129
#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:237
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:90
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
const char * specialist_plural_translation(const struct specialist *sp)
Definition specialist.c:168
Specialist_type_id specialist_count(void)
Definition specialist.c:71
const char * specialist_abbreviation_translation(const struct specialist *sp)
Definition specialist.c:179
const char * specialists_string(const citizens *specialist_list)
Definition specialist.c:262
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
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:318
struct packet_game_info info
Definition game.h:89
bool concise_city_production
Definition options.h:164
float numeric_value
bool is_numeric
char * string_value
union datum::@134 val
struct unit_list * units
Definition tile.h:58
Continent_id continent
Definition tile.h:54
int defense_strength
Definition unittype.h:523
int attack_strength
Definition unittype.h:522
struct tile * tile
Definition unit.h:141
struct unit::@84::@86 client
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
#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:529
#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:126
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66