Freeciv-3.2
Loading...
Searching...
No Matches
report.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 <stdio.h>
19#include <string.h>
20
21/* utility */
22#include "bitvector.h"
23#include "fciconv.h"
24#include "fcintl.h"
25#include "log.h"
26#include "mem.h"
27#include "rand.h"
28#include "support.h"
29
30/* common */
31#include "achievements.h"
32#include "calendar.h"
33#include "connection.h"
34#include "events.h"
35#include "game.h"
36#include "government.h"
37#include "nation.h"
38#include "packets.h"
39#include "player.h"
40#include "research.h"
41#include "specialist.h"
42#include "unitlist.h"
43#include "version.h"
44
45/* server */
46#include "citytools.h"
47#include "plrhand.h"
48#include "score.h"
49#include "srv_main.h"
50
51#include "report.h"
52
53
54/* data needed for logging civ score */
56 char *name;
57};
58
64
65/* Have to be initialized to value less than -1 so it doesn't seem like report was created at
66 * the end of previous turn in the beginning to turn 0. */
68
70
71static void plrdata_slot_init(struct plrdata_slot *plrdata,
72 const char *name);
73static void plrdata_slot_replace(struct plrdata_slot *plrdata,
74 const char *name);
75static void plrdata_slot_free(struct plrdata_slot *plrdata);
76
77static void page_conn_etype(struct conn_list *dest, const char *caption,
78 const char *headline, const char *lines,
79 enum event_type event);
80static void page_conn(struct conn_list *dest, const char *caption,
81 const char *headline, const char *lines);
82
89
90#define HISTORIAN_FIRST HISTORIAN_RICHEST
91#define HISTORIAN_LAST HISTORIAN_LARGEST
92
93static const char *historian_message[]={
94 /* TRANS: year <name> reports ... */
95 N_("%s %s reports on the RICHEST Civilizations in the World."),
96 /* TRANS: year <name> reports ... */
97 N_("%s %s reports on the most ADVANCED Civilizations in the World."),
98 /* TRANS: year <name> reports ... */
99 N_("%s %s reports on the most MILITARIZED Civilizations in the World."),
100 /* TRANS: year <name> reports ... */
101 N_("%s %s reports on the HAPPIEST Civilizations in the World."),
102 /* TRANS: year <name> reports ... */
103 N_("%s %s reports on the LARGEST Civilizations in the World.")
104};
105
106static const char *historian_name[]={
107 /* TRANS: [year] <name> [reports ...] */
108 N_("Herodotus"),
109 /* TRANS: [year] <name> [reports ...] */
110 N_("Thucydides"),
111 /* TRANS: [year] <name> [reports ...] */
112 N_("Pliny the Elder"),
113 /* TRANS: [year] <name> [reports ...] */
114 N_("Livy"),
115 /* TRANS: [year] <name> [reports ...] */
116 N_("Toynbee"),
117 /* TRANS: [year] <name> [reports ...] */
118 N_("Gibbon"),
119 /* TRANS: [year] <name> [reports ...] */
120 N_("Ssu-ma Ch'ien"),
121 /* TRANS: [year] <name> [reports ...] */
122 N_("Pan Ku")
123};
124
125/* With terminating '\0' */
126#define MAX_SCORELOG_LINE_LEN (119 + 1)
127
128static const char scorelog_magic[] = "#FREECIV SCORELOG2 ";
129
131 const struct player *player;
132 int value;
133};
134
136 struct city *city;
137 int value;
138};
139
140static int get_population(const struct player *pplayer);
141static int get_landarea(const struct player *pplayer);
142static int get_settledarea(const struct player *pplayer);
143static int get_research(const struct player *pplayer);
144static int get_production(const struct player *pplayer);
145static int get_economics(const struct player *pplayer);
146static int get_pollution(const struct player *pplayer);
147static int get_mil_service(const struct player *pplayer);
148static int get_culture(const struct player *pplayer);
149
150static const char *area_to_text(int value);
151static const char *percent_to_text(int value);
152static const char *production_to_text(int value);
153static const char *economics_to_text(int value);
154static const char *science_to_text(int value);
155static const char *mil_service_to_text(int value);
156static const char *pollution_to_text(int value);
157static const char *culture_to_text(int value);
158
159#define GOOD_PLAYER(p) ((p)->is_alive && !is_barbarian(p))
160
161/*
162 * Describes a row.
163 */
164static struct dem_row {
165 const char key;
166 const char *name;
167 int (*get_value) (const struct player *);
168 const char *(*to_text) (int);
170} rowtable[] = {
171 {'N', N_("Population"), get_population, population_to_text, TRUE },
172 {'A', N_("Land Area"), get_landarea, area_to_text, TRUE },
173 {'S', N_("Settled Area"), get_settledarea, area_to_text, TRUE },
174 {'R', N_("Research Speed"), get_research, science_to_text, TRUE },
175 /* TRANS: How literate people are. */
176 {'L', N_("?ability:Literacy"), get_literacy, percent_to_text, TRUE },
177 {'P', N_("Production"), get_production, production_to_text, TRUE },
178 {'E', N_("Economics"), get_economics, economics_to_text, TRUE },
179 {'M', N_("Military Service"), get_mil_service, mil_service_to_text, FALSE },
180 {'O', N_("?stats:Pollution"), get_pollution, pollution_to_text, FALSE },
181 {'C', N_("Culture"), get_culture, culture_to_text, TRUE }
183
184/* Demographics columns. */
192static struct dem_col {
193 char key;
194} coltable[] = {{'q'}, {'r'}, {'b'}}; /* Corresponds to dem_flag enum */
195
196/* prime number of entries makes for better scaling */
197static const char *ranking[] = {
198 /* TRANS: <#>: The <ranking> Poles */
199 N_("%2d: The Supreme %s"),
200 /* TRANS: <#>: The <ranking> Poles */
201 N_("%2d: The Magnificent %s"),
202 /* TRANS: <#>: The <ranking> Poles */
203 N_("%2d: The Great %s"),
204 /* TRANS: <#>: The <ranking> Poles */
205 N_("%2d: The Glorious %s"),
206 /* TRANS: <#>: The <ranking> Poles */
207 N_("%2d: The Excellent %s"),
208 /* TRANS: <#>: The <ranking> Poles */
209 N_("%2d: The Eminent %s"),
210 /* TRANS: <#>: The <ranking> Poles */
211 N_("%2d: The Distinguished %s"),
212 /* TRANS: <#>: The <ranking> Poles */
213 N_("%2d: The Average %s"),
214 /* TRANS: <#>: The <ranking> Poles */
215 N_("%2d: The Mediocre %s"),
216 /* TRANS: <#>: The <ranking> Poles */
217 N_("%2d: The Ordinary %s"),
218 /* TRANS: <#>: The <ranking> Poles */
219 N_("%2d: The Pathetic %s"),
220 /* TRANS: <#>: The <ranking> Poles */
221 N_("%2d: The Useless %s"),
222 /* TRANS: <#>: The <ranking> Poles */
223 N_("%2d: The Valueless %s"),
224 /* TRANS: <#>: The <ranking> Poles */
225 N_("%2d: The Worthless %s"),
226 /* TRANS: <#>: The <ranking> Poles */
227 N_("%2d: The Wretched %s"),
228};
229
230/**********************************************************************/
233static int secompare(const void *a, const void *b)
234{
235 return (((const struct player_score_entry *)b)->value -
236 ((const struct player_score_entry *)a)->value);
237}
238
239/**********************************************************************/
244{
245 int i, j = 0, rank = 0;
247
248 report->turn = game.info.turn;
249 players_iterate(pplayer) {
250 if (GOOD_PLAYER(pplayer)) {
251 switch (which_news) {
253 size[j].value = pplayer->economic.gold;
254 break;
256 size[j].value
257 = pplayer->score.techs + research_get(pplayer)->future_tech;
258 break;
260 size[j].value = pplayer->score.units;
261 break;
262 case HISTORIAN_HAPPIEST:
263 size[j].value =
264 (((pplayer->score.happy - pplayer->score.unhappy
265 - 2 * pplayer->score.angry) * 1000) /
266 (1 + total_player_citizens(pplayer)));
267 break;
269 size[j].value = total_player_citizens(pplayer);
270 break;
271 }
272 size[j].player = pplayer;
273 j++;
274 } /* else the player is dead or barbarian or observer */
276
277 qsort(size, j, sizeof(size[0]), secompare);
278 report->body[0] = '\0';
279 for (i = 0; i < j; i++) {
280 if (i > 0 && size[i].value < size[i - 1].value) {
281 /* since i < j, only top entry reigns Supreme */
282 rank = ((i * ARRAY_SIZE(ranking)) / j) + 1;
283 }
284 if (rank >= ARRAY_SIZE(ranking)) {
285 /* clamp to final entry */
286 rank = ARRAY_SIZE(ranking) - 1;
287 }
289 _(ranking[rank]),
290 i + 1,
292 fc_strlcat(report->body, "\n", REPORT_BODYSIZE);
293 }
297}
298
299/**********************************************************************/
303{
304 /* History report is actually constructed at the end of previous turn. */
306 page_conn_etype(dest, _("Historian Publishes!"),
309 }
310}
311
312/**********************************************************************/
315static int nr_wonders(struct city *pcity)
316{
317 int result = 0;
318
319 city_built_iterate(pcity, i) {
320 if (is_great_wonder(i)) {
321 result++;
322 }
324
325 return result;
326}
327
328/**********************************************************************/
331void report_top_cities(struct conn_list *dest)
332{
333 if (game.info.top_cities_count > 0) {
334 /* A wonder equals WONDER_FACTOR citizen */
335 const int WONDER_FACTOR = 5;
336 struct city_score_entry size[game.info.top_cities_count];
337 int i;
338 char header[256];
339 char buffer[4096];
340
341 for (i = 0; i < game.info.top_cities_count; i++) {
342 size[i].value = 0;
343 size[i].city = NULL;
344 }
345
346 shuffled_players_iterate(pplayer) {
347 city_list_iterate(pplayer->cities, pcity) {
348 int value_of_pcity = city_size_get(pcity)
349 + nr_wonders(pcity) * WONDER_FACTOR;
350
351 if (value_of_pcity > size[game.info.top_cities_count - 1].value) {
353 size[game.info.top_cities_count - 1].city = pcity;
355 }
358
359 buffer[0] = '\0';
360 for (i = 0; i < game.info.top_cities_count; i++) {
361 int wonders;
362
363 if (size[i].city == NULL) {
364 /*
365 * There are less than game.info.top_cities_count cities in
366 * the whole game.
367 */
368 break;
369 }
370
371 if (player_count() > team_count()) {
372 /* There exists a team with more than one member. */
373 char team_name[2 * MAX_LEN_NAME];
374
376 sizeof(team_name));
377 cat_snprintf(buffer, sizeof(buffer),
378 /* TRANS:"The French City of Lyon (team 3) of size 18". */
379 _("%2d: The %s City of %s (%s) of size %d, "), i + 1,
381 city_name_get(size[i].city), team_name,
383 } else {
384 cat_snprintf(buffer, sizeof(buffer),
385 _("%2d: The %s City of %s of size %d, "), i + 1,
388 }
389
390 wonders = nr_wonders(size[i].city);
391 if (wonders == 0) {
392 cat_snprintf(buffer, sizeof(buffer), _("with no Great Wonders\n"));
393 } else {
394 cat_snprintf(buffer, sizeof(buffer),
395 PL_("with %d Great Wonder\n", "with %d Great Wonders\n",
396 wonders),
397 wonders);
398 }
399 }
400
401 fc_snprintf(header, sizeof(header),
402 PL_("The %d Greatest City in the World!",
403 "The %d Greatest Cities in the World!",
406 page_conn(dest, _("Traveler's Report:"), header, buffer);
407 }
408}
409
410/**********************************************************************/
415{
416 char buffer[4096];
417 const char *separator = "\n";
418 struct strvec *wonderlist = strvec_new();
419
420 buffer[0] = '\0';
421
422 /* Sort by players and cities */
423 players_iterate(pplayer) {
424 city_list_iterate(pplayer->cities, pcity) {
425 int w = 0;
426
427 city_built_iterate(pcity, i) {
428 if (is_great_wonder(i)) {
429 w++;
430
431 if (player_count() > team_count()) {
432 /* There exists a team with more than one member. */
433 char team_name[2 * MAX_LEN_NAME];
434
435 team_pretty_name(city_owner(pcity)->team, team_name,
436 sizeof(team_name));
437 cat_snprintf(buffer, sizeof(buffer),
438 /* TRANS: "Colossus in Rhodes (Greek, team 2)". */
439 _("%s in %s (%s, %s)\n"),
441 city_name_get(pcity),
443 team_name);
444 } else {
445 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
447 city_name_get(pcity),
449 }
450 } /* endif is_great_wonder */
452
453 if (w != 0) {
454 cat_snprintf(buffer, sizeof(buffer), "\n");
455 }
458
459 cat_snprintf(buffer, sizeof(buffer), "----------------------------\n");
460
461 /* Find destroyed wonders */
463 if (is_great_wonder(imp)) {
465 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
467 }
468 }
470
471 /* Blank line */
472 cat_snprintf(buffer, sizeof(buffer), "----------------------------\n");
473
474 /* Copy buffer into list before "building %s in ...."
475 because all "building %s" would be sorted at the same letter b */
476
478
480 if (is_great_wonder(i)) {
481 players_iterate(pplayer) {
482 city_list_iterate(pplayer->cities, pcity) {
483 if (VUT_IMPROVEMENT == pcity->production.kind
484 && pcity->production.value.building == i) {
485 if (player_count() > team_count()) {
486 /* There exists a team with more than one member. */
487 char team_name[2 * MAX_LEN_NAME];
488
489 team_pretty_name(city_owner(pcity)->team, team_name,
490 sizeof(team_name));
491 cat_snprintf(buffer, sizeof(buffer),
492 /* TRANS: "([...] (Roman, team 4))". */
493 _("(building %s in %s (%s, %s))\n"),
495 _(nation_adjective_for_player(pplayer)), team_name);
496 } else {
497 cat_snprintf(buffer, sizeof(buffer),
498 _("(building %s in %s (%s))\n"),
501 }
502 }
505 }
507
508 /* Show again all wonders, sorted alphabetically */
509 /* The separator line will be the first one, no need to add another one */
512
514 cat_snprintf(buffer, sizeof(buffer), "%s\n", wonder);
516
517 page_conn(dest, _("Traveler's Report:"),
518 _("Wonders of the World"), buffer);
519}
520
521/**********************************************************************/
526{
527 char buffer[4096];
528
529 buffer[0] = '\0';
530
532 if (is_great_wonder(i)) {
533 struct city *pcity = city_from_great_wonder(i);
534
535 if (pcity) {
536 if (player_count() > team_count()) {
537 /* There exists a team with more than one member. */
538 char team_name[2 * MAX_LEN_NAME];
539
540 team_pretty_name(city_owner(pcity)->team, team_name,
541 sizeof(team_name));
542 cat_snprintf(buffer, sizeof(buffer),
543 /* TRANS: "Colossus in Rhodes (Greek, team 2)". */
544 _("%s in %s (%s, %s)\n"),
546 city_name_get(pcity),
548 team_name);
549 } else {
550 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
552 city_name_get(pcity),
554 }
555 } else if (great_wonder_is_destroyed(i)) {
556 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
558 }
559 }
561
563 if (is_great_wonder(i)) {
564 players_iterate(pplayer) {
565 city_list_iterate(pplayer->cities, pcity) {
566 if (VUT_IMPROVEMENT == pcity->production.kind
567 && pcity->production.value.building == i) {
568 if (player_count() > team_count()) {
569 /* There exists a team with more than one member. */
570 char team_name[2 * MAX_LEN_NAME];
571
572 team_pretty_name(city_owner(pcity)->team, team_name,
573 sizeof(team_name));
574 cat_snprintf(buffer, sizeof(buffer),
575 /* TRANS: "([...] (Roman, team 4))". */
576 _("(building %s in %s (%s, %s))\n"),
578 nation_adjective_for_player(pplayer), team_name);
579 } else {
580 cat_snprintf(buffer, sizeof(buffer),
581 _("(building %s in %s (%s))\n"),
584 }
585 }
588 }
590
591 page_conn(dest, _("Traveler's Report:"),
592 _("Wonders of the World"), buffer);
593}
594
595/**************************************************************************
596 Helper functions which return the value for the given player.
597**************************************************************************/
598
599/**********************************************************************/
602static int get_population(const struct player *pplayer)
603{
604 return pplayer->score.population;
605}
606
607/**********************************************************************/
610static int get_pop(const struct player *pplayer)
611{
612 return total_player_citizens(pplayer);
613}
614
615/**********************************************************************/
618static int get_real_pop(const struct player *pplayer)
619{
620 return 1000 * get_pop(pplayer);
621}
622
623/**********************************************************************/
626static int get_landarea(const struct player *pplayer)
627{
628 return pplayer->score.landarea;
629}
630
631/**********************************************************************/
634static int get_settledarea(const struct player *pplayer)
635{
636 return pplayer->score.settledarea;
637}
638
639/**********************************************************************/
642static int get_research(const struct player *pplayer)
643{
644 return pplayer->score.techout;
645}
646
647/**********************************************************************/
650static int get_production(const struct player *pplayer)
651{
652 return pplayer->score.mfg;
653}
654
655/**********************************************************************/
658static int get_economics(const struct player *pplayer)
659{
660 return pplayer->score.bnp;
661}
662
663/**********************************************************************/
666static int get_pollution(const struct player *pplayer)
667{
668 return pplayer->score.pollution;
669}
670
671/**********************************************************************/
674static int get_mil_service(const struct player *pplayer)
675{
676 return (pplayer->score.units * 5000) / (10 + pplayer->score.population);
677}
678
679/**********************************************************************/
682static int get_cities(const struct player *pplayer)
683{
684 return pplayer->score.cities;
685}
686
687/**********************************************************************/
690static int get_techs(const struct player *pplayer)
691{
692 return pplayer->score.techs;
693}
694
695/**********************************************************************/
698static int get_munits(const struct player *pplayer)
699{
700 int result = 0;
701
702 /* Count up military units */
703 unit_list_iterate(pplayer->units, punit) {
704 if (!is_special_unit(punit)) {
705 result++;
706 }
708
709 return result;
710}
711
712/**********************************************************************/
715static int get_settlers(const struct player *pplayer)
716{
717 int result = 0;
718
720 /* count up settlers */
721 unit_list_iterate(pplayer->units, punit) {
723 result++;
724 }
726 }
727
728 return result;
729}
730
731/**********************************************************************/
734static int get_wonders(const struct player *pplayer)
735{
736 return pplayer->score.wonders;
737}
738
739/**********************************************************************/
742static int get_techout(const struct player *pplayer)
743{
744 return pplayer->score.techout;
745}
746
747/**********************************************************************/
751static int get_literacy2(const struct player *pplayer)
752{
753 return pplayer->score.literacy;
754}
755
756/**********************************************************************/
759static int get_spaceship(const struct player *pplayer)
760{
761 return pplayer->score.spaceship;
762}
763
764/**********************************************************************/
767static int get_units_built(const struct player *pplayer)
768{
769 return pplayer->score.units_built;
770}
771
772/**********************************************************************/
775static int get_units_killed(const struct player *pplayer)
776{
777 return pplayer->score.units_killed;
778}
779
780/**********************************************************************/
783static int get_units_lost(const struct player *pplayer)
784{
785 return pplayer->score.units_lost;
786}
787
788/**********************************************************************/
791static int get_units_used(const struct player *pplayer)
792{
793 return pplayer->score.units_used;
794}
795
796/**********************************************************************/
799static int get_gold(const struct player *pplayer)
800{
801 return pplayer->economic.gold;
802}
803
804/**********************************************************************/
807static int get_taxrate(const struct player *pplayer)
808{
809 return pplayer->economic.tax;
810}
811
812/**********************************************************************/
815static int get_scirate(const struct player *pplayer)
816{
817 return pplayer->economic.science;
818}
819
820/**********************************************************************/
823static int get_luxrate(const struct player *pplayer)
824{
825 return pplayer->economic.luxury;
826}
827
828/**********************************************************************/
831static int get_riots(const struct player *pplayer)
832{
833 int result = 0;
834
835 city_list_iterate(pplayer->cities, pcity) {
836 if (pcity->anarchy > 0) {
837 result++;
838 }
840
841 return result;
842}
843
844/**********************************************************************/
847static int get_happypop(const struct player *pplayer)
848{
849 return pplayer->score.happy;
850}
851
852/**********************************************************************/
855static int get_contentpop(const struct player *pplayer)
856{
857 return pplayer->score.content;
858}
859
860/**********************************************************************/
863static int get_unhappypop(const struct player *pplayer)
864{
865 return pplayer->score.unhappy;
866}
867
868/**********************************************************************/
871static int get_specialists(const struct player *pplayer)
872{
873 int count = 0;
874
876 count += pplayer->score.specialists[sp];
878
879 return count;
880}
881
882/**********************************************************************/
885static int get_gov(const struct player *pplayer)
886{
887 return (int) government_number(government_of_player(pplayer));
888}
889
890/**********************************************************************/
893static int get_corruption(const struct player *pplayer)
894{
895 int result = 0;
896
897 city_list_iterate(pplayer->cities, pcity) {
898 result += pcity->waste[O_TRADE];
900
901 return result;
902}
903
904/**********************************************************************/
907static int get_total_score(const struct player *pplayer)
908{
909 return pplayer->score.game;
910}
911
912/**********************************************************************/
915static int get_culture(const struct player *pplayer)
916{
917 return pplayer->score.culture;
918}
919
920/**********************************************************************/
923static const char *value_units(int val, const char *uni)
924{
925 static char buf[64];
926
927 if (fc_snprintf(buf, sizeof(buf), "%s%s", int_to_text(val), uni) == -1) {
928 log_error("String truncated in value_units()!");
929 }
930
931 return buf;
932}
933
934/**********************************************************************/
938static const char *area_to_text(int value)
939{
940 /* TRANS: abbreviation of "square miles" */
941 return value_units(value, PL_(" sq. mi.", " sq. mi.", value));
942}
943
944/**********************************************************************/
948static const char *percent_to_text(int value)
949{
950 return value_units(value, "%");
951}
952
953/**********************************************************************/
957static const char *production_to_text(int value)
958{
959 int clip = MAX(0, value);
960 /* TRANS: "M tons" = million tons, so always plural */
961 return value_units(clip, PL_(" M tons", " M tons", clip));
962}
963
964/**********************************************************************/
968static const char *economics_to_text(int value)
969{
970 /* TRANS: "M goods" = million goods, so always plural */
971 return value_units(value, PL_(" M goods", " M goods", value));
972}
973
974/**********************************************************************/
978static const char *science_to_text(int value)
979{
980 return value_units(value, PL_(" bulb", " bulbs", value));
981}
982
983/**********************************************************************/
987static const char *mil_service_to_text(int value)
988{
989 return value_units(value, PL_(" month", " months", value));
990}
991
992/**********************************************************************/
996static const char *pollution_to_text(int value)
997{
998 return value_units(value, PL_(" ton", " tons", value));
999}
1000
1001/**********************************************************************/
1005static const char *culture_to_text(int value)
1006{
1007 /* TRANS: Unit(s) of culture */
1008 return value_units(value, PL_(" point", " points", value));
1009}
1010
1011/**********************************************************************/
1014static void dem_line_item(char *outptr, size_t out_size,
1015 struct player *pplayer, struct dem_row *prow,
1017{
1018 if (NULL != pplayer && BV_ISSET(selcols, DEM_COL_QUANTITY)) {
1019 const char *text = prow->to_text(prow->get_value(pplayer));
1020
1021 cat_snprintf(outptr, out_size, " %s", text);
1023 18 - (int) get_internal_string_length(text), "");
1024 }
1025
1026 if (NULL != pplayer && BV_ISSET(selcols, DEM_COL_RANK)) {
1027 int basis = prow->get_value(pplayer);
1028 int place = 1;
1029
1031 if (GOOD_PLAYER(other)
1032 && ((prow->greater_values_are_better
1033 && prow->get_value(other) > basis)
1034 || (!prow->greater_values_are_better
1035 && prow->get_value(other) < basis))) {
1036 place++;
1037 }
1039
1040 cat_snprintf(outptr, out_size, _("(ranked %d)"), place);
1041 }
1042
1043 if (NULL == pplayer || BV_ISSET(selcols, DEM_COL_BEST)) {
1044 struct player *best_player = pplayer;
1045 int best_value = NULL != pplayer ? prow->get_value(pplayer) : 0;
1046
1048 if (GOOD_PLAYER(other)) {
1049 int value = prow->get_value(other);
1050
1051 if (!best_player
1052 || (prow->greater_values_are_better && value > best_value)
1053 || (!prow->greater_values_are_better && value < best_value)) {
1055 best_value = value;
1056 }
1057 }
1059
1060 if (NULL == pplayer
1061 || (team_has_embassy(pplayer->team, best_player)
1062 && (pplayer != best_player))) {
1063 cat_snprintf(outptr, out_size, " %s: %s",
1065 prow->to_text(prow->get_value(best_player)));
1066 }
1067 }
1068}
1069
1070/**********************************************************************/
1078bool is_valid_demography(const char *demography, int *error)
1079{
1080 int len = strlen(demography), i;
1081
1082 /* We check each character individually to see if it's valid. This
1083 * does not check for duplicate entries. */
1084 for (i = 0; i < len; i++) {
1085 bool found = FALSE;
1086 int j;
1087
1088 /* See if the character is a valid column label. */
1089 for (j = 0; j < DEM_COL_LAST; j++) {
1090 if (demography[i] == coltable[j].key) {
1091 found = TRUE;
1092 break;
1093 }
1094 }
1095
1096 if (found) {
1097 continue;
1098 }
1099
1100 /* See if the character is a valid row label. */
1101 for (j = 0; j < ARRAY_SIZE(rowtable); j++) {
1102 if (demography[i] == rowtable[j].key) {
1103 found = TRUE;
1104 break;
1105 }
1106 }
1107
1108 if (!found) {
1109 if (error != NULL) {
1110 (*error) = i;
1111 }
1112 /* The character is invalid. */
1113 return FALSE;
1114 }
1115 }
1116
1117 /* Looks like all characters were valid. */
1118 return TRUE;
1119}
1120
1121/**********************************************************************/
1126{
1127 char civbuf[1024];
1128 char buffer[4096];
1129 int i;
1130 bool anyrows;
1132 int numcols = 0;
1133 struct player *pplayer = pconn->playing;
1134
1137 for (i = 0; i < DEM_COL_LAST; i++) {
1139 BV_SET(selcols, i);
1140 numcols++;
1141 }
1142 }
1143
1144 anyrows = FALSE;
1145 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1147 anyrows = TRUE;
1148 break;
1149 }
1150 }
1151
1152 if ((!pconn->observer && !pplayer)
1153 || (pplayer && !pplayer->is_alive)
1154 || !anyrows
1155 || numcols == 0) {
1156 page_conn(pconn->self, _("Demographics Report:"),
1157 _("Sorry, the Demographics report is unavailable."), "");
1158 return;
1159 }
1160
1161 if (pplayer) {
1162 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1165 calendar_text());
1166 } else {
1167 civbuf[0] = '\0';
1168 }
1169
1170 buffer[0] = '\0';
1171 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1173 const char *name = Q_(rowtable[i].name);
1174
1175 cat_snprintf(buffer, sizeof(buffer), "%s", name);
1176 cat_snprintf(buffer, sizeof(buffer), "%*s",
1177 18 - (int) get_internal_string_length(name), "");
1178 dem_line_item(buffer, sizeof(buffer), pplayer, &rowtable[i], selcols);
1179 sz_strlcat(buffer, "\n");
1180 }
1181 }
1182
1183 page_conn(pconn->self, _("Demographics Report:"), civbuf, buffer);
1184}
1185
1186/**********************************************************************/
1190{
1191 char civbuf[1024];
1192 char buffer[4096];
1193 struct player *pplayer = pconn->playing;
1194
1195 if (pplayer == NULL) {
1196 return;
1197 }
1198
1199 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1202 calendar_text());
1203
1204 buffer[0] = '\0';
1205
1207 if (achievement_player_has(pach, pplayer)) {
1208 cat_snprintf(buffer, sizeof(buffer), "%s\n",
1210 }
1212
1213 page_conn(pconn->self, _("Achievements List:"), civbuf, buffer);
1214}
1215
1216/**********************************************************************/
1219static void plrdata_slot_init(struct plrdata_slot *plrdata,
1220 const char *name)
1221{
1222 fc_assert_ret(plrdata->name == NULL);
1223
1224 plrdata->name = fc_calloc(MAX_LEN_NAME, sizeof(plrdata->name));
1225 plrdata_slot_replace(plrdata, name);
1226}
1227
1228/**********************************************************************/
1231static void plrdata_slot_replace(struct plrdata_slot *plrdata,
1232 const char *name)
1233{
1234 fc_assert_ret(plrdata->name != NULL);
1235
1236 fc_strlcpy(plrdata->name, name, MAX_LEN_NAME);
1237}
1238
1239/**********************************************************************/
1242static void plrdata_slot_free(struct plrdata_slot *plrdata)
1243{
1244 if (plrdata->name != NULL) {
1245 free(plrdata->name);
1246 plrdata->name = NULL;
1247 }
1248}
1249
1250/**********************************************************************/
1257static bool scan_score_log(char *id)
1258{
1259 int line_nr, turn, plr_no, spaces;
1260 struct plrdata_slot *plrdata;
1261 char line[MAX_SCORELOG_LINE_LEN], *ptr;
1262
1263 /* Must be big enough to contain any string there might be in "addplayer" line
1264 * to read.
1265 * Could have even sizeof("addplayer 0 0 ") - 1, but maintenance not worth
1266 * saving couple of bytes. */
1267 char plr_name[MAX(MAX_LEN_NAME, MAX_SCORELOG_LINE_LEN - (sizeof("addplayer ") - 1)) + 1];
1268
1271
1272 score_log->last_turn = -1;
1273 id[0] = '\0';
1274
1275 for (line_nr = 1;; line_nr++) {
1276 if (!fgets(line, sizeof(line), score_log->fp)) {
1277 if (feof(score_log->fp) != 0) {
1278 break;
1279 }
1280 log_error("[%s:-] Can't read scorelog file header!",
1282 return FALSE;
1283 }
1284
1285 ptr = strchr(line, '\n');
1286 if (!ptr) {
1287 log_error("[%s:%d] Line too long!", game.server.scorefile, line_nr);
1288 return FALSE;
1289 }
1290 *ptr = '\0';
1291
1292 if (line_nr == 1) {
1294 log_error("[%s:%d] Bad file magic!", game.server.scorefile, line_nr);
1295 return FALSE;
1296 }
1297 }
1298
1299 if (!fc_strncmp(line, "id ", strlen("id "))) {
1300 if (strlen(id) > 0) {
1301 log_error("[%s:%d] Multiple ID entries!", game.server.scorefile,
1302 line_nr);
1303 return FALSE;
1304 }
1306 if (strcmp(id, server.game_identifier) != 0) {
1307 log_error("[%s:%d] IDs don't match! game='%s' scorelog='%s'",
1308 game.server.scorefile, line_nr, server.game_identifier,
1309 id);
1310 return FALSE;
1311 }
1312 }
1313
1314 if (!fc_strncmp(line, "turn ", strlen("turn "))) {
1315 if (sscanf(line + strlen("turn "), "%d", &turn) != 1) {
1316 log_error("[%s:%d] Bad line (turn)!", game.server.scorefile,
1317 line_nr);
1318 return FALSE;
1319 }
1320
1322 score_log->last_turn = turn;
1323 }
1324
1325 if (!fc_strncmp(line, "addplayer ", strlen("addplayer "))) {
1326 /* If you change this, be sure to adjust plr_name buffer size to
1327 * match longest possible string read. */
1328 if (3 != sscanf(line + strlen("addplayer "), "%d %d %s",
1329 &turn, &plr_no, plr_name)) {
1330 log_error("[%s:%d] Bad line (addplayer)!",
1332 return FALSE;
1333 }
1334
1335 /* Now get the complete player name if there are several parts. */
1336 ptr = line + strlen("addplayer ");
1337 spaces = 0;
1338 while (*ptr != '\0' && spaces < 2) {
1339 if (*ptr == ' ') {
1340 spaces++;
1341 }
1342 ptr++;
1343 }
1344 fc_snprintf(plr_name, sizeof(plr_name), "%s", ptr);
1345 log_debug("add player '%s' (from line %d: '%s')", plr_name, line_nr,
1346 line);
1347
1348 if (0 > plr_no || plr_no >= player_slot_count()) {
1349 log_error("[%s:%d] Invalid player number: %d!",
1351 return FALSE;
1352 }
1353
1354 plrdata = score_log->plrdata + plr_no;
1355 if (plrdata->name != NULL) {
1356 log_error("[%s:%d] Two names for one player (id %d)!",
1358 return FALSE;
1359 }
1360
1361 plrdata_slot_init(plrdata, plr_name);
1362 }
1363
1364 if (!fc_strncmp(line, "delplayer ", strlen("delplayer "))) {
1365 if (2 != sscanf(line + strlen("delplayer "), "%d %d",
1366 &turn, &plr_no)) {
1367 log_error("[%s:%d] Bad line (delplayer)!",
1369 return FALSE;
1370 }
1371
1372 if (!(plr_no >= 0 && plr_no < player_slot_count())) {
1373 log_error("[%s:%d] Invalid player number: %d!",
1375 return FALSE;
1376 }
1377
1378 plrdata = score_log->plrdata + plr_no;
1379 if (plrdata->name == NULL) {
1380 log_error("[%s:%d] Trying to remove undefined player (id %d)!",
1382 return FALSE;
1383 }
1384
1385 plrdata_slot_free(plrdata);
1386 }
1387 }
1388
1389 if (score_log->last_turn == -1) {
1390 log_error("[%s:-] Scorelog contains no turn!", game.server.scorefile);
1391 return FALSE;
1392 }
1393
1394 if (strlen(id) == 0) {
1395 log_error("[%s:-] Scorelog contains no ID!", game.server.scorefile);
1396 return FALSE;
1397 }
1398
1399 if (score_log->last_turn + 1 != game.info.turn) {
1400 log_error("[%s:-] Scorelog doesn't match savegame!",
1402 return FALSE;
1403 }
1404
1405 return TRUE;
1406}
1407
1408/**********************************************************************/
1412{
1413 if (score_log != NULL) {
1414 return;
1415 }
1416
1417 score_log = fc_calloc(1, sizeof(*score_log));
1418 score_log->fp = NULL;
1419 score_log->last_turn = -1;
1421 sizeof(*score_log->plrdata));
1422 player_slots_iterate(pslot) {
1423 struct plrdata_slot *plrdata = score_log->plrdata
1424 + player_slot_index(pslot);
1425 plrdata->name = NULL;
1427
1429}
1430
1431/**********************************************************************/
1435{
1436 if (!score_log) {
1437 /* nothing to do */
1438 return;
1439 }
1440
1441 if (score_log->fp) {
1443 score_log->fp = NULL;
1444 }
1445
1446 if (score_log->plrdata) {
1447 player_slots_iterate(pslot) {
1448 struct plrdata_slot *plrdata = score_log->plrdata
1449 + player_slot_index(pslot);
1450 if (plrdata->name != NULL) {
1451 free(plrdata->name);
1452 }
1455 }
1456
1457 free(score_log);
1458 score_log = NULL;
1459}
1460
1461/**********************************************************************/
1465{
1467 char id[MAX_LEN_GAME_IDENTIFIER];
1468 int i = 0;
1469
1470 /* Add new tags only at end of this list. Maintaining the order of
1471 * old tags is critical. */
1472 static const struct {
1473 char *name;
1474 int (*get_value) (const struct player *);
1475 } score_tags[] = {
1476 {"pop", get_pop},
1477 {"bnp", get_economics},
1478 {"mfg", get_production},
1479 {"cities", get_cities},
1480 {"techs", get_techs},
1481 {"munits", get_munits},
1482 {"settlers", get_settlers}, /* "original" tags end here */
1483
1484 {"wonders", get_wonders},
1485 {"techout", get_techout},
1486 {"landarea", get_landarea},
1487 {"settledarea", get_settledarea},
1488 {"pollution", get_pollution},
1489 {"literacy", get_literacy2},
1490 {"spaceship", get_spaceship}, /* new 1.8.2 tags end here */
1491
1492 {"gold", get_gold},
1493 {"taxrate", get_taxrate},
1494 {"scirate", get_scirate},
1495 {"luxrate", get_luxrate},
1496 {"riots", get_riots},
1497 {"happypop", get_happypop},
1498 {"contentpop", get_contentpop},
1499 {"unhappypop", get_unhappypop},
1500 {"specialists", get_specialists},
1501 {"gov", get_gov},
1502 {"corruption", get_corruption}, /* new 1.11.5 tags end here */
1503
1504 {"score", get_total_score}, /* New 2.1.10 tag end here. */
1505
1506 {"unitsbuilt", get_units_built}, /* New tags since 2.3.0. */
1507 {"unitskilled", get_units_killed},
1508 {"unitslost", get_units_lost},
1509
1510 {"culture", get_culture}, /* New tag in 2.6.0. */
1511
1512 {"unitsused", get_units_used} /* New tag in 3.2.0. */
1513 };
1514
1515 if (!game.server.scorelog) {
1516 return;
1517 }
1518
1519 if (!score_log) {
1520 return;
1521 }
1522
1523 if (!score_log->fp) {
1525 oper = SL_CREATE;
1526 } else {
1528 if (!score_log->fp) {
1529 oper = SL_CREATE;
1530 } else {
1531 if (!scan_score_log(id)) {
1533 }
1534 oper = SL_APPEND;
1535
1537 score_log->fp = NULL;
1538 }
1539 }
1540
1541 switch (oper) {
1542 case SL_CREATE:
1544 if (!score_log->fp) {
1545 log_error("Can't open scorelog file '%s' for creation!",
1548 }
1551 "\n"
1552 "# For a specification of the format of this see doc/README.scorelog or \n"
1553 "# <https://raw.githubusercontent.com/freeciv/freeciv/S3_2/doc/README.scorelog>.\n"
1554 "\n");
1555
1556 fprintf(score_log->fp, "id %s\n", server.game_identifier);
1557 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1558 fprintf(score_log->fp, "tag %d %s\n", i, score_tags[i].name);
1559 }
1560 break;
1561 case SL_APPEND:
1563 if (!score_log->fp) {
1564 log_error("Can't open scorelog file '%s' for appending!",
1567 }
1568 break;
1569 default:
1570 log_error("[%s] bad operation %d", __FUNCTION__, (int) oper);
1572 }
1573 }
1574
1575 if (game.info.turn > score_log->last_turn) {
1576 fprintf(score_log->fp, "turn %d %d %s\n", game.info.turn, game.info.year,
1577 calendar_text());
1579 }
1580
1581 player_slots_iterate(pslot) {
1582 struct plrdata_slot *plrdata = score_log->plrdata
1583 + player_slot_index(pslot);
1584 if (plrdata->name != NULL
1585 && player_slot_is_used(pslot)) {
1586 struct player *pplayer = player_slot_get_player(pslot);
1587
1588 if (!GOOD_PLAYER(pplayer)) {
1589 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1590 player_number(pplayer));
1591 plrdata_slot_free(plrdata);
1592 }
1593 }
1595
1596 players_iterate(pplayer) {
1597 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1598
1599 if (plrdata->name == NULL && GOOD_PLAYER(pplayer)) {
1600 switch (game.server.scoreloglevel) {
1601 case SL_HUMANS:
1602 if (is_ai(pplayer)) {
1603 break;
1604 }
1605
1606 fc__fallthrough; /* No break - continue to actual implementation
1607 * in SL_ALL case if reached here */
1608 case SL_ALL:
1609 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1610 player_number(pplayer), player_name(pplayer));
1611 plrdata_slot_init(plrdata, player_name(pplayer));
1612 }
1613 }
1615
1616 players_iterate(pplayer) {
1617 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1618
1619 if (GOOD_PLAYER(pplayer)) {
1620 switch (game.server.scoreloglevel) {
1621 case SL_HUMANS:
1622 if (is_ai(pplayer) && plrdata->name == NULL) {
1623 /* If a human player toggled into AI mode, don't break. */
1624 break;
1625 }
1626
1627 fc__fallthrough; /* No break - continue to actual implementation
1628 * in SL_ALL case if reached here */
1629 case SL_ALL:
1630 if (strcmp(plrdata->name, player_name(pplayer)) != 0) {
1631 log_debug("player names does not match '%s' != '%s'", plrdata->name,
1632 player_name(pplayer));
1633 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1634 player_number(pplayer));
1635 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1636 player_number(pplayer), player_name(pplayer));
1637 plrdata_slot_replace(plrdata, player_name(pplayer));
1638 }
1639 }
1640 }
1642
1643 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1644 players_iterate(pplayer) {
1645 if (!GOOD_PLAYER(pplayer)
1646 || (game.server.scoreloglevel == SL_HUMANS && is_ai(pplayer))) {
1647 continue;
1648 }
1649
1650 fprintf(score_log->fp, "data %d %d %d %d\n", game.info.turn, i,
1651 player_number(pplayer), score_tags[i].get_value(pplayer));
1653 }
1654
1656
1657 return;
1658
1660
1662}
1663
1664/**********************************************************************/
1668{
1669 if (player_count() == 1) {
1670 return;
1671 }
1672
1674 return;
1675 }
1676
1679
1681 % (HISTORIAN_LAST + 1));
1683}
1684
1685/**********************************************************************/
1690{
1691 static const struct {
1692 const char *name;
1693 int (*score) (const struct player *);
1694 } score_categories[] = {
1695 { N_("Population\n"), get_real_pop },
1696 /* TRANS: "M goods" = million goods */
1697 { N_("Trade\n(M goods)"), get_economics },
1698 /* TRANS: "M tons" = million tons */
1699 { N_("Production\n(M tons)"), get_production },
1700 { N_("Cities\n"), get_cities },
1701 { N_("Technologies\n"), get_techs },
1702 { N_("Military Service\n(months)"), get_mil_service },
1703 { N_("Wonders\n"), get_wonders },
1704 { N_("Research Speed\n(bulbs)"), get_research },
1705 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1706 { N_("Land Area\n(sq. mi.)"), get_landarea },
1707 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1708 { N_("Settled Area\n(sq. mi.)"), get_settledarea },
1709 { N_("Literacy\n(%)"), get_literacy },
1710 { N_("Culture\n"), get_culture },
1711 { N_("Spaceship\n"), get_spaceship },
1712 { N_("Built Units\n"), get_units_built },
1713 { N_("Killed Units\n"), get_units_killed },
1714 { N_("Unit Losses\n"), get_units_lost },
1715 { N_("Units Used\n"), get_units_used },
1716 };
1718
1719 int i, j;
1721 struct packet_endgame_report packet;
1722
1724
1725 if (!dest) {
1726 dest = game.est_connections;
1727 }
1728
1730 for (j = 0; j < score_categories_num; j++) {
1731 sz_strlcpy(packet.category_name[j], score_categories[j].name);
1732 }
1733
1734 i = 0;
1735 players_iterate(pplayer) {
1736 if (!is_barbarian(pplayer)) {
1737 size[i].value = pplayer->score.game;
1738 size[i].player = pplayer;
1739 i++;
1740 }
1742
1743 qsort(size, i, sizeof(size[0]), secompare);
1744
1745 packet.player_num = i;
1746
1747 lsend_packet_endgame_report(dest, &packet);
1748
1749 for (i = 0; i < packet.player_num; i++) {
1751 const struct player *pplayer = size[i].player;
1752
1753 ppacket.category_num = score_categories_num;
1754 ppacket.player_id = player_number(pplayer);
1755 ppacket.score = size[i].value;
1756 for (j = 0; j < score_categories_num; j++) {
1757 ppacket.category_score[j] = score_categories[j].score(pplayer);
1758 }
1759
1760 ppacket.winner = pplayer->is_winner;
1761
1763 }
1764}
1765
1766/**********************************************************************/
1769static void page_conn(struct conn_list *dest, const char *caption,
1770 const char *headline, const char *lines)
1771{
1773}
1774
1775/**********************************************************************/
1786static void page_conn_etype(struct conn_list *dest, const char *caption,
1787 const char *headline, const char *lines,
1788 enum event_type event)
1789{
1790 struct packet_page_msg packet;
1791 int i;
1792 int len;
1793
1794 sz_strlcpy(packet.caption, caption);
1795 sz_strlcpy(packet.headline, headline);
1796 packet.event = event;
1797 len = strlen(lines);
1798 if ((len % (MAX_LEN_CONTENT - 1)) == 0) {
1799 packet.parts = len / (MAX_LEN_CONTENT - 1);
1800 } else {
1801 packet.parts = len / (MAX_LEN_CONTENT - 1) + 1;
1802 }
1803 packet.len = len;
1804
1805 lsend_packet_page_msg(dest, &packet);
1806
1807 for (i = 0; i < packet.parts; i++) {
1809 int plen;
1810
1811 plen = MIN(len, (MAX_LEN_CONTENT - 1));
1812 strncpy(part.lines, &(lines[(MAX_LEN_CONTENT - 1) * i]), plen);
1813 part.lines[plen] = '\0';
1814
1816
1817 len -= plen;
1818 }
1819}
1820
1821/**********************************************************************/
1825{
1826 return &latest_history_report;
1827}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
int get_literacy(const struct player *pplayer)
const char * achievement_name_translation(struct achievement *pach)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
#define BV_DEFINE(name, bits)
Definition bitvector.h:132
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
const char * calendar_text(void)
Definition calendar.c:141
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:663
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
#define city_list_iterate(citylist, pcity)
Definition city.h:508
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
#define city_list_iterate_end
Definition city.h:510
#define city_built_iterate(_pcity, _p)
Definition city.h:834
#define city_built_iterate_end
Definition city.h:840
char * incite_cost
Definition comments.c:75
#define MAX_LEN_CONTENT
Definition conn_types.h:32
const char * caption
Definition dialogs_g.h:37
const char const char * headline
Definition dialogs_g.h:38
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
enum event_type event
Definition events.c:81
#define MAX_LEN_GAME_IDENTIFIER
Definition fc_types.h:71
#define MAX_LEN_NAME
Definition fc_types.h:66
@ O_TRADE
Definition fc_types.h:101
size_t get_internal_string_length(const char *text)
Definition fciconv.c:395
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
const char * population_to_text(int thousand_citizen)
Definition game.c:734
struct civ_game game
Definition game.c:62
#define GAME_DEFAULT_SCORETURN
Definition game.h:582
@ SL_HUMANS
Definition game.h:69
@ SL_ALL
Definition game.h:68
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
const char * government_name_for_player(const struct player *pplayer)
Definition government.c:154
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
struct city * city_from_great_wonder(const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#define fc_calloc(n, esz)
Definition mem.h:38
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
void lsend_packet_endgame_player(struct conn_list *dest, const struct packet_endgame_player *packet)
void lsend_packet_endgame_report(struct conn_list *dest, const struct packet_endgame_report *packet)
void lsend_packet_page_msg(struct conn_list *dest, const struct packet_page_msg *packet)
void lsend_packet_page_msg_part(struct conn_list *dest, const struct packet_page_msg_part *packet)
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
int player_count(void)
Definition player.c:817
int player_slot_count(void)
Definition player.c:418
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:220
int player_index(const struct player *pplayer)
Definition player.c:829
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define player_slots_iterate(_pslot)
Definition player.h:523
#define is_ai(plr)
Definition player.h:230
#define player_slots_iterate_end
Definition player.h:527
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
#define fc_rand(_size)
Definition rand.h:56
static int get_units_killed(const struct player *pplayer)
Definition report.c:775
static int get_units_built(const struct player *pplayer)
Definition report.c:767
static int get_contentpop(const struct player *pplayer)
Definition report.c:855
static struct logging_civ_score * score_log
Definition report.c:69
static int nr_wonders(struct city *pcity)
Definition report.c:315
static const char * ranking[]
Definition report.c:197
void report_final_scores(struct conn_list *dest)
Definition report.c:1689
static const char * economics_to_text(int value)
Definition report.c:968
static const char * production_to_text(int value)
Definition report.c:957
static int get_munits(const struct player *pplayer)
Definition report.c:698
static const char * science_to_text(int value)
Definition report.c:978
static int get_pollution(const struct player *pplayer)
Definition report.c:666
#define HISTORIAN_LAST
Definition report.c:91
static int get_economics(const struct player *pplayer)
Definition report.c:658
static int get_techs(const struct player *pplayer)
Definition report.c:690
static void plrdata_slot_init(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1219
static void page_conn_etype(struct conn_list *dest, const char *caption, const char *headline, const char *lines, enum event_type event)
Definition report.c:1786
static int get_pop(const struct player *pplayer)
Definition report.c:610
static int get_riots(const struct player *pplayer)
Definition report.c:831
static void historian_generic(struct history_report *report, enum historian_type which_news)
Definition report.c:242
static const char * pollution_to_text(int value)
Definition report.c:996
static void plrdata_slot_replace(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1231
static int get_production(const struct player *pplayer)
Definition report.c:650
struct history_report latest_history_report
Definition report.c:67
static bool scan_score_log(char *id)
Definition report.c:1257
static int get_scirate(const struct player *pplayer)
Definition report.c:815
static int get_taxrate(const struct player *pplayer)
Definition report.c:807
void send_current_history_report(struct conn_list *dest)
Definition report.c:302
static int get_spaceship(const struct player *pplayer)
Definition report.c:759
void report_wonders_of_the_world(struct conn_list *dest)
Definition report.c:525
dem_flag
Definition report.c:185
@ DEM_COL_BEST
Definition report.c:188
@ DEM_COL_RANK
Definition report.c:187
@ DEM_COL_QUANTITY
Definition report.c:186
@ DEM_COL_LAST
Definition report.c:189
historian_type
Definition report.c:83
@ HISTORIAN_LARGEST
Definition report.c:88
@ HISTORIAN_MILITARY
Definition report.c:86
@ HISTORIAN_ADVANCED
Definition report.c:85
@ HISTORIAN_RICHEST
Definition report.c:84
@ HISTORIAN_HAPPIEST
Definition report.c:87
void report_demographics(struct connection *pconn)
Definition report.c:1125
static const char * historian_message[]
Definition report.c:93
static int get_corruption(const struct player *pplayer)
Definition report.c:893
static int get_wonders(const struct player *pplayer)
Definition report.c:734
void report_wonders_of_the_world_long(struct conn_list *dest)
Definition report.c:414
static int get_landarea(const struct player *pplayer)
Definition report.c:626
static int get_total_score(const struct player *pplayer)
Definition report.c:907
static const char * area_to_text(int value)
Definition report.c:938
static const char scorelog_magic[]
Definition report.c:128
static int get_population(const struct player *pplayer)
Definition report.c:602
static struct dem_col coltable[]
static int get_units_used(const struct player *pplayer)
Definition report.c:791
static const char * historian_name[]
Definition report.c:106
#define GOOD_PLAYER(p)
Definition report.c:159
struct history_report * history_report_get(void)
Definition report.c:1824
void make_history_report(void)
Definition report.c:1667
void log_civ_score_free(void)
Definition report.c:1434
static int get_culture(const struct player *pplayer)
Definition report.c:915
static const char * value_units(int val, const char *uni)
Definition report.c:923
static int get_techout(const struct player *pplayer)
Definition report.c:742
static int get_specialists(const struct player *pplayer)
Definition report.c:871
static struct dem_row rowtable[]
static int get_unhappypop(const struct player *pplayer)
Definition report.c:863
bool is_valid_demography(const char *demography, int *error)
Definition report.c:1078
void report_top_cities(struct conn_list *dest)
Definition report.c:331
static int get_settledarea(const struct player *pplayer)
Definition report.c:634
void log_civ_score_init(void)
Definition report.c:1411
static int get_literacy2(const struct player *pplayer)
Definition report.c:751
static void dem_line_item(char *outptr, size_t out_size, struct player *pplayer, struct dem_row *prow, bv_cols selcols)
Definition report.c:1014
static const char * culture_to_text(int value)
Definition report.c:1005
static int get_mil_service(const struct player *pplayer)
Definition report.c:674
void report_achievements(struct connection *pconn)
Definition report.c:1189
static const char * percent_to_text(int value)
Definition report.c:948
static int secompare(const void *a, const void *b)
Definition report.c:233
static int get_happypop(const struct player *pplayer)
Definition report.c:847
static void plrdata_slot_free(struct plrdata_slot *plrdata)
Definition report.c:1242
static void page_conn(struct conn_list *dest, const char *caption, const char *headline, const char *lines)
Definition report.c:1769
static int get_settlers(const struct player *pplayer)
Definition report.c:715
static int get_real_pop(const struct player *pplayer)
Definition report.c:618
static int get_luxrate(const struct player *pplayer)
Definition report.c:823
void log_civ_score_now(void)
Definition report.c:1464
static int get_units_lost(const struct player *pplayer)
Definition report.c:783
static int get_gold(const struct player *pplayer)
Definition report.c:799
#define MAX_SCORELOG_LINE_LEN
Definition report.c:126
static int get_cities(const struct player *pplayer)
Definition report.c:682
static const char * mil_service_to_text(int value)
Definition report.c:987
static int get_gov(const struct player *pplayer)
Definition report.c:885
static int get_research(const struct player *pplayer)
Definition report.c:642
#define REPORT_BODYSIZE
Definition report.h:23
#define REPORT_TITLESIZE
Definition report.h:22
struct research * research_get(const struct player *pplayer)
Definition research.c:128
int total_player_citizens(const struct player *pplayer)
Definition score.c:382
int compare_strings_strvec(const char *const *first, const char *const *second)
Definition shared.c:379
const char * int_to_text(unsigned int number)
Definition shared.c:234
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
#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
void strvec_sort(struct strvec *psv, int(*sort_func)(const char *const *, const char *const *))
void strvec_from_str(struct strvec *psv, char separator, const char *str)
struct strvec * strvec_new(void)
void strvec_remove_duplicate(struct strvec *psv, int(*cmp_func)(const char *, const char *))
#define strvec_iterate(psv, str)
#define strvec_iterate_end
Definition report.c:135
int value
Definition report.c:137
struct city * city
Definition report.c:136
Definition city.h:320
char scorefile[MAX_LEN_PATH]
Definition game.h:228
char demography[MAX_LEN_DEMOGRAPHY]
Definition game.h:243
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
enum scorelog_level scoreloglevel
Definition game.h:227
int start_year
Definition game.h:195
int scoreturn
Definition game.h:229
struct packet_scenario_info scenario
Definition game.h:87
struct civ_game::@31::@35 server
bool scorelog
Definition game.h:226
char key
Definition report.c:193
const char * name
Definition report.c:166
int(* get_value)(const struct player *)
Definition report.c:167
const char key
Definition report.c:165
bool greater_values_are_better
Definition report.c:169
char title[REPORT_TITLESIZE]
Definition report.h:28
char body[REPORT_BODYSIZE]
Definition report.h:29
struct plrdata_slot * plrdata
Definition report.c:62
char category_name[32][MAX_LEN_NAME]
Definition packets_gen.h:85
enum event_type event
char headline[MAX_LEN_MSG]
char caption[MAX_LEN_MSG]
Definition goto.c:52
Definition report.c:130
const struct player * player
Definition report.c:131
int value
Definition report.c:132
int units_killed
Definition player.h:103
int landarea
Definition player.h:92
int population
Definition player.h:94
int pollution
Definition player.h:97
int wonders
Definition player.h:89
int settledarea
Definition player.h:93
int units_used
Definition player.h:106
int specialists[SP_MAX]
Definition player.h:88
int units_lost
Definition player.h:104
int techout
Definition player.h:91
int units
Definition player.h:96
int units_built
Definition player.h:102
int content
Definition player.h:85
int happy
Definition player.h:84
int spaceship
Definition player.h:101
int culture
Definition player.h:107
int unhappy
Definition player.h:86
int cities
Definition player.h:95
int literacy
Definition player.h:98
int techs
Definition player.h:90
struct city_list * cities
Definition player.h:279
bool is_winner
Definition player.h:267
struct team * team
Definition player.h:259
struct unit_list * units
Definition player.h:280
bool is_alive
Definition player.h:266
struct player_economic economic
Definition player.h:282
struct player_score score
Definition player.h:281
char * name
Definition report.c:56
int future_tech
Definition research.h:42
Definition team.c:40
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:507
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
#define fc__fallthrough
Definition support.h:119
int team_count(void)
Definition team.c:375
int team_pretty_name(const struct team *pteam, char *buf, size_t buf_len)
Definition team.c:432
static int best_value(const void *a, const void *b)
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:359
bool is_special_unit(const struct unit *punit)
Definition unit.c:350
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33