Freeciv-3.3
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 "culture.h"
35#include "events.h"
36#include "game.h"
37#include "government.h"
38#include "nation.h"
39#include "packets.h"
40#include "player.h"
41#include "research.h"
42#include "specialist.h"
43#include "unitlist.h"
44#include "version.h"
45
46/* server */
47#include "citytools.h"
48#include "plrhand.h"
49#include "score.h"
50#include "srv_main.h"
51
52#include "report.h"
53
54
55/* data needed for logging civ score */
57 char *name;
58};
59
65
66/* Have to be initialized to value less than -1 so it doesn't seem like report was created at
67 * the end of previous turn in the beginning to turn 0. */
69
70static struct logging_civ_score *score_log = nullptr;
71
72static void plrdata_slot_init(struct plrdata_slot *plrdata,
73 const char *name);
74static void plrdata_slot_replace(struct plrdata_slot *plrdata,
75 const char *name);
76static void plrdata_slot_free(struct plrdata_slot *plrdata);
77
78static void page_conn_etype(struct conn_list *dest, const char *caption,
79 const char *headline, const char *lines,
80 enum event_type event);
81static void page_conn(struct conn_list *dest, const char *caption,
82 const char *headline, const char *lines);
83
91
92#define HISTORIAN_FIRST HISTORIAN_RICHEST
93#define HISTORIAN_LAST HISTORIAN_CULTURAL
94
95static const char *historian_message[] = {
96 /* TRANS: year <name> reports ... */
97 N_("%s %s reports on the RICHEST Civilizations in the World."),
98 /* TRANS: year <name> reports ... */
99 N_("%s %s reports on the most ADVANCED Civilizations in the World."),
100 /* TRANS: year <name> reports ... */
101 N_("%s %s reports on the most MILITARIZED Civilizations in the World."),
102 /* TRANS: year <name> reports ... */
103 N_("%s %s reports on the HAPPIEST Civilizations in the World."),
104 /* TRANS: year <name> reports ... */
105 N_("%s %s reports on the LARGEST Civilizations in the World."),
106 /* TRANS: year <name> reports ... */
107 N_("%s %s reports on the MOST CULTURAL Civilizations in the World.")
108};
109
110static const char *historian_name[] = {
111 /* TRANS: [year] <name> [reports ...] */
112 N_("Herodotus"),
113 /* TRANS: [year] <name> [reports ...] */
114 N_("Thucydides"),
115 /* TRANS: [year] <name> [reports ...] */
116 N_("Pliny the Elder"),
117 /* TRANS: [year] <name> [reports ...] */
118 N_("Livy"),
119 /* TRANS: [year] <name> [reports ...] */
120 N_("Toynbee"),
121 /* TRANS: [year] <name> [reports ...] */
122 N_("Gibbon"),
123 /* TRANS: [year] <name> [reports ...] */
124 N_("Ssu-ma Ch'ien"),
125 /* TRANS: [year] <name> [reports ...] */
126 N_("Pan Ku")
127};
128
129/* With terminating '\0' */
130#define MAX_SCORELOG_LINE_LEN (119 + 1)
131
132static const char scorelog_magic[] = "#FREECIV SCORELOG2 ";
133
135 const struct player *player;
136 int value;
137};
138
140 struct city *city;
141 int value;
142};
143
144static int get_population(const struct player *pplayer);
145static int get_landarea(const struct player *pplayer);
146static int get_settledarea(const struct player *pplayer);
147static int get_research(const struct player *pplayer);
148static int get_production(const struct player *pplayer);
149static int get_economics(const struct player *pplayer);
150static int get_pollution(const struct player *pplayer);
151static int get_mil_service(const struct player *pplayer);
152static int get_culture(const struct player *pplayer);
153
154static int get_pop(const struct player *pplayer);
155static int get_cities(const struct player *pplayer);
156static int get_techs(const struct player *pplayer);
157static int get_munits(const struct player *pplayer);
158static int get_settlers(const struct player *pplayer);
159static int get_wonders(const struct player *pplayer);
160static int get_techout(const struct player *pplayer);
161static int get_literacy2(const struct player *pplayer);
162static int get_spaceship(const struct player *pplayer);
163static int get_gold(const struct player *pplayer);
164static int get_taxrate(const struct player *pplayer);
165static int get_scirate(const struct player *pplayer);
166static int get_luxrate(const struct player *pplayer);
167static int get_riots(const struct player *pplayer);
168static int get_happypop(const struct player *pplayer);
169static int get_contentpop(const struct player *pplayer);
170static int get_unhappypop(const struct player *pplayer);
171static int get_specialists(const struct player *pplayer);
172static int get_gov(const struct player *pplayer);
173static int get_corruption(const struct player *pplayer);
174static int get_total_score(const struct player *pplayer);
175static int get_units_built(const struct player *pplayer);
176static int get_units_killed(const struct player *pplayer);
177static int get_units_lost(const struct player *pplayer);
178static int get_units_used(const struct player *pplayer);
179
180static const char *area_to_text(int value);
181static const char *percent_to_text(int value);
182static const char *production_to_text(int value);
183static const char *economics_to_text(int value);
184static const char *science_to_text(int value);
185static const char *mil_service_to_text(int value);
186static const char *pollution_to_text(int value);
187static const char *culture_to_text(int value);
188
189/* Add new tags only at end of this list. Maintaining the order of
190 * old tags is critical. */
191static const struct {
192 char *name;
193 int (*get_value) (const struct player *);
194} score_tags[] = {
195 {"pop", get_pop},
196 {"bnp", get_economics},
197 {"mfg", get_production},
198 {"cities", get_cities},
199 {"techs", get_techs},
200 {"munits", get_munits},
201 {"settlers", get_settlers}, /* "original" tags end here */
202
203 {"wonders", get_wonders},
204 {"techout", get_techout},
205 {"landarea", get_landarea},
206 {"settledarea", get_settledarea},
207 {"pollution", get_pollution},
208 {"literacy", get_literacy2},
209 {"spaceship", get_spaceship}, /* new 1.8.2 tags end here */
210
211 {"gold", get_gold},
212 {"taxrate", get_taxrate},
213 {"scirate", get_scirate},
214 {"luxrate", get_luxrate},
215 {"riots", get_riots},
216 {"happypop", get_happypop},
217 {"contentpop", get_contentpop},
218 {"unhappypop", get_unhappypop},
219 {"specialists", get_specialists},
220 {"gov", get_gov},
221 {"corruption", get_corruption}, /* new 1.11.5 tags end here */
222
223 {"score", get_total_score}, /* New 2.1.10 tag end here. */
224
225 {"unitsbuilt", get_units_built}, /* New tags since 2.3.0. */
226 {"unitskilled", get_units_killed},
227 {"unitslost", get_units_lost},
228
229 {"culture", get_culture}, /* New tag in 2.6.0. */
230
231 {"unitsused", get_units_used} /* New tag in 3.2.0. */
233
234#define GOOD_PLAYER(p) ((p)->is_alive && !is_barbarian(p))
235
236/*
237 * Describes a row.
238 */
239static struct dem_row {
240 const char key;
241 const char *name;
242 int (*get_value) (const struct player *);
243 const char *(*to_text) (int);
245} rowtable[] = {
246 {'N', N_("Population"), get_population, population_to_text, TRUE },
247 {'A', N_("Land Area"), get_landarea, area_to_text, TRUE },
248 {'S', N_("Settled Area"), get_settledarea, area_to_text, TRUE },
249 {'R', N_("Research Speed"), get_research, science_to_text, TRUE },
250 /* TRANS: How literate people are. */
251 {'L', N_("?ability:Literacy"), get_literacy, percent_to_text, TRUE },
252 {'P', N_("Production"), get_production, production_to_text, TRUE },
253 {'E', N_("Economics"), get_economics, economics_to_text, TRUE },
254 {'M', N_("Military Service"), get_mil_service, mil_service_to_text, FALSE },
255 {'O', N_("?stats:Pollution"), get_pollution, pollution_to_text, FALSE },
256 {'C', N_("Culture"), get_culture, culture_to_text, TRUE }
258
259/* Demographics columns. */
267static struct dem_col {
268 char key;
269} coltable[] = {{'q'}, {'r'}, {'b'}}; /* Corresponds to dem_flag enum */
270
271/* Prime number of entries makes for better scaling */
272static const char *ranking[] = {
273 /* TRANS: <#>: The <ranking> Poles */
274 N_("%2d: The Supreme %s"),
275 /* TRANS: <#>: The <ranking> Poles */
276 N_("%2d: The Magnificent %s"),
277 /* TRANS: <#>: The <ranking> Poles */
278 N_("%2d: The Great %s"),
279 /* TRANS: <#>: The <ranking> Poles */
280 N_("%2d: The Glorious %s"),
281 /* TRANS: <#>: The <ranking> Poles */
282 N_("%2d: The Excellent %s"),
283 /* TRANS: <#>: The <ranking> Poles */
284 N_("%2d: The Eminent %s"),
285 /* TRANS: <#>: The <ranking> Poles */
286 N_("%2d: The Distinguished %s"),
287 /* TRANS: <#>: The <ranking> Poles */
288 N_("%2d: The Average %s"),
289 /* TRANS: <#>: The <ranking> Poles */
290 N_("%2d: The Mediocre %s"),
291 /* TRANS: <#>: The <ranking> Poles */
292 N_("%2d: The Ordinary %s"),
293 /* TRANS: <#>: The <ranking> Poles */
294 N_("%2d: The Pathetic %s"),
295 /* TRANS: <#>: The <ranking> Poles */
296 N_("%2d: The Useless %s"),
297 /* TRANS: <#>: The <ranking> Poles */
298 N_("%2d: The Valueless %s"),
299 /* TRANS: <#>: The <ranking> Poles */
300 N_("%2d: The Worthless %s"),
301 /* TRANS: <#>: The <ranking> Poles */
302 N_("%2d: The Wretched %s"),
303};
304
305/**********************************************************************/
308static int secompare(const void *a, const void *b)
309{
310 return (((const struct player_score_entry *)b)->value -
311 ((const struct player_score_entry *)a)->value);
312}
313
314/**********************************************************************/
319{
320 int i, j = 0, rank = 0;
322
323 report->turn = game.info.turn;
324 players_iterate(pplayer) {
325 if (GOOD_PLAYER(pplayer)) {
326 switch (which_news) {
328 size[j].value = pplayer->economic.gold;
329 break;
331 size[j].value
332 = pplayer->score.techs + research_get(pplayer)->future_tech;
333 break;
335 size[j].value = pplayer->score.units;
336 break;
338 size[j].value
339 = (((pplayer->score.happy - pplayer->score.unhappy
340 - 2 * pplayer->score.angry) * 1000) /
341 (1 + total_player_citizens(pplayer)));
342 break;
344 size[j].value = total_player_citizens(pplayer);
345 break;
347 size[j].value = player_culture(pplayer) /
348 (1 + city_list_size(pplayer->cities));
349 break;
350 }
351 size[j].player = pplayer;
352 j++;
353 } /* Else the player is dead or barbarian or observer */
355
356 qsort(size, j, sizeof(size[0]), secompare);
357 report->body[0] = '\0';
358 for (i = 0; i < j; i++) {
359 if (i > 0 && size[i].value < size[i - 1].value) {
360 /* Since i < j, only top entry reigns Supreme */
361 rank = ((i * ARRAY_SIZE(ranking)) / j) + 1;
362 }
363 if (rank >= ARRAY_SIZE(ranking)) {
364 /* Clamp to final entry */
365 rank = ARRAY_SIZE(ranking) - 1;
366 }
368 _(ranking[rank]),
369 i + 1,
371 fc_strlcat(report->body, "\n", REPORT_BODYSIZE);
372 }
376}
377
378/**********************************************************************/
382{
383 /* History report is actually constructed at the end of previous turn. */
385 page_conn_etype(dest, _("Historian Publishes!"),
388 }
389}
390
391/**********************************************************************/
394static int nr_wonders(struct city *pcity)
395{
396 int result = 0;
397
399 if (is_great_wonder(i)) {
400 result++;
401 }
403
404 return result;
405}
406
407/**********************************************************************/
410void report_top_cities(struct conn_list *dest)
411{
412 if (game.info.top_cities_count > 0) {
413 /* A wonder equals WONDER_FACTOR citizen */
414 const int WONDER_FACTOR = 5;
415 struct city_score_entry size[game.info.top_cities_count];
416 int i;
417 char header[256];
418 char buffer[4096];
419
420 for (i = 0; i < game.info.top_cities_count; i++) {
421 size[i].value = 0;
422 size[i].city = nullptr;
423 }
424
425 shuffled_players_iterate(pplayer) {
426 city_list_iterate(pplayer->cities, pcity) {
429
430 if (value_of_pcity > size[game.info.top_cities_count - 1].value) {
432 size[game.info.top_cities_count - 1].city = pcity;
434 }
437
438 buffer[0] = '\0';
439 for (i = 0; i < game.info.top_cities_count; i++) {
440 int wonders;
441
442 if (size[i].city == nullptr) {
443 /*
444 * There are less than game.info.top_cities_count cities in
445 * the whole game.
446 */
447 break;
448 }
449
450 if (player_count() > team_count()) {
451 /* There exists a team with more than one member. */
452 char team_name[2 * MAX_LEN_NAME];
453
455 sizeof(team_name));
456 cat_snprintf(buffer, sizeof(buffer),
457 /* TRANS:"The French City of Lyon (team 3) of size 18". */
458 _("%2d: The %s City of %s (%s) of size %d, "), i + 1,
460 city_name_get(size[i].city), team_name,
462 } else {
463 cat_snprintf(buffer, sizeof(buffer),
464 _("%2d: The %s City of %s of size %d, "), i + 1,
467 }
468
469 wonders = nr_wonders(size[i].city);
470 if (wonders == 0) {
471 cat_snprintf(buffer, sizeof(buffer), _("with no Great Wonders\n"));
472 } else {
473 cat_snprintf(buffer, sizeof(buffer),
474 PL_("with %d Great Wonder\n", "with %d Great Wonders\n",
475 wonders),
476 wonders);
477 }
478 }
479
480 fc_snprintf(header, sizeof(header),
481 PL_("The %d Greatest City in the World!",
482 "The %d Greatest Cities in the World!",
485 page_conn(dest, _("Traveler's Report:"), header, buffer);
486 }
487}
488
489/**********************************************************************/
494{
495 char buffer[4096];
496 const char *separator = "\n";
497 struct strvec *wonderlist = strvec_new();
498
499 buffer[0] = '\0';
500
501 /* Sort by players and cities */
502 players_iterate(pplayer) {
503 city_list_iterate(pplayer->cities, pcity) {
504 int w = 0;
505
507 if (is_great_wonder(i)) {
508 w++;
509
510 if (player_count() > team_count()) {
511 /* There exists a team with more than one member. */
512 char team_name[2 * MAX_LEN_NAME];
513
515 sizeof(team_name));
516 cat_snprintf(buffer, sizeof(buffer),
517 /* TRANS: "Colossus in Rhodes (Greek, team 2)". */
518 _("%s in %s (%s, %s)\n"),
522 team_name);
523 } else {
524 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
528 }
529 } /* endif is_great_wonder */
531
532 if (w != 0) {
533 cat_snprintf(buffer, sizeof(buffer), "\n");
534 }
537
538 cat_snprintf(buffer, sizeof(buffer), "----------------------------\n");
539
540 /* Find destroyed wonders */
542 if (is_great_wonder(imp)) {
544 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
546 }
547 }
549
550 /* Blank line */
551 cat_snprintf(buffer, sizeof(buffer), "----------------------------\n");
552
553 /* Copy buffer into list before "building %s in ...."
554 because all "building %s" would be sorted at the same letter b */
555
557
559 if (is_great_wonder(i)) {
560 players_iterate(pplayer) {
561 city_list_iterate(pplayer->cities, pcity) {
562 if (VUT_IMPROVEMENT == pcity->production.kind
563 && pcity->production.value.building == i) {
564 if (player_count() > team_count()) {
565 /* There exists a team with more than one member. */
566 char team_name[2 * MAX_LEN_NAME];
567
569 sizeof(team_name));
570 cat_snprintf(buffer, sizeof(buffer),
571 /* TRANS: "([...] (Roman, team 4))". */
572 _("(building %s in %s (%s, %s))\n"),
574 _(nation_adjective_for_player(pplayer)), team_name);
575 } else {
576 cat_snprintf(buffer, sizeof(buffer),
577 _("(building %s in %s (%s))\n"),
580 }
581 }
584 }
586
587 /* Show again all wonders, sorted alphabetically */
588 /* The separator line will be the first one, no need to add another one */
591
593 cat_snprintf(buffer, sizeof(buffer), "%s\n", wonder);
595
596 page_conn(dest, _("Traveler's Report:"),
597 _("Wonders of the World"), buffer);
598}
599
600/**********************************************************************/
605{
606 char buffer[4096];
607
608 buffer[0] = '\0';
609
611 if (is_great_wonder(i)) {
613
614 if (pcity) {
615 if (player_count() > team_count()) {
616 /* There exists a team with more than one member. */
617 char team_name[2 * MAX_LEN_NAME];
618
620 sizeof(team_name));
621 cat_snprintf(buffer, sizeof(buffer),
622 /* TRANS: "Colossus in Rhodes (Greek, team 2)". */
623 _("%s in %s (%s, %s)\n"),
627 team_name);
628 } else {
629 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
633 }
634 } else if (great_wonder_is_destroyed(i)) {
635 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
637 }
638 }
640
642 if (is_great_wonder(i)) {
643 players_iterate(pplayer) {
644 city_list_iterate(pplayer->cities, pcity) {
645 if (VUT_IMPROVEMENT == pcity->production.kind
646 && pcity->production.value.building == i) {
647 if (player_count() > team_count()) {
648 /* There exists a team with more than one member. */
649 char team_name[2 * MAX_LEN_NAME];
650
652 sizeof(team_name));
653 cat_snprintf(buffer, sizeof(buffer),
654 /* TRANS: "([...] (Roman, team 4))". */
655 _("(building %s in %s (%s, %s))\n"),
657 nation_adjective_for_player(pplayer), team_name);
658 } else {
659 cat_snprintf(buffer, sizeof(buffer),
660 _("(building %s in %s (%s))\n"),
663 }
664 }
667 }
669
670 page_conn(dest, _("Traveler's Report:"),
671 _("Wonders of the World"), buffer);
672}
673
674/**************************************************************************
675 Helper functions which return the value for the given player.
676**************************************************************************/
677
678/**********************************************************************/
681static int get_population(const struct player *pplayer)
682{
683 return pplayer->score.population;
684}
685
686/**********************************************************************/
689static int get_pop(const struct player *pplayer)
690{
691 return total_player_citizens(pplayer);
692}
693
694/**********************************************************************/
697static int get_real_pop(const struct player *pplayer)
698{
699 return 1000 * get_pop(pplayer);
700}
701
702/**********************************************************************/
705static int get_landarea(const struct player *pplayer)
706{
707 return pplayer->score.landarea;
708}
709
710/**********************************************************************/
713static int get_settledarea(const struct player *pplayer)
714{
715 return pplayer->score.settledarea;
716}
717
718/**********************************************************************/
721static int get_research(const struct player *pplayer)
722{
723 return pplayer->score.techout;
724}
725
726/**********************************************************************/
729static int get_production(const struct player *pplayer)
730{
731 return pplayer->score.mfg;
732}
733
734/**********************************************************************/
737static int get_economics(const struct player *pplayer)
738{
739 return pplayer->score.bnp;
740}
741
742/**********************************************************************/
745static int get_pollution(const struct player *pplayer)
746{
747 return pplayer->score.pollution;
748}
749
750/**********************************************************************/
753static int get_mil_service(const struct player *pplayer)
754{
755 return (pplayer->score.units * 5000) / (10 + pplayer->score.population);
756}
757
758/**********************************************************************/
761static int get_cities(const struct player *pplayer)
762{
763 return pplayer->score.cities;
764}
765
766/**********************************************************************/
769static int get_techs(const struct player *pplayer)
770{
771 return pplayer->score.techs;
772}
773
774/**********************************************************************/
777static int get_munits(const struct player *pplayer)
778{
779 int result = 0;
780
781 /* Count up military units */
782 unit_list_iterate(pplayer->units, punit) {
783 if (!is_special_unit(punit)) {
784 result++;
785 }
787
788 return result;
789}
790
791/**********************************************************************/
794static int get_settlers(const struct player *pplayer)
795{
796 int result = 0;
797
799 /* Count up settlers */
800 unit_list_iterate(pplayer->units, punit) {
802 result++;
803 }
805 }
806
807 return result;
808}
809
810/**********************************************************************/
813static int get_wonders(const struct player *pplayer)
814{
815 return pplayer->score.wonders;
816}
817
818/**********************************************************************/
821static int get_techout(const struct player *pplayer)
822{
823 return pplayer->score.techout;
824}
825
826/**********************************************************************/
830static int get_literacy2(const struct player *pplayer)
831{
832 return pplayer->score.literacy;
833}
834
835/**********************************************************************/
838static int get_spaceship(const struct player *pplayer)
839{
840 return pplayer->score.spaceship;
841}
842
843/**********************************************************************/
846static int get_units_built(const struct player *pplayer)
847{
848 return pplayer->score.units_built;
849}
850
851/**********************************************************************/
854static int get_units_killed(const struct player *pplayer)
855{
856 return pplayer->score.units_killed;
857}
858
859/**********************************************************************/
862static int get_units_lost(const struct player *pplayer)
863{
864 return pplayer->score.units_lost;
865}
866
867/**********************************************************************/
870static int get_units_used(const struct player *pplayer)
871{
872 return pplayer->score.units_used;
873}
874
875/**********************************************************************/
878static int get_gold(const struct player *pplayer)
879{
880 return pplayer->economic.gold;
881}
882
883/**********************************************************************/
886static int get_taxrate(const struct player *pplayer)
887{
888 return pplayer->economic.tax;
889}
890
891/**********************************************************************/
894static int get_scirate(const struct player *pplayer)
895{
896 return pplayer->economic.science;
897}
898
899/**********************************************************************/
902static int get_luxrate(const struct player *pplayer)
903{
904 return pplayer->economic.luxury;
905}
906
907/**********************************************************************/
910static int get_riots(const struct player *pplayer)
911{
912 int result = 0;
913
914 city_list_iterate(pplayer->cities, pcity) {
915 if (pcity->anarchy > 0) {
916 result++;
917 }
919
920 return result;
921}
922
923/**********************************************************************/
926static int get_happypop(const struct player *pplayer)
927{
928 return pplayer->score.happy;
929}
930
931/**********************************************************************/
934static int get_contentpop(const struct player *pplayer)
935{
936 return pplayer->score.content;
937}
938
939/**********************************************************************/
942static int get_unhappypop(const struct player *pplayer)
943{
944 return pplayer->score.unhappy;
945}
946
947/**********************************************************************/
950static int get_specialists(const struct player *pplayer)
951{
952 int count = 0;
953
955 count += pplayer->score.specialists[sp];
957
958 return count;
959}
960
961/**********************************************************************/
964static int get_gov(const struct player *pplayer)
965{
966 return (int) government_number(government_of_player(pplayer));
967}
968
969/**********************************************************************/
972static int get_corruption(const struct player *pplayer)
973{
974 int result = 0;
975
976 city_list_iterate(pplayer->cities, pcity) {
977 result += pcity->waste[O_TRADE];
979
980 return result;
981}
982
983/**********************************************************************/
986static int get_total_score(const struct player *pplayer)
987{
988 return pplayer->score.game;
989}
990
991/**********************************************************************/
994static int get_culture(const struct player *pplayer)
995{
996 return pplayer->score.culture;
997}
998
999/**********************************************************************/
1002static const char *value_units(int val, const char *uni)
1003{
1004 static char buf[64];
1005
1006 if (fc_snprintf(buf, sizeof(buf), "%s%s", int_to_text(val), uni) == -1) {
1007 log_error("String truncated in value_units()!");
1008 }
1009
1010 return buf;
1011}
1012
1013/**********************************************************************/
1017static const char *area_to_text(int value)
1018{
1019 /* TRANS: abbreviation of "square miles" */
1020 return value_units(value, PL_(" sq. mi.", " sq. mi.", value));
1021}
1022
1023/**********************************************************************/
1027static const char *percent_to_text(int value)
1028{
1029 return value_units(value, "%");
1030}
1031
1032/**********************************************************************/
1036static const char *production_to_text(int value)
1037{
1038 int clip = MAX(0, value);
1039
1040 /* TRANS: "M tons" = million tons, so always plural */
1041 return value_units(clip, PL_(" M tons", " M tons", clip));
1042}
1043
1044/**********************************************************************/
1048static const char *economics_to_text(int value)
1049{
1050 /* TRANS: "M goods" = million goods, so always plural */
1051 return value_units(value, PL_(" M goods", " M goods", value));
1052}
1053
1054/**********************************************************************/
1058static const char *science_to_text(int value)
1059{
1060 return value_units(value, PL_(" bulb", " bulbs", value));
1061}
1062
1063/**********************************************************************/
1067static const char *mil_service_to_text(int value)
1068{
1069 return value_units(value, PL_(" month", " months", value));
1070}
1071
1072/**********************************************************************/
1076static const char *pollution_to_text(int value)
1077{
1078 return value_units(value, PL_(" ton", " tons", value));
1079}
1080
1081/**********************************************************************/
1085static const char *culture_to_text(int value)
1086{
1087 /* TRANS: Unit(s) of culture */
1088 return value_units(value, PL_(" point", " points", value));
1089}
1090
1091/**********************************************************************/
1094static void dem_line_item(char *outptr, size_t out_size,
1095 struct player *pplayer, struct dem_row *prow,
1097{
1098 if (pplayer != nullptr && BV_ISSET(selcols, DEM_COL_QUANTITY)) {
1099 const char *text = prow->to_text(prow->get_value(pplayer));
1100
1101 cat_snprintf(outptr, out_size, " %s", text);
1103 18 - (int) get_internal_string_length(text), "");
1104 }
1105
1106 if (pplayer != nullptr && BV_ISSET(selcols, DEM_COL_RANK)) {
1107 int basis = prow->get_value(pplayer);
1108 int place = 1;
1109
1111 if (GOOD_PLAYER(other)
1112 && ((prow->greater_values_are_better
1113 && prow->get_value(other) > basis)
1114 || (!prow->greater_values_are_better
1115 && prow->get_value(other) < basis))) {
1116 place++;
1117 }
1119
1120 cat_snprintf(outptr, out_size, _("(ranked %d)"), place);
1121 }
1122
1123 if (pplayer == nullptr || BV_ISSET(selcols, DEM_COL_BEST)) {
1124 struct player *best_player = pplayer;
1125 int best_value = (pplayer != nullptr) ? prow->get_value(pplayer) : 0;
1126
1128 if (GOOD_PLAYER(other)) {
1129 int value = prow->get_value(other);
1130
1131 if (!best_player
1132 || (prow->greater_values_are_better && value > best_value)
1133 || (!prow->greater_values_are_better && value < best_value)) {
1135 best_value = value;
1136 }
1137 }
1139
1140 if (pplayer == nullptr
1141 || (team_has_embassy(pplayer->team, best_player)
1142 && (pplayer != best_player))) {
1143 cat_snprintf(outptr, out_size, " %s: %s",
1145 prow->to_text(prow->get_value(best_player)));
1146 }
1147 }
1148}
1149
1150/**********************************************************************/
1158bool is_valid_demography(const char *demography, int *error)
1159{
1160 int len = strlen(demography), i;
1161
1162 /* We check each character individually to see if it's valid.
1163 * This does not check for duplicate entries. */
1164 for (i = 0; i < len; i++) {
1165 bool found = FALSE;
1166 int j;
1167
1168 /* See if the character is a valid column label. */
1169 for (j = 0; j < DEM_COL_LAST; j++) {
1170 if (demography[i] == coltable[j].key) {
1171 found = TRUE;
1172 break;
1173 }
1174 }
1175
1176 if (found) {
1177 continue;
1178 }
1179
1180 /* See if the character is a valid row label. */
1181 for (j = 0; j < ARRAY_SIZE(rowtable); j++) {
1182 if (demography[i] == rowtable[j].key) {
1183 found = TRUE;
1184 break;
1185 }
1186 }
1187
1188 if (!found) {
1189 if (error != nullptr) {
1190 (*error) = i;
1191 }
1192 /* The character is invalid. */
1193 return FALSE;
1194 }
1195 }
1196
1197 /* Looks like all characters were valid. */
1198 return TRUE;
1199}
1200
1201/**********************************************************************/
1206{
1207 char civbuf[1024];
1208 char buffer[4096];
1209 int i;
1210 bool anyrows;
1212 int numcols = 0;
1213 struct player *pplayer = pconn->playing;
1214
1217 for (i = 0; i < DEM_COL_LAST; i++) {
1219 BV_SET(selcols, i);
1220 numcols++;
1221 }
1222 }
1223
1224 anyrows = FALSE;
1225 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1227 anyrows = TRUE;
1228 break;
1229 }
1230 }
1231
1232 if ((!pconn->observer && !pplayer)
1233 || (pplayer && !pplayer->is_alive)
1234 || !anyrows
1235 || numcols == 0) {
1236 page_conn(pconn->self, _("Demographics Report:"),
1237 _("Sorry, the Demographics report is unavailable."), "");
1238 return;
1239 }
1240
1241 if (pplayer) {
1242 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1245 calendar_text());
1246 } else {
1247 civbuf[0] = '\0';
1248 }
1249
1250 buffer[0] = '\0';
1251 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1253 const char *name = Q_(rowtable[i].name);
1254
1255 cat_snprintf(buffer, sizeof(buffer), "%s", name);
1256 cat_snprintf(buffer, sizeof(buffer), "%*s",
1257 18 - (int) get_internal_string_length(name), "");
1258 dem_line_item(buffer, sizeof(buffer), pplayer, &rowtable[i], selcols);
1259 sz_strlcat(buffer, "\n");
1260 }
1261 }
1262
1263 page_conn(pconn->self, _("Demographics Report:"), civbuf, buffer);
1264}
1265
1266/**********************************************************************/
1270{
1271 char civbuf[1024];
1272 char buffer[4096];
1273 struct player *pplayer = pconn->playing;
1274
1275 if (pplayer == nullptr) {
1276 return;
1277 }
1278
1279 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1282 calendar_text());
1283
1284 buffer[0] = '\0';
1285
1287 if (achievement_player_has(pach, pplayer)) {
1288 cat_snprintf(buffer, sizeof(buffer), "%s\n",
1290 }
1292
1293 page_conn(pconn->self, _("Achievements List:"), civbuf, buffer);
1294}
1295
1296/**********************************************************************/
1299static void plrdata_slot_init(struct plrdata_slot *plrdata,
1300 const char *name)
1301{
1302 fc_assert_ret(plrdata->name == nullptr);
1303
1304 plrdata->name = fc_calloc(MAX_LEN_NAME, sizeof(plrdata->name));
1305 plrdata_slot_replace(plrdata, name);
1306}
1307
1308/**********************************************************************/
1311static void plrdata_slot_replace(struct plrdata_slot *plrdata,
1312 const char *name)
1313{
1314 fc_assert_ret(plrdata->name != nullptr);
1315
1316 fc_strlcpy(plrdata->name, name, MAX_LEN_NAME);
1317}
1318
1319/**********************************************************************/
1322static void plrdata_slot_free(struct plrdata_slot *plrdata)
1323{
1324 if (plrdata->name != nullptr) {
1325 free(plrdata->name);
1326 plrdata->name = nullptr;
1327 }
1328}
1329
1330/**********************************************************************/
1337static bool scan_score_log(char *id)
1338{
1339 int line_nr, turn, plr_no, spaces;
1340 struct plrdata_slot *plrdata;
1341 char line[MAX_SCORELOG_LINE_LEN], *ptr;
1342
1343 /* Must be big enough to contain any string there might be in "addplayer" line
1344 * to read.
1345 * Could have even sizeof("addplayer 0 0 ") - 1, but maintenance not worth
1346 * saving couple of bytes. */
1347 char plr_name[MAX(MAX_LEN_NAME, MAX_SCORELOG_LINE_LEN - (sizeof("addplayer ") - 1)) + 1];
1348
1349 fc_assert_ret_val(score_log != nullptr, FALSE);
1350 fc_assert_ret_val(score_log->fp != nullptr, FALSE);
1351
1352 score_log->last_turn = -1;
1353 id[0] = '\0';
1354
1355 for (line_nr = 1;; line_nr++) {
1356 if (!fgets(line, sizeof(line), score_log->fp)) {
1357 if (feof(score_log->fp) != 0) {
1358 break;
1359 }
1360 log_error("[%s:-] Can't read scorelog file header!",
1362 return FALSE;
1363 }
1364
1365 ptr = strchr(line, '\n');
1366 if (!ptr) {
1367 log_error("[%s:%d] Line too long!", game.server.scorefile, line_nr);
1368 return FALSE;
1369 }
1370 *ptr = '\0';
1371
1372 if (line_nr == 1) {
1374 log_error("[%s:%d] Bad file magic!", game.server.scorefile, line_nr);
1375 return FALSE;
1376 }
1377 }
1378
1379 if (!fc_strncmp(line, "id ", strlen("id "))) {
1380 if (strlen(id) > 0) {
1381 log_error("[%s:%d] Multiple ID entries!", game.server.scorefile,
1382 line_nr);
1383 return FALSE;
1384 }
1386 if (strcmp(id, server.game_identifier) != 0) {
1387 log_error("[%s:%d] IDs don't match! game='%s' scorelog='%s'",
1388 game.server.scorefile, line_nr, server.game_identifier,
1389 id);
1390 return FALSE;
1391 }
1392 }
1393
1394 if (!fc_strncmp(line, "turn ", strlen("turn "))) {
1395 if (sscanf(line + strlen("turn "), "%d", &turn) != 1) {
1396 log_error("[%s:%d] Bad line (turn)!", game.server.scorefile,
1397 line_nr);
1398 return FALSE;
1399 }
1400
1402 score_log->last_turn = turn;
1403 }
1404
1405 if (!fc_strncmp(line, "addplayer ", strlen("addplayer "))) {
1406 /* If you change this, be sure to adjust plr_name buffer size to
1407 * match longest possible string read. */
1408 if (3 != sscanf(line + strlen("addplayer "), "%d %d %s",
1409 &turn, &plr_no, plr_name)) {
1410 log_error("[%s:%d] Bad line (addplayer)!",
1412 return FALSE;
1413 }
1414
1415 /* Now get the complete player name if there are several parts. */
1416 ptr = line + strlen("addplayer ");
1417 spaces = 0;
1418 while (*ptr != '\0' && spaces < 2) {
1419 if (*ptr == ' ') {
1420 spaces++;
1421 }
1422 ptr++;
1423 }
1424 fc_snprintf(plr_name, sizeof(plr_name), "%s", ptr);
1425 log_debug("add player '%s' (from line %d: '%s')", plr_name, line_nr,
1426 line);
1427
1428 if (0 > plr_no || plr_no >= player_slot_count()) {
1429 log_error("[%s:%d] Invalid player number: %d!",
1431 return FALSE;
1432 }
1433
1434 plrdata = score_log->plrdata + plr_no;
1435 if (plrdata->name != nullptr) {
1436 log_error("[%s:%d] Two names for one player (id %d)!",
1438 return FALSE;
1439 }
1440
1441 plrdata_slot_init(plrdata, plr_name);
1442 }
1443
1444 if (!fc_strncmp(line, "delplayer ", strlen("delplayer "))) {
1445 if (2 != sscanf(line + strlen("delplayer "), "%d %d",
1446 &turn, &plr_no)) {
1447 log_error("[%s:%d] Bad line (delplayer)!",
1449 return FALSE;
1450 }
1451
1452 if (!(plr_no >= 0 && plr_no < player_slot_count())) {
1453 log_error("[%s:%d] Invalid player number: %d!",
1455 return FALSE;
1456 }
1457
1458 plrdata = score_log->plrdata + plr_no;
1459 if (plrdata->name == nullptr) {
1460 log_error("[%s:%d] Trying to remove undefined player (id %d)!",
1462 return FALSE;
1463 }
1464
1465 plrdata_slot_free(plrdata);
1466 }
1467 }
1468
1469 if (score_log->last_turn == -1) {
1470 log_error("[%s:-] Scorelog contains no turn!", game.server.scorefile);
1471 return FALSE;
1472 }
1473
1474 if (strlen(id) == 0) {
1475 log_error("[%s:-] Scorelog contains no ID!", game.server.scorefile);
1476 return FALSE;
1477 }
1478
1479 if (score_log->last_turn + 1 != game.info.turn) {
1480 log_error("[%s:-] Scorelog doesn't match savegame!",
1482 return FALSE;
1483 }
1484
1485 return TRUE;
1486}
1487
1488/**********************************************************************/
1492{
1493 if (score_log != nullptr) {
1494 return;
1495 }
1496
1497 score_log = fc_calloc(1, sizeof(*score_log));
1498 score_log->fp = nullptr;
1499 score_log->last_turn = -1;
1501 sizeof(*score_log->plrdata));
1502 player_slots_iterate(pslot) {
1503 struct plrdata_slot *plrdata = score_log->plrdata
1504 + player_slot_index(pslot);
1505 plrdata->name = nullptr;
1507
1509}
1510
1511/**********************************************************************/
1515{
1516 if (!score_log) {
1517 /* Nothing to do */
1518 return;
1519 }
1520
1521 if (score_log->fp) {
1523 score_log->fp = nullptr;
1524 }
1525
1526 if (score_log->plrdata) {
1527 player_slots_iterate(pslot) {
1528 struct plrdata_slot *plrdata = score_log->plrdata
1529 + player_slot_index(pslot);
1530 if (plrdata->name != nullptr) {
1531 free(plrdata->name);
1532 }
1535 }
1536
1537 free(score_log);
1538 score_log = nullptr;
1539}
1540
1541/**********************************************************************/
1545{
1547 char id[MAX_LEN_GAME_IDENTIFIER];
1548 int i = 0;
1549
1550 if (!game.server.scorelog) {
1551 return;
1552 }
1553
1554 if (!score_log) {
1555 return;
1556 }
1557
1558 if (!score_log->fp) {
1560 oper = SL_CREATE;
1561 } else {
1563 if (!score_log->fp) {
1564 oper = SL_CREATE;
1565 } else {
1566 if (!scan_score_log(id)) {
1568 }
1569 oper = SL_APPEND;
1570
1572 score_log->fp = nullptr;
1573 }
1574 }
1575
1576 switch (oper) {
1577 case SL_CREATE:
1579 if (!score_log->fp) {
1580 log_error("Can't open scorelog file '%s' for creation!",
1583 }
1586 "\n"
1587 "# For a specification of the format of this see doc/README.scorelog or \n"
1588 "# <https://raw.githubusercontent.com/freeciv/freeciv/main/doc/README.scorelog>.\n"
1589 "\n");
1590
1591 fprintf(score_log->fp, "id %s\n", server.game_identifier);
1592 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1593 fprintf(score_log->fp, "tag %d %s\n", i, score_tags[i].name);
1594 }
1595 break;
1596 case SL_APPEND:
1598 if (!score_log->fp) {
1599 log_error("Can't open scorelog file '%s' for appending!",
1602 }
1603 break;
1604 default:
1605 log_error("[%s] bad operation %d", __FUNCTION__, (int) oper);
1607 }
1608 }
1609
1610 if (game.info.turn > score_log->last_turn) {
1611 fprintf(score_log->fp, "turn %d %d %s\n", game.info.turn, game.info.year,
1612 calendar_text());
1614 }
1615
1616 player_slots_iterate(pslot) {
1617 struct plrdata_slot *plrdata = score_log->plrdata
1618 + player_slot_index(pslot);
1619 if (plrdata->name != nullptr
1620 && player_slot_is_used(pslot)) {
1621 struct player *pplayer = player_slot_get_player(pslot);
1622
1623 if (!GOOD_PLAYER(pplayer)) {
1624 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1625 player_number(pplayer));
1626 plrdata_slot_free(plrdata);
1627 }
1628 }
1630
1631 players_iterate(pplayer) {
1632 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1633
1634 if (plrdata->name == nullptr && GOOD_PLAYER(pplayer)) {
1635 switch (game.server.scoreloglevel) {
1636 case SL_HUMANS:
1637 if (is_ai(pplayer)) {
1638 break;
1639 }
1640
1641 fc__fallthrough; /* No break - continue to actual implementation
1642 * in SL_ALL case if reached here */
1643 case SL_ALL:
1644 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1645 player_number(pplayer), player_name(pplayer));
1646 plrdata_slot_init(plrdata, player_name(pplayer));
1647 }
1648 }
1650
1651 players_iterate(pplayer) {
1652 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1653
1654 if (GOOD_PLAYER(pplayer)) {
1655 switch (game.server.scoreloglevel) {
1656 case SL_HUMANS:
1657 if (is_ai(pplayer) && plrdata->name == nullptr) {
1658 /* If a human player toggled into AI mode, don't break. */
1659 break;
1660 }
1661
1662 fc__fallthrough; /* No break - continue to actual implementation
1663 * in SL_ALL case if reached here */
1664 case SL_ALL:
1665 if (strcmp(plrdata->name, player_name(pplayer)) != 0) {
1666 log_debug("player names does not match '%s' != '%s'", plrdata->name,
1667 player_name(pplayer));
1668 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1669 player_number(pplayer));
1670 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1671 player_number(pplayer), player_name(pplayer));
1672 plrdata_slot_replace(plrdata, player_name(pplayer));
1673 }
1674 }
1675 }
1677
1678 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1679 players_iterate(pplayer) {
1680 if (!GOOD_PLAYER(pplayer)
1681 || (game.server.scoreloglevel == SL_HUMANS && is_ai(pplayer))) {
1682 continue;
1683 }
1684
1685 fprintf(score_log->fp, "data %d %d %d %d\n", game.info.turn, i,
1686 player_number(pplayer), score_tags[i].get_value(pplayer));
1688 }
1689
1691
1692 return;
1693
1695
1697}
1698
1699/**********************************************************************/
1703{
1704 if (player_count() == 1) {
1705 return;
1706 }
1707
1709 return;
1710 }
1711
1714
1716 % (HISTORIAN_LAST + 1));
1718}
1719
1720/**********************************************************************/
1725{
1726 static const struct {
1727 const char *name;
1728 int (*score) (const struct player *);
1729 } score_categories[] = {
1730 { N_("Population\n"), get_real_pop },
1731 /* TRANS: "M goods" = million goods */
1732 { N_("Trade\n(M goods)"), get_economics },
1733 /* TRANS: "M tons" = million tons */
1734 { N_("Production\n(M tons)"), get_production },
1735 { N_("Cities\n"), get_cities },
1736 { N_("Technologies\n"), get_techs },
1737 { N_("Military Service\n(months)"), get_mil_service },
1738 { N_("Wonders\n"), get_wonders },
1739 { N_("Research Speed\n(bulbs)"), get_research },
1740 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1741 { N_("Land Area\n(sq. mi.)"), get_landarea },
1742 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1743 { N_("Settled Area\n(sq. mi.)"), get_settledarea },
1744 { N_("Literacy\n(%)"), get_literacy },
1745 { N_("Culture\n"), get_culture },
1746 { N_("Spaceship\n"), get_spaceship },
1747 { N_("Built Units\n"), get_units_built },
1748 { N_("Killed Units\n"), get_units_killed },
1749 { N_("Unit Losses\n"), get_units_lost },
1750 { N_("Units Used\n"), get_units_used },
1751 };
1753
1754 int i, j;
1756 struct packet_endgame_report packet;
1757
1759
1760 if (!dest) {
1761 dest = game.est_connections;
1762 }
1763
1765 for (j = 0; j < score_categories_num; j++) {
1766 sz_strlcpy(packet.category_name[j], score_categories[j].name);
1767 }
1768
1769 i = 0;
1770 players_iterate(pplayer) {
1771 if (!is_barbarian(pplayer)) {
1772 size[i].value = pplayer->score.game;
1773 size[i].player = pplayer;
1774 i++;
1775 }
1777
1778 qsort(size, i, sizeof(size[0]), secompare);
1779
1780 packet.player_num = i;
1781
1782 lsend_packet_endgame_report(dest, &packet);
1783
1784 for (i = 0; i < packet.player_num; i++) {
1786 const struct player *pplayer = size[i].player;
1787
1788 ppacket.category_num = score_categories_num;
1789 ppacket.player_id = player_number(pplayer);
1790 ppacket.score = size[i].value;
1791 for (j = 0; j < score_categories_num; j++) {
1792 ppacket.category_score[j] = score_categories[j].score(pplayer);
1793 }
1794
1795 ppacket.winner = pplayer->is_winner;
1796
1798 }
1799}
1800
1801/**********************************************************************/
1804static void page_conn(struct conn_list *dest, const char *caption,
1805 const char *headline, const char *lines)
1806{
1808}
1809
1810/**********************************************************************/
1821static void page_conn_etype(struct conn_list *dest, const char *caption,
1822 const char *headline, const char *lines,
1823 enum event_type event)
1824{
1825 struct packet_page_msg packet;
1826 int i;
1827 int len;
1828
1829 sz_strlcpy(packet.caption, caption);
1830 sz_strlcpy(packet.headline, headline);
1831 packet.event = event;
1832 len = strlen(lines);
1833 if ((len % (MAX_LEN_CONTENT - 1)) == 0) {
1834 packet.parts = len / (MAX_LEN_CONTENT - 1);
1835 } else {
1836 packet.parts = len / (MAX_LEN_CONTENT - 1) + 1;
1837 }
1838 packet.len = len;
1839
1840 lsend_packet_page_msg(dest, &packet);
1841
1842 for (i = 0; i < packet.parts; i++) {
1844 int plen;
1845
1846 plen = MIN(len, (MAX_LEN_CONTENT - 1));
1847 strncpy(part.lines, &(lines[(MAX_LEN_CONTENT - 1) * i]), plen);
1848 part.lines[plen] = '\0';
1849
1851
1852 len -= plen;
1853 }
1854}
1855
1856/**********************************************************************/
1860{
1861 return &latest_history_report;
1862}
1863
1864/**********************************************************************/
1867int get_tag_score(const char *tag, const struct player *pplayer)
1868{
1869 int i;
1870
1871 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1872 if (!fc_strcasecmp(tag, score_tags[i].name)) {
1873 return score_tags[i].get_value(pplayer);
1874 }
1875 }
1876
1877 return -1;
1878}
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:140
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
const char * calendar_text(void)
Definition calendar.c:142
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:505
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define city_owner(_pcity_)
Definition city.h:560
#define city_list_iterate_end
Definition city.h:507
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
char * incite_cost
Definition comments.c:76
#define MAX_LEN_CONTENT
Definition conn_types.h:32
int player_culture(const struct player *plr)
Definition culture.c:49
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
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
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:396
#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:739
struct civ_game game
Definition game.c:61
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
@ 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)
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#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:542
#define players_iterate(_pplayer)
Definition player.h:537
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define player_slots_iterate(_pslot)
Definition player.h:528
#define is_ai(plr)
Definition player.h:232
#define player_slots_iterate_end
Definition player.h:532
#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:854
static int get_units_built(const struct player *pplayer)
Definition report.c:846
static int get_contentpop(const struct player *pplayer)
Definition report.c:934
static struct logging_civ_score * score_log
Definition report.c:70
static int nr_wonders(struct city *pcity)
Definition report.c:394
static const char * ranking[]
Definition report.c:272
void report_final_scores(struct conn_list *dest)
Definition report.c:1724
static const char * economics_to_text(int value)
Definition report.c:1048
static const char * production_to_text(int value)
Definition report.c:1036
static int get_munits(const struct player *pplayer)
Definition report.c:777
static const char * science_to_text(int value)
Definition report.c:1058
static int get_pollution(const struct player *pplayer)
Definition report.c:745
#define HISTORIAN_LAST
Definition report.c:93
static int get_economics(const struct player *pplayer)
Definition report.c:737
static int get_techs(const struct player *pplayer)
Definition report.c:769
static void plrdata_slot_init(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1299
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:1821
static int get_pop(const struct player *pplayer)
Definition report.c:689
static int get_riots(const struct player *pplayer)
Definition report.c:910
static void historian_generic(struct history_report *report, enum historian_type which_news)
Definition report.c:317
static const char * pollution_to_text(int value)
Definition report.c:1076
static void plrdata_slot_replace(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1311
static int get_production(const struct player *pplayer)
Definition report.c:729
struct history_report latest_history_report
Definition report.c:68
static bool scan_score_log(char *id)
Definition report.c:1337
static int get_scirate(const struct player *pplayer)
Definition report.c:894
static int get_taxrate(const struct player *pplayer)
Definition report.c:886
void send_current_history_report(struct conn_list *dest)
Definition report.c:381
static int get_spaceship(const struct player *pplayer)
Definition report.c:838
void report_wonders_of_the_world(struct conn_list *dest)
Definition report.c:604
dem_flag
Definition report.c:260
@ DEM_COL_BEST
Definition report.c:263
@ DEM_COL_RANK
Definition report.c:262
@ DEM_COL_QUANTITY
Definition report.c:261
@ DEM_COL_LAST
Definition report.c:264
int(* get_value)(const struct player *)
Definition report.c:193
historian_type
Definition report.c:84
@ HISTORIAN_LARGEST
Definition report.c:89
@ HISTORIAN_CULTURAL
Definition report.c:90
@ HISTORIAN_MILITARY
Definition report.c:87
@ HISTORIAN_ADVANCED
Definition report.c:86
@ HISTORIAN_RICHEST
Definition report.c:85
@ HISTORIAN_HAPPIEST
Definition report.c:88
char * name
Definition report.c:192
void report_demographics(struct connection *pconn)
Definition report.c:1205
static const char * historian_message[]
Definition report.c:95
static int get_corruption(const struct player *pplayer)
Definition report.c:972
static int get_wonders(const struct player *pplayer)
Definition report.c:813
void report_wonders_of_the_world_long(struct conn_list *dest)
Definition report.c:493
static int get_landarea(const struct player *pplayer)
Definition report.c:705
static int get_total_score(const struct player *pplayer)
Definition report.c:986
static const char * area_to_text(int value)
Definition report.c:1017
static const char scorelog_magic[]
Definition report.c:132
static int get_population(const struct player *pplayer)
Definition report.c:681
int get_tag_score(const char *tag, const struct player *pplayer)
Definition report.c:1867
static struct dem_col coltable[]
static int get_units_used(const struct player *pplayer)
Definition report.c:870
static const char * historian_name[]
Definition report.c:110
#define GOOD_PLAYER(p)
Definition report.c:234
struct history_report * history_report_get(void)
Definition report.c:1859
void make_history_report(void)
Definition report.c:1702
void log_civ_score_free(void)
Definition report.c:1514
static int get_culture(const struct player *pplayer)
Definition report.c:994
static const char * value_units(int val, const char *uni)
Definition report.c:1002
static int get_techout(const struct player *pplayer)
Definition report.c:821
static int get_specialists(const struct player *pplayer)
Definition report.c:950
static struct dem_row rowtable[]
static int get_unhappypop(const struct player *pplayer)
Definition report.c:942
bool is_valid_demography(const char *demography, int *error)
Definition report.c:1158
static const struct @100 score_tags[]
void report_top_cities(struct conn_list *dest)
Definition report.c:410
static int get_settledarea(const struct player *pplayer)
Definition report.c:713
void log_civ_score_init(void)
Definition report.c:1491
static int get_literacy2(const struct player *pplayer)
Definition report.c:830
static void dem_line_item(char *outptr, size_t out_size, struct player *pplayer, struct dem_row *prow, bv_cols selcols)
Definition report.c:1094
static const char * culture_to_text(int value)
Definition report.c:1085
static int get_mil_service(const struct player *pplayer)
Definition report.c:753
void report_achievements(struct connection *pconn)
Definition report.c:1269
static const char * percent_to_text(int value)
Definition report.c:1027
static int secompare(const void *a, const void *b)
Definition report.c:308
static int get_happypop(const struct player *pplayer)
Definition report.c:926
static void plrdata_slot_free(struct plrdata_slot *plrdata)
Definition report.c:1322
static void page_conn(struct conn_list *dest, const char *caption, const char *headline, const char *lines)
Definition report.c:1804
static int get_settlers(const struct player *pplayer)
Definition report.c:794
static int get_real_pop(const struct player *pplayer)
Definition report.c:697
static int get_luxrate(const struct player *pplayer)
Definition report.c:902
void log_civ_score_now(void)
Definition report.c:1544
static int get_units_lost(const struct player *pplayer)
Definition report.c:862
static int get_gold(const struct player *pplayer)
Definition report.c:878
#define MAX_SCORELOG_LINE_LEN
Definition report.c:130
static int get_cities(const struct player *pplayer)
Definition report.c:761
static const char * mil_service_to_text(int value)
Definition report.c:1067
static int get_gov(const struct player *pplayer)
Definition report.c:964
static int get_research(const struct player *pplayer)
Definition report.c:721
#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:383
const char * int_to_text(unsigned int number)
Definition shared.c:237
#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:139
int value
Definition report.c:141
struct city * city
Definition report.c:140
Definition city.h:317
char * name
Definition city.h:318
char scorefile[MAX_LEN_PATH]
Definition game.h:231
char demography[MAX_LEN_DEMOGRAPHY]
Definition game.h:247
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:230
int start_year
Definition game.h:198
int scoreturn
Definition game.h:232
struct packet_scenario_info scenario
Definition game.h:87
struct civ_game::@32::@36 server
bool scorelog
Definition game.h:229
char key
Definition report.c:268
const char * name
Definition report.c:241
int(* get_value)(const struct player *)
Definition report.c:242
const char key
Definition report.c:240
bool greater_values_are_better
Definition report.c:244
char title[REPORT_TITLESIZE]
Definition report.h:28
char body[REPORT_BODYSIZE]
Definition report.h:29
struct plrdata_slot * plrdata
Definition report.c:63
char category_name[32][MAX_LEN_NAME]
Definition packets_gen.h:89
enum event_type event
char headline[MAX_LEN_MSG]
char caption[MAX_LEN_MSG]
Definition goto.c:52
Definition report.c:134
const struct player * player
Definition report.c:135
int value
Definition report.c:136
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct city_list * cities
Definition player.h:281
bool is_winner
Definition player.h:269
struct team * team
Definition player.h:261
struct unit_list * units
Definition player.h:282
bool is_alive
Definition player.h:268
struct player_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
char * name
Definition report.c:57
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:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:505
#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:383
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