Freeciv-3.3
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",
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_snprintf(buf, sizeof(buf), "%2d",
268 pcity->specialists[specialist_index(sp)]);
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];
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/********************************************************************/
370static const char *cr_entry_present(const struct city *pcity,
371 const void *data)
372{
373 static char buf[8];
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
607 fc_snprintf(buf, sizeof(buf), "%s (%d)%s",
609 MAX(0, pcity->surplus[O_SHIELD]), from_worklist);
610 } else {
611 fc_snprintf(buf, sizeof(buf), "%s (--)%s",
614 }
615 } else {
616 fc_snprintf(buf, sizeof(buf), "%s (%d/%s)%s",
618 pcity->shield_stock,
621 }
622
623 return buf;
624}
625
626/********************************************************************/
631static const char *cr_entry_build_cost(const struct city *pcity,
632 const void *data)
633{
634 char bufone[8];
635 char buftwo[8];
636 static char buf[32];
637 int price;
638 int turns;
639
641 fc_snprintf(buf, sizeof(buf), "*");
642 return buf;
643 }
644 price = pcity->client.buy_cost;
646
647 if (price > 99999) {
648 fc_snprintf(bufone, sizeof(bufone), "---");
649 } else {
650 fc_snprintf(bufone, sizeof(bufone), "%d", price);
651 }
652 if (turns > 999) {
653 fc_snprintf(buftwo, sizeof(buftwo), "--");
654 } else {
655 fc_snprintf(buftwo, sizeof(buftwo), "%3d", turns);
656 }
657 fc_snprintf(buf, sizeof(buf), "%s/%s", buftwo, bufone);
658 return buf;
659}
660
661/********************************************************************/
666static const char *cr_entry_corruption(const struct city *pcity,
667 const void *data)
668{
669 static char buf[8];
670
671 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_TRADE]));
672
673 return buf;
674}
675
676/********************************************************************/
681static const char *cr_entry_waste(const struct city *pcity,
682 const void *data)
683{
684 static char buf[8];
685
686 fc_snprintf(buf, sizeof(buf), "%3d", -(pcity->waste[O_SHIELD]));
687
688 return buf;
689}
690
691/********************************************************************/
696static const char *cr_entry_plague_risk(const struct city *pcity,
697 const void *data)
698{
699 static char buf[8];
700
701 if (!game.info.illness_on) {
702 fc_snprintf(buf, sizeof(buf), " -.-");
703 } else {
704 fc_snprintf(buf, sizeof(buf), "%4.1f",
705 (float)city_illness_calc(pcity, NULL, NULL, NULL, NULL)/10.0);
706 }
707
708 return buf;
709}
710
711/********************************************************************/
714static const char *cr_entry_continent(const struct city *pcity,
715 const void *data)
716{
717 static char buf[8];
718
719 fc_snprintf(buf, sizeof(buf), "%3d", pcity->tile->continent);
720
721 return buf;
722}
723
724/********************************************************************/
729static const char *cr_entry_cma(const struct city *pcity,
730 const void *data)
731{
733}
734
735/* City report options (which columns get shown)
736 * To add a new entry, you should just have to:
737 * - add a function like those above
738 * - add an entry in the base_city_report_specs[] table
739 */
740
741/* This generates the function name and the tagname: */
742#define FUNC_TAG(var) cr_entry_##var, #var
743
745 { TRUE, -15, NULL, N_("?city:Name"), N_("City Name"),
746 NULL, FUNC_TAG(cityname) },
747 { FALSE, -15, NULL, N_("Nation"), N_("Nation"),
748 NULL, FUNC_TAG(nation) },
749 { TRUE, 2, NULL, N_("?size [short]:Sz"), N_("Size"),
750 NULL, FUNC_TAG(size) },
751 { TRUE, -8, NULL, N_("State"), N_("Celebrating/Peace/Disorder"),
753 { FALSE, 1, NULL, NULL, N_("Concise *=Celebrating, X=Disorder"),
755
756 { FALSE, 2, NULL, N_("?Happy workers:H"), N_("Workers: Happy"),
757 NULL, FUNC_TAG(happy) },
758 { FALSE, 2, NULL, N_("?Content workers:C"), N_("Workers: Content"),
759 NULL, FUNC_TAG(content) },
760 { FALSE, 2, NULL, N_("?Unhappy workers:U"), N_("Workers: Unhappy"),
761 NULL, FUNC_TAG(unhappy) },
762 { FALSE, 2, NULL, N_("?Angry workers:A"), N_("Workers: Angry"),
763 NULL, FUNC_TAG(angry) },
764 { TRUE, 10, N_("?city:Workers"),
765 N_("?happy/content/unhappy/angry:H/C/U/A"),
766 N_("Workers: Happy, Content, Unhappy, Angry"),
767 NULL, FUNC_TAG(workers) },
768
769 { FALSE, 8, N_("Best"), N_("attack"),
770 N_("Best attacking units"), NULL, FUNC_TAG(attack)},
771 { FALSE, 8, N_("Best"), N_("defense"),
772 N_("Best defending units"), NULL, FUNC_TAG(defense)},
773 { FALSE, 2, N_("Units"),
774 /* TRANS: Header "Number of units inside city" */
775 N_("?Present (units):Here"),
776 N_("Number of units present"), NULL, FUNC_TAG(present) },
777 { FALSE, 2, N_("Units"),
778 /* TRANS: Header "Number of units supported by given city" */
779 N_("?Supported (units):Owned"),
780 N_("Number of units supported"), NULL, FUNC_TAG(supported) },
781
782 { /* TRANS: Header "It will take this many turns before city grows" */
783 TRUE, 14, N_("?food (population):Grow"),
784 N_("?Stock/Target:(Have/Need)"),
785 N_("Turns until growth/famine"),
787
788 { TRUE, 10, N_("Surplus"), N_("?food/production/trade:F/P/T"),
789 N_("Surplus: Food, Production, Trade"),
791 { FALSE, 3, NULL, N_("?Food surplus [short]:+F"), N_("Surplus: Food"),
793 { FALSE, 3, NULL, N_("?Production surplus [short]:+P"),
794 N_("Surplus: Production"), NULL, FUNC_TAG(prodplus) },
795 { FALSE, 3, NULL, N_("?Production loss (waste) [short]:-P"),
796 N_("Waste"), NULL, FUNC_TAG(waste) },
797 { FALSE, 3, NULL, N_("?Trade surplus [short]:+T"), N_("Surplus: Trade"),
799 { FALSE, 3, NULL, N_("?Trade loss (corruption) [short]:-T"),
800 N_("Corruption"), NULL, FUNC_TAG(corruption) },
801
802 { TRUE, 10, N_("Economy"), N_("?gold/luxury/science:G/L/S"),
803 N_("Economy: Gold, Luxuries, Science"),
804 NULL, FUNC_TAG(output) },
805 { FALSE, 3, NULL, N_("?Gold:G"), N_("Economy: Gold"),
806 NULL, FUNC_TAG(gold) },
807 { FALSE, 3, NULL, N_("?Luxury:L"), N_("Economy: Luxury"),
808 NULL, FUNC_TAG(luxury) },
809 { FALSE, 3, NULL, N_("?Science:S"), N_("Economy: Science"),
810 NULL, FUNC_TAG(science) },
811 { FALSE, 3, NULL, N_("?Culture:Clt"), N_("Culture (History+Performance)"),
812 NULL, FUNC_TAG(culture) },
813 { FALSE, 3, NULL, N_("?History:Hst"),
814 N_("Culture: History (and gain per turn)"),
815 NULL, FUNC_TAG(history) },
816 { FALSE, 3, NULL, N_("?Performance:Prf"), N_("Culture: Performance"),
818 { FALSE, 3, NULL, N_("?Continent:C"), N_("Continent number"),
819 NULL, FUNC_TAG(continent) },
820 { FALSE, 1, N_("?number_trade_routes:n"),
821 N_("?number_trade_routes:R"),
822 N_("Number (and total value) of trade routes"),
824 { FALSE, 3, NULL, N_("?pollution [short]:Pol"), N_("?stats:Pollution"),
825 NULL, FUNC_TAG(pollution) },
826 { FALSE, 4, N_("?plague risk [short]:Pla"), N_("(%)"),
827 N_("Plague risk per turn"),
829 { FALSE, 15, NULL, N_("?cma:Governor"), N_("Citizen Governor"),
830 NULL, FUNC_TAG(cma) },
831
832 /* TRANS: "BS" = "build slots" */
833 { FALSE, 3, NULL, N_("BS"), N_("Maximum units buildable per turn"),
835 { TRUE, 9, N_("Production"), N_("Turns/Buy"),
836 /* N_("Turns or gold to complete production"), future menu needs translation */
837 N_("Production"),
838 NULL, FUNC_TAG(build_cost) },
839 { TRUE, 0, N_("Currently Building"),
840 N_("?Stock/Target:(Have/Need)"),
841 N_("Currently Building"),
842 NULL, FUNC_TAG(building) }
843};
844
847
848/********************************************************************/
852{
853 return num_creport_cols;
854}
855
856/********************************************************************/
860{
861 return &(city_report_specs[i].show);
862}
863
864/********************************************************************/
868{
870}
871
872/********************************************************************/
878{
879 static char sp_explanation[SP_MAX][128];
880 static char sp_explanations[SP_MAX*128];
881 struct city_report_spec *p;
882 int i;
883
885 + specialist_count() + 1;
889 p = &city_report_specs[0];
890
892 "%s", _("Specialists: "));
895
896 p->show = FALSE;
897 p->width = 2;
898 p->title1 = Q_("?specialist:S");
901 _("Specialists: %s"), specialist_plural_translation(s));
903 "%s%s", (sp == 0) ? "" : ", ",
906 p->data = s;
909 p++;
911
912 /* Summary column for all specialists. */
913 {
914 static char sp_summary[128];
915
916 p->show = FALSE;
917 p->width = MAX(7, specialist_count() * 2 - 1);
918 p->title1 = _("Special");
921 p->title2 = sp_summary;
923 p->data = NULL;
925 p->tagname = "specialists";
926 p++;
927 }
928
930 sizeof(base_city_report_specs));
931
932 for (i = 0; i < ARRAY_SIZE(base_city_report_specs); i++) {
933 if (p->title1) {
934 p->title1 = Q_(p->title1);
935 }
936 if (p->title2) {
937 p->title2 = Q_(p->title2);
938 }
939 p->explanation = Q_(p->explanation);
940 p++;
941 }
942
944 + specialist_count() + 1);
945}
946
947/************************************************************************
948 The following several functions allow intelligent sorting city report
949 fields by column. This doesn't necessarily do the right thing, but
950 it's better than sorting alphabetically.
951
952 The GUI gives us two values to compare (as strings). We try to split
953 them into an array of numeric and string fields, then we compare
954 lexicographically. Two numeric fields are compared in the obvious
955 way, two character fields are compared alphabetically.
956 Arbitrarily, a numeric field is sorted before a character field
957 (for "justification" note that numbers are before letters
958 in the ASCII table).
959************************************************************************/
960
961/* A datum is one short string, or one number.
962 A datum_vector represents a long string of alternating strings and
963 numbers. */
964struct datum {
965 union {
970};
971#define SPECVEC_TAG datum
972#include "specvec.h"
973
974/********************************************************************/
977static void init_datum_string(struct datum *dat, const char *left,
978 const char *right)
979{
980 int len = right - left;
981
982 dat->is_numeric = FALSE;
983 dat->val.string_value = fc_malloc(len + 1);
984 memcpy(dat->val.string_value, left, len);
985 dat->val.string_value[len] = 0;
986}
987
988/********************************************************************/
992static void init_datum_number(struct datum *dat, float val)
993{
994 dat->is_numeric = TRUE;
995 dat->val.numeric_value = val;
996}
997
998/********************************************************************/
1002static void free_datum(struct datum *dat)
1003{
1004 if (!dat->is_numeric) {
1005 free(dat->val.string_value);
1006 }
1007}
1008
1009/********************************************************************/
1015static int datum_compare(const struct datum *a, const struct datum *b)
1016{
1017 if (a->is_numeric == b->is_numeric) {
1018 if (a->is_numeric) {
1019 if (a->val.numeric_value == b->val.numeric_value) {
1020 return 0;
1021 } else if (a->val.numeric_value < b->val.numeric_value) {
1022 return -1;
1023 } else if (a->val.numeric_value > b->val.numeric_value) {
1024 return +1;
1025 } else {
1026 return 0; /* shrug */
1027 }
1028 } else {
1029 return strcmp(a->val.string_value, b->val.string_value);
1030 }
1031 } else {
1032 if (a->is_numeric) {
1033 return -1;
1034 } else {
1035 return 1;
1036 }
1037 }
1038}
1039
1040/********************************************************************/
1043static int data_compare(const struct datum_vector *a,
1044 const struct datum_vector *b)
1045{
1046 int i, n;
1047
1048 n = MIN(a->size, b->size);
1049
1050 for (i = 0; i < n; i++) {
1051 int cmp = datum_compare(&a->p[i], &b->p[i]);
1052
1053 if (cmp != 0) {
1054 return cmp;
1055 }
1056 }
1057
1058 /* The first n fields match; whoever has more fields goes last.
1059 If they have equal numbers, the two really are equal. */
1060 return a->size - b->size;
1061}
1062
1063/********************************************************************/
1066static void split_string(struct datum_vector *data, const char *str)
1067{
1068 const char *string_start;
1069
1070 datum_vector_init(data);
1071 string_start = str;
1072 while (*str) {
1073 char *endptr;
1074 float value;
1075
1076 errno = 0;
1077 value = strtof(str, &endptr);
1078 if (errno != 0 || endptr == str || !isfinite(value)) {
1079 /* that wasn't a sensible number; go on */
1080 str++;
1081 } else {
1082 /* that was a number, so stop the string we were parsing, add
1083 it (unless it's empty), then add the number we just parsed */
1084 struct datum d;
1085
1086 if (str != string_start) {
1088 datum_vector_append(data, d);
1089 }
1090
1091 init_datum_number(&d, value);
1092 datum_vector_append(data, d);
1093
1094 /* finally, update the string position pointers */
1096 }
1097 }
1098
1099 /* if we have anything leftover then it's a string */
1100 if (str != string_start) {
1101 struct datum d;
1102
1104 datum_vector_append(data, d);
1105 }
1106}
1107
1108/********************************************************************/
1111static void free_data(struct datum_vector *data)
1112{
1113 int i;
1114
1115 for (i = 0; i < data->size; i++) {
1116 free_datum(&data->p[i]);
1117 }
1118 datum_vector_free(data);
1119}
1120
1121/********************************************************************/
1124int cityrepfield_compare(const char *str1, const char *str2)
1125{
1126 struct datum_vector data1, data2;
1127 int retval;
1128
1129 if (str1 == str2) {
1130 return 0;
1131 } else if (NULL == str1) {
1132 return 1;
1133 } else if (NULL == str2) {
1134 return -1;
1135 }
1136
1137 split_string(&data1, str1);
1138 split_string(&data2, str2);
1139
1140 retval = data_compare(&data1, &data2);
1141
1142 free_data(&data1);
1143 free_data(&data2);
1144
1145 return retval;
1146}
1147
1148/********************************************************************/
1152 const struct universal *target)
1153{
1154 return target->kind == VUT_IMPROVEMENT
1156}
#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:566
@ CITIZEN_ANGRY
Definition city.h:268
@ CITIZEN_HAPPY
Definition city.h:265
@ CITIZEN_CONTENT
Definition city.h:266
@ CITIZEN_UNHAPPY
Definition city.h:267
#define city_owner(_pcity_)
Definition city.h:560
@ FEELING_FINAL
Definition city.h:281
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:76
int city_history_gain(const struct city *pcity)
Definition culture.c:39
static void attack(QVariant data1, QVariant data2)
Definition dialogs.cpp:3034
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
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:78
#define SP_MAX
Definition fc_types.h:267
@ 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:61
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_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:317
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:142
struct unit::@84::@86 client
enum universals_n kind
Definition fc_types.h:608
universals_u value
Definition fc_types.h:607
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
#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:546
#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