Freeciv-3.3: /fast/freeciv/nightly/main/server/report.c Source File

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 "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 */
55 struct plrdata_slot {
56 char *name;
57};
58
59 struct logging_civ_score {
60 FILE *fp;
61 int last_turn;
62 struct plrdata_slot *plrdata;
63};
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. */
67 struct history_report latest_history_report = { -2 };
68
69 static struct logging_civ_score *score_log = nullptr;
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
83 enum historian_type {
84 HISTORIAN_RICHEST = 0,
85 HISTORIAN_ADVANCED = 1,
86 HISTORIAN_MILITARY = 2,
87 HISTORIAN_HAPPIEST = 3,
88 HISTORIAN_LARGEST = 4};
89
90#define HISTORIAN_FIRST HISTORIAN_RICHEST
91#define HISTORIAN_LAST HISTORIAN_LARGEST
92
93 static 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
106 static 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
128 static const char scorelog_magic[] = "#FREECIV SCORELOG2 ";
129
130 struct player_score_entry {
131 const struct player *player;
132 int value;
133};
134
135 struct city_score_entry {
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 */
164 static struct dem_row {
165 const char key;
166 const char *name;
167 int (*get_value) (const struct player *);
168 const char *(*to_text) (int);
169 bool greater_values_are_better;
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 }
182};
183
184/* Demographics columns. */
185 enum dem_flag {
186 DEM_COL_QUANTITY,
187 DEM_COL_RANK,
188 DEM_COL_BEST,
189 DEM_COL_LAST
190};
191 BV_DEFINE(bv_cols, DEM_COL_LAST);
192 static 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 */
197 static 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/**********************************************************************/
233 static 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/**********************************************************************/
242 static void historian_generic(struct history_report *report,
243 enum historian_type which_news)
244{
245 int i, j = 0, rank = 0;
246 struct player_score_entry size[player_count()];
247
248 report->turn = game.info.turn;
249 players_iterate(pplayer) {
250 if (GOOD_PLAYER(pplayer)) {
251 switch (which_news) {
252 case HISTORIAN_RICHEST:
253 size[j].value = pplayer->economic.gold;
254 break;
255 case HISTORIAN_ADVANCED:
256 size[j].value
257 = pplayer->score.techs + research_get(pplayer)->future_tech;
258 break;
259 case HISTORIAN_MILITARY:
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;
268 case HISTORIAN_LARGEST:
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 */
275 } players_iterate_end;
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 }
288 cat_snprintf(report->body, REPORT_BODYSIZE,
289 _(ranking[rank]),
290 i + 1,
291 nation_plural_for_player(size[i].player));
292 fc_strlcat(report->body, "\n", REPORT_BODYSIZE);
293 }
294 fc_snprintf(report->title, REPORT_TITLESIZE, _(historian_message[which_news]),
295 calendar_text(),
296 _(historian_name[fc_rand(ARRAY_SIZE(historian_name))]));
297}
298
299/**********************************************************************/
302 void send_current_history_report(struct conn_list *dest)
303{
304 /* History report is actually constructed at the end of previous turn. */
305 if (latest_history_report.turn >= game.info.turn - 1) {
306 page_conn_etype(dest, _("Historian Publishes!"),
307 latest_history_report.title, latest_history_report.body,
308 E_BROADCAST_REPORT);
309 }
310}
311
312/**********************************************************************/
315 static 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 }
323 } city_built_iterate_end;
324
325 return result;
326}
327
328/**********************************************************************/
331 void 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 = nullptr;
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) {
352 size[game.info.top_cities_count - 1].value = value_of_pcity;
353 size[game.info.top_cities_count - 1].city = pcity;
354 qsort(size, game.info.top_cities_count, sizeof(size[0]), secompare);
355 }
356 } city_list_iterate_end;
357 } shuffled_players_iterate_end;
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 == nullptr) {
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
375 team_pretty_name(city_owner(size[i].city)->team, team_name,
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,
380 nation_adjective_for_player(city_owner(size[i].city)),
381 city_name_get(size[i].city), team_name,
382 city_size_get(size[i].city));
383 } else {
384 cat_snprintf(buffer, sizeof(buffer),
385 _("%2d: The %s City of %s of size %d, "), i + 1,
386 nation_adjective_for_player(city_owner(size[i].city)),
387 city_name_get(size[i].city), city_size_get(size[i].city));
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!",
404 game.info.top_cities_count),
405 game.info.top_cities_count);
406 page_conn(dest, _("Traveler's Report:"), header, buffer);
407 }
408}
409
410/**********************************************************************/
414 void report_wonders_of_the_world_long(struct conn_list *dest)
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"),
440 city_improvement_name_translation(pcity, i),
441 city_name_get(pcity),
442 _(nation_adjective_for_player(pplayer)),
443 team_name);
444 } else {
445 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
446 city_improvement_name_translation(pcity, i),
447 city_name_get(pcity),
448 _(nation_adjective_for_player(pplayer)));
449 }
450 } /* endif is_great_wonder */
451 } city_built_iterate_end;
452
453 if (w != 0) {
454 cat_snprintf(buffer, sizeof(buffer), "\n");
455 }
456 } city_list_iterate_end;
457 } players_iterate_end;
458
459 cat_snprintf(buffer, sizeof(buffer), "----------------------------\n");
460
461 /* Find destroyed wonders */
462 improvement_iterate(imp) {
463 if (is_great_wonder(imp)) {
464 if (great_wonder_is_destroyed(imp)) {
465 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
466 improvement_name_translation(imp));
467 }
468 }
469 } improvement_iterate_end;
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
477 strvec_from_str(wonderlist, *separator, buffer);
478
479 improvement_iterate(i) {
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"),
494 improvement_name_translation(i), city_name_get(pcity),
495 _(nation_adjective_for_player(pplayer)), team_name);
496 } else {
497 cat_snprintf(buffer, sizeof(buffer),
498 _("(building %s in %s (%s))\n"),
499 improvement_name_translation(i), city_name_get(pcity),
500 _(nation_adjective_for_player(pplayer)));
501 }
502 }
503 } city_list_iterate_end;
504 } players_iterate_end;
505 }
506 } improvement_iterate_end;
507
508 /* Show again all wonders, sorted alphabetically */
509 /* The separator line will be the first one, no need to add another one */
510 strvec_remove_duplicate(wonderlist, strcmp);
511 strvec_sort(wonderlist, compare_strings_strvec);
512
513 strvec_iterate(wonderlist,wonder) {
514 cat_snprintf(buffer, sizeof(buffer), "%s\n", wonder);
515 } strvec_iterate_end;
516
517 page_conn(dest, _("Traveler's Report:"),
518 _("Wonders of the World"), buffer);
519}
520
521/**********************************************************************/
525 void report_wonders_of_the_world(struct conn_list *dest)
526{
527 char buffer[4096];
528
529 buffer[0] = '\0';
530
531 improvement_iterate(i) {
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"),
545 city_improvement_name_translation(pcity, i),
546 city_name_get(pcity),
547 nation_adjective_for_player(city_owner(pcity)),
548 team_name);
549 } else {
550 cat_snprintf(buffer, sizeof(buffer), _("%s in %s (%s)\n"),
551 city_improvement_name_translation(pcity, i),
552 city_name_get(pcity),
553 nation_adjective_for_player(city_owner(pcity)));
554 }
555 } else if (great_wonder_is_destroyed(i)) {
556 cat_snprintf(buffer, sizeof(buffer), _("%s has been DESTROYED\n"),
557 improvement_name_translation(i));
558 }
559 }
560 } improvement_iterate_end;
561
562 improvement_iterate(i) {
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"),
577 improvement_name_translation(i), city_name_get(pcity),
578 nation_adjective_for_player(pplayer), team_name);
579 } else {
580 cat_snprintf(buffer, sizeof(buffer),
581 _("(building %s in %s (%s))\n"),
582 improvement_name_translation(i), city_name_get(pcity),
583 nation_adjective_for_player(pplayer));
584 }
585 }
586 } city_list_iterate_end;
587 } players_iterate_end;
588 }
589 } improvement_iterate_end;
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/**********************************************************************/
602 static int get_population(const struct player *pplayer)
603{
604 return pplayer->score.population;
605}
606
607/**********************************************************************/
610 static int get_pop(const struct player *pplayer)
611{
612 return total_player_citizens(pplayer);
613}
614
615/**********************************************************************/
618 static int get_real_pop(const struct player *pplayer)
619{
620 return 1000 * get_pop(pplayer);
621}
622
623/**********************************************************************/
626 static int get_landarea(const struct player *pplayer)
627{
628 return pplayer->score.landarea;
629}
630
631/**********************************************************************/
634 static int get_settledarea(const struct player *pplayer)
635{
636 return pplayer->score.settledarea;
637}
638
639/**********************************************************************/
642 static int get_research(const struct player *pplayer)
643{
644 return pplayer->score.techout;
645}
646
647/**********************************************************************/
650 static int get_production(const struct player *pplayer)
651{
652 return pplayer->score.mfg;
653}
654
655/**********************************************************************/
658 static int get_economics(const struct player *pplayer)
659{
660 return pplayer->score.bnp;
661}
662
663/**********************************************************************/
666 static int get_pollution(const struct player *pplayer)
667{
668 return pplayer->score.pollution;
669}
670
671/**********************************************************************/
674 static int get_mil_service(const struct player *pplayer)
675{
676 return (pplayer->score.units * 5000) / (10 + pplayer->score.population);
677}
678
679/**********************************************************************/
682 static int get_cities(const struct player *pplayer)
683{
684 return pplayer->score.cities;
685}
686
687/**********************************************************************/
690 static int get_techs(const struct player *pplayer)
691{
692 return pplayer->score.techs;
693}
694
695/**********************************************************************/
698 static 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 }
707 } unit_list_iterate_end;
708
709 return result;
710}
711
712/**********************************************************************/
715 static int get_settlers(const struct player *pplayer)
716{
717 int result = 0;
718
719 if (!game.scenario.prevent_new_cities) {
720 /* Count up settlers */
721 unit_list_iterate(pplayer->units, punit) {
722 if (unit_can_do_action(punit, ACTION_FOUND_CITY)) {
723 result++;
724 }
725 } unit_list_iterate_end;
726 }
727
728 return result;
729}
730
731/**********************************************************************/
734 static int get_wonders(const struct player *pplayer)
735{
736 return pplayer->score.wonders;
737}
738
739/**********************************************************************/
742 static int get_techout(const struct player *pplayer)
743{
744 return pplayer->score.techout;
745}
746
747/**********************************************************************/
751 static int get_literacy2(const struct player *pplayer)
752{
753 return pplayer->score.literacy;
754}
755
756/**********************************************************************/
759 static int get_spaceship(const struct player *pplayer)
760{
761 return pplayer->score.spaceship;
762}
763
764/**********************************************************************/
767 static int get_units_built(const struct player *pplayer)
768{
769 return pplayer->score.units_built;
770}
771
772/**********************************************************************/
775 static int get_units_killed(const struct player *pplayer)
776{
777 return pplayer->score.units_killed;
778}
779
780/**********************************************************************/
783 static int get_units_lost(const struct player *pplayer)
784{
785 return pplayer->score.units_lost;
786}
787
788/**********************************************************************/
791 static int get_units_used(const struct player *pplayer)
792{
793 return pplayer->score.units_used;
794}
795
796/**********************************************************************/
799 static int get_gold(const struct player *pplayer)
800{
801 return pplayer->economic.gold;
802}
803
804/**********************************************************************/
807 static int get_taxrate(const struct player *pplayer)
808{
809 return pplayer->economic.tax;
810}
811
812/**********************************************************************/
815 static int get_scirate(const struct player *pplayer)
816{
817 return pplayer->economic.science;
818}
819
820/**********************************************************************/
823 static int get_luxrate(const struct player *pplayer)
824{
825 return pplayer->economic.luxury;
826}
827
828/**********************************************************************/
831 static 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 }
839 } city_list_iterate_end;
840
841 return result;
842}
843
844/**********************************************************************/
847 static int get_happypop(const struct player *pplayer)
848{
849 return pplayer->score.happy;
850}
851
852/**********************************************************************/
855 static int get_contentpop(const struct player *pplayer)
856{
857 return pplayer->score.content;
858}
859
860/**********************************************************************/
863 static int get_unhappypop(const struct player *pplayer)
864{
865 return pplayer->score.unhappy;
866}
867
868/**********************************************************************/
871 static int get_specialists(const struct player *pplayer)
872{
873 int count = 0;
874
875 specialist_type_iterate(sp) {
876 count += pplayer->score.specialists[sp];
877 } specialist_type_iterate_end;
878
879 return count;
880}
881
882/**********************************************************************/
885 static int get_gov(const struct player *pplayer)
886{
887 return (int) government_number(government_of_player(pplayer));
888}
889
890/**********************************************************************/
893 static 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];
899 } city_list_iterate_end;
900
901 return result;
902}
903
904/**********************************************************************/
907 static int get_total_score(const struct player *pplayer)
908{
909 return pplayer->score.game;
910}
911
912/**********************************************************************/
915 static int get_culture(const struct player *pplayer)
916{
917 return pplayer->score.culture;
918}
919
920/**********************************************************************/
923 static 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/**********************************************************************/
938 static 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/**********************************************************************/
948 static const char *percent_to_text(int value)
949{
950 return value_units(value, "%");
951}
952
953/**********************************************************************/
957 static const char *production_to_text(int value)
958{
959 int clip = MAX(0, value);
960
961 /* TRANS: "M tons" = million tons, so always plural */
962 return value_units(clip, PL_(" M tons", " M tons", clip));
963}
964
965/**********************************************************************/
969 static const char *economics_to_text(int value)
970{
971 /* TRANS: "M goods" = million goods, so always plural */
972 return value_units(value, PL_(" M goods", " M goods", value));
973}
974
975/**********************************************************************/
979 static const char *science_to_text(int value)
980{
981 return value_units(value, PL_(" bulb", " bulbs", value));
982}
983
984/**********************************************************************/
988 static const char *mil_service_to_text(int value)
989{
990 return value_units(value, PL_(" month", " months", value));
991}
992
993/**********************************************************************/
997 static const char *pollution_to_text(int value)
998{
999 return value_units(value, PL_(" ton", " tons", value));
1000}
1001
1002/**********************************************************************/
1006 static const char *culture_to_text(int value)
1007{
1008 /* TRANS: Unit(s) of culture */
1009 return value_units(value, PL_(" point", " points", value));
1010}
1011
1012/**********************************************************************/
1015 static void dem_line_item(char *outptr, size_t out_size,
1016 struct player *pplayer, struct dem_row *prow,
1017 bv_cols selcols)
1018{
1019 if (pplayer != nullptr && BV_ISSET(selcols, DEM_COL_QUANTITY)) {
1020 const char *text = prow->to_text(prow->get_value(pplayer));
1021
1022 cat_snprintf(outptr, out_size, " %s", text);
1023 cat_snprintf(outptr, out_size, "%*s",
1024 18 - (int) get_internal_string_length(text), "");
1025 }
1026
1027 if (pplayer != nullptr && BV_ISSET(selcols, DEM_COL_RANK)) {
1028 int basis = prow->get_value(pplayer);
1029 int place = 1;
1030
1031 players_iterate(other) {
1032 if (GOOD_PLAYER(other)
1033 && ((prow->greater_values_are_better
1034 && prow->get_value(other) > basis)
1035 || (!prow->greater_values_are_better
1036 && prow->get_value(other) < basis))) {
1037 place++;
1038 }
1039 } players_iterate_end;
1040
1041 cat_snprintf(outptr, out_size, _("(ranked %d)"), place);
1042 }
1043
1044 if (pplayer == nullptr || BV_ISSET(selcols, DEM_COL_BEST)) {
1045 struct player *best_player = pplayer;
1046 int best_value = (pplayer != nullptr) ? prow->get_value(pplayer) : 0;
1047
1048 players_iterate(other) {
1049 if (GOOD_PLAYER(other)) {
1050 int value = prow->get_value(other);
1051
1052 if (!best_player
1053 || (prow->greater_values_are_better && value > best_value)
1054 || (!prow->greater_values_are_better && value < best_value)) {
1055 best_player = other;
1056 best_value = value;
1057 }
1058 }
1059 } players_iterate_end;
1060
1061 if (pplayer == nullptr
1062 || (team_has_embassy(pplayer->team, best_player)
1063 && (pplayer != best_player))) {
1064 cat_snprintf(outptr, out_size, " %s: %s",
1065 nation_plural_for_player(best_player),
1066 prow->to_text(prow->get_value(best_player)));
1067 }
1068 }
1069}
1070
1071/**********************************************************************/
1079 bool is_valid_demography(const char *demography, int *error)
1080{
1081 int len = strlen(demography), i;
1082
1083 /* We check each character individually to see if it's valid.
1084 * This does not check for duplicate entries. */
1085 for (i = 0; i < len; i++) {
1086 bool found = FALSE;
1087 int j;
1088
1089 /* See if the character is a valid column label. */
1090 for (j = 0; j < DEM_COL_LAST; j++) {
1091 if (demography[i] == coltable[j].key) {
1092 found = TRUE;
1093 break;
1094 }
1095 }
1096
1097 if (found) {
1098 continue;
1099 }
1100
1101 /* See if the character is a valid row label. */
1102 for (j = 0; j < ARRAY_SIZE(rowtable); j++) {
1103 if (demography[i] == rowtable[j].key) {
1104 found = TRUE;
1105 break;
1106 }
1107 }
1108
1109 if (!found) {
1110 if (error != nullptr) {
1111 (*error) = i;
1112 }
1113 /* The character is invalid. */
1114 return FALSE;
1115 }
1116 }
1117
1118 /* Looks like all characters were valid. */
1119 return TRUE;
1120}
1121
1122/**********************************************************************/
1126 void report_demographics(struct connection *pconn)
1127{
1128 char civbuf[1024];
1129 char buffer[4096];
1130 int i;
1131 bool anyrows;
1132 bv_cols selcols;
1133 int numcols = 0;
1134 struct player *pplayer = pconn->playing;
1135
1136 BV_CLR_ALL(selcols);
1137 fc_assert_ret(ARRAY_SIZE(coltable) == DEM_COL_LAST);
1138 for (i = 0; i < DEM_COL_LAST; i++) {
1139 if (strchr(game.server.demography, coltable[i].key)) {
1140 BV_SET(selcols, i);
1141 numcols++;
1142 }
1143 }
1144
1145 anyrows = FALSE;
1146 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1147 if (strchr(game.server.demography, rowtable[i].key)) {
1148 anyrows = TRUE;
1149 break;
1150 }
1151 }
1152
1153 if ((!pconn->observer && !pplayer)
1154 || (pplayer && !pplayer->is_alive)
1155 || !anyrows
1156 || numcols == 0) {
1157 page_conn(pconn->self, _("Demographics Report:"),
1158 _("Sorry, the Demographics report is unavailable."), "");
1159 return;
1160 }
1161
1162 if (pplayer) {
1163 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1164 nation_adjective_for_player(pplayer),
1165 government_name_for_player(pplayer),
1166 calendar_text());
1167 } else {
1168 civbuf[0] = '\0';
1169 }
1170
1171 buffer[0] = '\0';
1172 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1173 if (strchr(game.server.demography, rowtable[i].key)) {
1174 const char *name = Q_(rowtable[i].name);
1175
1176 cat_snprintf(buffer, sizeof(buffer), "%s", name);
1177 cat_snprintf(buffer, sizeof(buffer), "%*s",
1178 18 - (int) get_internal_string_length(name), "");
1179 dem_line_item(buffer, sizeof(buffer), pplayer, &rowtable[i], selcols);
1180 sz_strlcat(buffer, "\n");
1181 }
1182 }
1183
1184 page_conn(pconn->self, _("Demographics Report:"), civbuf, buffer);
1185}
1186
1187/**********************************************************************/
1190 void report_achievements(struct connection *pconn)
1191{
1192 char civbuf[1024];
1193 char buffer[4096];
1194 struct player *pplayer = pconn->playing;
1195
1196 if (pplayer == nullptr) {
1197 return;
1198 }
1199
1200 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1201 nation_adjective_for_player(pplayer),
1202 government_name_for_player(pplayer),
1203 calendar_text());
1204
1205 buffer[0] = '\0';
1206
1207 achievements_iterate(pach) {
1208 if (achievement_player_has(pach, pplayer)) {
1209 cat_snprintf(buffer, sizeof(buffer), "%s\n",
1210 achievement_name_translation(pach));
1211 }
1212 } achievements_iterate_end;
1213
1214 page_conn(pconn->self, _("Achievements List:"), civbuf, buffer);
1215}
1216
1217/**********************************************************************/
1220 static void plrdata_slot_init(struct plrdata_slot *plrdata,
1221 const char *name)
1222{
1223 fc_assert_ret(plrdata->name == nullptr);
1224
1225 plrdata->name = fc_calloc(MAX_LEN_NAME, sizeof(plrdata->name));
1226 plrdata_slot_replace(plrdata, name);
1227}
1228
1229/**********************************************************************/
1232 static void plrdata_slot_replace(struct plrdata_slot *plrdata,
1233 const char *name)
1234{
1235 fc_assert_ret(plrdata->name != nullptr);
1236
1237 fc_strlcpy(plrdata->name, name, MAX_LEN_NAME);
1238}
1239
1240/**********************************************************************/
1243 static void plrdata_slot_free(struct plrdata_slot *plrdata)
1244{
1245 if (plrdata->name != nullptr) {
1246 free(plrdata->name);
1247 plrdata->name = nullptr;
1248 }
1249}
1250
1251/**********************************************************************/
1258 static bool scan_score_log(char *id)
1259{
1260 int line_nr, turn, plr_no, spaces;
1261 struct plrdata_slot *plrdata;
1262 char line[MAX_SCORELOG_LINE_LEN], *ptr;
1263
1264 /* Must be big enough to contain any string there might be in "addplayer" line
1265 * to read.
1266 * Could have even strlen("addplayer 0 0 "), but maintenance not worth
1267 * saving couple of bytes. */
1268 char plr_name[MAX(MAX_LEN_NAME, MAX_SCORELOG_LINE_LEN - strlen("addplayer "))];
1269
1270 fc_assert_ret_val(score_log != nullptr, FALSE);
1271 fc_assert_ret_val(score_log->fp != nullptr, FALSE);
1272
1273 score_log->last_turn = -1;
1274 id[0] = '\0';
1275
1276 for (line_nr = 1;; line_nr++) {
1277 if (!fgets(line, sizeof(line), score_log->fp)) {
1278 if (feof(score_log->fp) != 0) {
1279 break;
1280 }
1281 log_error("[%s:-] Can't read scorelog file header!",
1282 game.server.scorefile);
1283 return FALSE;
1284 }
1285
1286 ptr = strchr(line, '\n');
1287 if (!ptr) {
1288 log_error("[%s:%d] Line too long!", game.server.scorefile, line_nr);
1289 return FALSE;
1290 }
1291 *ptr = '\0';
1292
1293 if (line_nr == 1) {
1294 if (fc_strncmp(line, scorelog_magic, strlen(scorelog_magic))) {
1295 log_error("[%s:%d] Bad file magic!", game.server.scorefile, line_nr);
1296 return FALSE;
1297 }
1298 }
1299
1300 if (!fc_strncmp(line, "id ", strlen("id "))) {
1301 if (strlen(id) > 0) {
1302 log_error("[%s:%d] Multiple ID entries!", game.server.scorefile,
1303 line_nr);
1304 return FALSE;
1305 }
1306 fc_strlcpy(id, line + strlen("id "), MAX_LEN_GAME_IDENTIFIER);
1307 if (strcmp(id, server.game_identifier) != 0) {
1308 log_error("[%s:%d] IDs don't match! game='%s' scorelog='%s'",
1309 game.server.scorefile, line_nr, server.game_identifier,
1310 id);
1311 return FALSE;
1312 }
1313 }
1314
1315 if (!fc_strncmp(line, "turn ", strlen("turn "))) {
1316 if (sscanf(line + strlen("turn "), "%d", &turn) != 1) {
1317 log_error("[%s:%d] Bad line (turn)!", game.server.scorefile,
1318 line_nr);
1319 return FALSE;
1320 }
1321
1322 fc_assert_ret_val(turn > score_log->last_turn, FALSE);
1323 score_log->last_turn = turn;
1324 }
1325
1326 if (!fc_strncmp(line, "addplayer ", strlen("addplayer "))) {
1327 /* If you change this, be sure to adjust plr_name buffer size to
1328 * match longest possible string read. */
1329 if (3 != sscanf(line + strlen("addplayer "), "%d %d %s",
1330 &turn, &plr_no, plr_name)) {
1331 log_error("[%s:%d] Bad line (addplayer)!",
1332 game.server.scorefile, line_nr);
1333 return FALSE;
1334 }
1335
1336 /* Now get the complete player name if there are several parts. */
1337 ptr = line + strlen("addplayer ");
1338 spaces = 0;
1339 while (*ptr != '\0' && spaces < 2) {
1340 if (*ptr == ' ') {
1341 spaces++;
1342 }
1343 ptr++;
1344 }
1345 fc_snprintf(plr_name, sizeof(plr_name), "%s", ptr);
1346 log_debug("add player '%s' (from line %d: '%s')", plr_name, line_nr,
1347 line);
1348
1349 if (0 > plr_no || plr_no >= player_slot_count()) {
1350 log_error("[%s:%d] Invalid player number: %d!",
1351 game.server.scorefile, line_nr, plr_no);
1352 return FALSE;
1353 }
1354
1355 plrdata = score_log->plrdata + plr_no;
1356 if (plrdata->name != nullptr) {
1357 log_error("[%s:%d] Two names for one player (id %d)!",
1358 game.server.scorefile, line_nr, plr_no);
1359 return FALSE;
1360 }
1361
1362 plrdata_slot_init(plrdata, plr_name);
1363 }
1364
1365 if (!fc_strncmp(line, "delplayer ", strlen("delplayer "))) {
1366 if (2 != sscanf(line + strlen("delplayer "), "%d %d",
1367 &turn, &plr_no)) {
1368 log_error("[%s:%d] Bad line (delplayer)!",
1369 game.server.scorefile, line_nr);
1370 return FALSE;
1371 }
1372
1373 if (!(plr_no >= 0 && plr_no < player_slot_count())) {
1374 log_error("[%s:%d] Invalid player number: %d!",
1375 game.server.scorefile, line_nr, plr_no);
1376 return FALSE;
1377 }
1378
1379 plrdata = score_log->plrdata + plr_no;
1380 if (plrdata->name == nullptr) {
1381 log_error("[%s:%d] Trying to remove undefined player (id %d)!",
1382 game.server.scorefile, line_nr, plr_no);
1383 return FALSE;
1384 }
1385
1386 plrdata_slot_free(plrdata);
1387 }
1388 }
1389
1390 if (score_log->last_turn == -1) {
1391 log_error("[%s:-] Scorelog contains no turn!", game.server.scorefile);
1392 return FALSE;
1393 }
1394
1395 if (strlen(id) == 0) {
1396 log_error("[%s:-] Scorelog contains no ID!", game.server.scorefile);
1397 return FALSE;
1398 }
1399
1400 if (score_log->last_turn + 1 != game.info.turn) {
1401 log_error("[%s:-] Scorelog doesn't match savegame!",
1402 game.server.scorefile);
1403 return FALSE;
1404 }
1405
1406 return TRUE;
1407}
1408
1409/**********************************************************************/
1412 void log_civ_score_init(void)
1413{
1414 if (score_log != nullptr) {
1415 return;
1416 }
1417
1418 score_log = fc_calloc(1, sizeof(*score_log));
1419 score_log->fp = nullptr;
1420 score_log->last_turn = -1;
1421 score_log->plrdata = fc_calloc(player_slot_count(),
1422 sizeof(*score_log->plrdata));
1423 player_slots_iterate(pslot) {
1424 struct plrdata_slot *plrdata = score_log->plrdata
1425 + player_slot_index(pslot);
1426 plrdata->name = nullptr;
1427 } player_slots_iterate_end;
1428
1429 latest_history_report.turn = -2;
1430}
1431
1432/**********************************************************************/
1435 void log_civ_score_free(void)
1436{
1437 if (!score_log) {
1438 /* Nothing to do */
1439 return;
1440 }
1441
1442 if (score_log->fp) {
1443 fclose(score_log->fp);
1444 score_log->fp = nullptr;
1445 }
1446
1447 if (score_log->plrdata) {
1448 player_slots_iterate(pslot) {
1449 struct plrdata_slot *plrdata = score_log->plrdata
1450 + player_slot_index(pslot);
1451 if (plrdata->name != nullptr) {
1452 free(plrdata->name);
1453 }
1454 } player_slots_iterate_end;
1455 free(score_log->plrdata);
1456 }
1457
1458 free(score_log);
1459 score_log = nullptr;
1460}
1461
1462/**********************************************************************/
1465 void log_civ_score_now(void)
1466{
1467 enum { SL_CREATE, SL_APPEND, SL_UNSPEC } oper = SL_UNSPEC;
1468 char id[MAX_LEN_GAME_IDENTIFIER];
1469 int i = 0;
1470
1471 /* Add new tags only at end of this list. Maintaining the order of
1472 * old tags is critical. */
1473 static const struct {
1474 char *name;
1475 int (*get_value) (const struct player *);
1476 } score_tags[] = {
1477 {"pop", get_pop},
1478 {"bnp", get_economics},
1479 {"mfg", get_production},
1480 {"cities", get_cities},
1481 {"techs", get_techs},
1482 {"munits", get_munits},
1483 {"settlers", get_settlers}, /* "original" tags end here */
1484
1485 {"wonders", get_wonders},
1486 {"techout", get_techout},
1487 {"landarea", get_landarea},
1488 {"settledarea", get_settledarea},
1489 {"pollution", get_pollution},
1490 {"literacy", get_literacy2},
1491 {"spaceship", get_spaceship}, /* new 1.8.2 tags end here */
1492
1493 {"gold", get_gold},
1494 {"taxrate", get_taxrate},
1495 {"scirate", get_scirate},
1496 {"luxrate", get_luxrate},
1497 {"riots", get_riots},
1498 {"happypop", get_happypop},
1499 {"contentpop", get_contentpop},
1500 {"unhappypop", get_unhappypop},
1501 {"specialists", get_specialists},
1502 {"gov", get_gov},
1503 {"corruption", get_corruption}, /* new 1.11.5 tags end here */
1504
1505 {"score", get_total_score}, /* New 2.1.10 tag end here. */
1506
1507 {"unitsbuilt", get_units_built}, /* New tags since 2.3.0. */
1508 {"unitskilled", get_units_killed},
1509 {"unitslost", get_units_lost},
1510
1511 {"culture", get_culture}, /* New tag in 2.6.0. */
1512
1513 {"unitsused", get_units_used} /* New tag in 3.2.0. */
1514 };
1515
1516 if (!game.server.scorelog) {
1517 return;
1518 }
1519
1520 if (!score_log) {
1521 return;
1522 }
1523
1524 if (!score_log->fp) {
1525 if (game.info.year == game.server.start_year) {
1526 oper = SL_CREATE;
1527 } else {
1528 score_log->fp = fc_fopen(game.server.scorefile, "r");
1529 if (!score_log->fp) {
1530 oper = SL_CREATE;
1531 } else {
1532 if (!scan_score_log(id)) {
1533 goto log_civ_score_disable;
1534 }
1535 oper = SL_APPEND;
1536
1537 fclose(score_log->fp);
1538 score_log->fp = nullptr;
1539 }
1540 }
1541
1542 switch (oper) {
1543 case SL_CREATE:
1544 score_log->fp = fc_fopen(game.server.scorefile, "w");
1545 if (!score_log->fp) {
1546 log_error("Can't open scorelog file '%s' for creation!",
1547 game.server.scorefile);
1548 goto log_civ_score_disable;
1549 }
1550 fprintf(score_log->fp, "%s%s\n", scorelog_magic, VERSION_STRING);
1551 fprintf(score_log->fp,
1552 "\n"
1553 "# For a specification of the format of this see doc/README.scorelog or \n"
1554 "# <https://raw.githubusercontent.com/freeciv/freeciv/main/doc/README.scorelog>.\n"
1555 "\n");
1556
1557 fprintf(score_log->fp, "id %s\n", server.game_identifier);
1558 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1559 fprintf(score_log->fp, "tag %d %s\n", i, score_tags[i].name);
1560 }
1561 break;
1562 case SL_APPEND:
1563 score_log->fp = fc_fopen(game.server.scorefile, "a");
1564 if (!score_log->fp) {
1565 log_error("Can't open scorelog file '%s' for appending!",
1566 game.server.scorefile);
1567 goto log_civ_score_disable;
1568 }
1569 break;
1570 default:
1571 log_error("[%s] bad operation %d", __FUNCTION__, (int) oper);
1572 goto log_civ_score_disable;
1573 }
1574 }
1575
1576 if (game.info.turn > score_log->last_turn) {
1577 fprintf(score_log->fp, "turn %d %d %s\n", game.info.turn, game.info.year,
1578 calendar_text());
1579 score_log->last_turn = game.info.turn;
1580 }
1581
1582 player_slots_iterate(pslot) {
1583 struct plrdata_slot *plrdata = score_log->plrdata
1584 + player_slot_index(pslot);
1585 if (plrdata->name != nullptr
1586 && player_slot_is_used(pslot)) {
1587 struct player *pplayer = player_slot_get_player(pslot);
1588
1589 if (!GOOD_PLAYER(pplayer)) {
1590 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1591 player_number(pplayer));
1592 plrdata_slot_free(plrdata);
1593 }
1594 }
1595 } player_slots_iterate_end;
1596
1597 players_iterate(pplayer) {
1598 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1599
1600 if (plrdata->name == nullptr && GOOD_PLAYER(pplayer)) {
1601 switch (game.server.scoreloglevel) {
1602 case SL_HUMANS:
1603 if (is_ai(pplayer)) {
1604 break;
1605 }
1606
1607 fc__fallthrough; /* No break - continue to actual implementation
1608 * in SL_ALL case if reached here */
1609 case SL_ALL:
1610 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1611 player_number(pplayer), player_name(pplayer));
1612 plrdata_slot_init(plrdata, player_name(pplayer));
1613 }
1614 }
1615 } players_iterate_end;
1616
1617 players_iterate(pplayer) {
1618 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1619
1620 if (GOOD_PLAYER(pplayer)) {
1621 switch (game.server.scoreloglevel) {
1622 case SL_HUMANS:
1623 if (is_ai(pplayer) && plrdata->name == nullptr) {
1624 /* If a human player toggled into AI mode, don't break. */
1625 break;
1626 }
1627
1628 fc__fallthrough; /* No break - continue to actual implementation
1629 * in SL_ALL case if reached here */
1630 case SL_ALL:
1631 if (strcmp(plrdata->name, player_name(pplayer)) != 0) {
1632 log_debug("player names does not match '%s' != '%s'", plrdata->name,
1633 player_name(pplayer));
1634 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1635 player_number(pplayer));
1636 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1637 player_number(pplayer), player_name(pplayer));
1638 plrdata_slot_replace(plrdata, player_name(pplayer));
1639 }
1640 }
1641 }
1642 } players_iterate_end;
1643
1644 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1645 players_iterate(pplayer) {
1646 if (!GOOD_PLAYER(pplayer)
1647 || (game.server.scoreloglevel == SL_HUMANS && is_ai(pplayer))) {
1648 continue;
1649 }
1650
1651 fprintf(score_log->fp, "data %d %d %d %d\n", game.info.turn, i,
1652 player_number(pplayer), score_tags[i].get_value(pplayer));
1653 } players_iterate_end;
1654 }
1655
1656 fflush(score_log->fp);
1657
1658 return;
1659
1660 log_civ_score_disable:
1661
1662 log_civ_score_free();
1663}
1664
1665/**********************************************************************/
1668 void make_history_report(void)
1669{
1670 if (player_count() == 1) {
1671 return;
1672 }
1673
1674 if (game.server.scoreturn > game.info.turn) {
1675 return;
1676 }
1677
1678 game.server.scoreturn = (game.info.turn + GAME_DEFAULT_SCORETURN
1679 + fc_rand(GAME_DEFAULT_SCORETURN));
1680
1681 historian_generic(&latest_history_report, game.server.scoreturn
1682 % (HISTORIAN_LAST + 1));
1683 send_current_history_report(game.est_connections);
1684}
1685
1686/**********************************************************************/
1690 void report_final_scores(struct conn_list *dest)
1691{
1692 static const struct {
1693 const char *name;
1694 int (*score) (const struct player *);
1695 } score_categories[] = {
1696 { N_("Population\n"), get_real_pop },
1697 /* TRANS: "M goods" = million goods */
1698 { N_("Trade\n(M goods)"), get_economics },
1699 /* TRANS: "M tons" = million tons */
1700 { N_("Production\n(M tons)"), get_production },
1701 { N_("Cities\n"), get_cities },
1702 { N_("Technologies\n"), get_techs },
1703 { N_("Military Service\n(months)"), get_mil_service },
1704 { N_("Wonders\n"), get_wonders },
1705 { N_("Research Speed\n(bulbs)"), get_research },
1706 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1707 { N_("Land Area\n(sq. mi.)"), get_landarea },
1708 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1709 { N_("Settled Area\n(sq. mi.)"), get_settledarea },
1710 { N_("Literacy\n(%)"), get_literacy },
1711 { N_("Culture\n"), get_culture },
1712 { N_("Spaceship\n"), get_spaceship },
1713 { N_("Built Units\n"), get_units_built },
1714 { N_("Killed Units\n"), get_units_killed },
1715 { N_("Unit Losses\n"), get_units_lost },
1716 { N_("Units Used\n"), get_units_used },
1717 };
1718 const size_t score_categories_num = ARRAY_SIZE(score_categories);
1719
1720 int i, j;
1721 struct player_score_entry size[player_count()];
1722 struct packet_endgame_report packet;
1723
1724 fc_assert(score_categories_num <= ARRAY_SIZE(packet.category_name));
1725
1726 if (!dest) {
1727 dest = game.est_connections;
1728 }
1729
1730 packet.category_num = score_categories_num;
1731 for (j = 0; j < score_categories_num; j++) {
1732 sz_strlcpy(packet.category_name[j], score_categories[j].name);
1733 }
1734
1735 i = 0;
1736 players_iterate(pplayer) {
1737 if (!is_barbarian(pplayer)) {
1738 size[i].value = pplayer->score.game;
1739 size[i].player = pplayer;
1740 i++;
1741 }
1742 } players_iterate_end;
1743
1744 qsort(size, i, sizeof(size[0]), secompare);
1745
1746 packet.player_num = i;
1747
1748 lsend_packet_endgame_report(dest, &packet);
1749
1750 for (i = 0; i < packet.player_num; i++) {
1751 struct packet_endgame_player ppacket;
1752 const struct player *pplayer = size[i].player;
1753
1754 ppacket.category_num = score_categories_num;
1755 ppacket.player_id = player_number(pplayer);
1756 ppacket.score = size[i].value;
1757 for (j = 0; j < score_categories_num; j++) {
1758 ppacket.category_score[j] = score_categories[j].score(pplayer);
1759 }
1760
1761 ppacket.winner = pplayer->is_winner;
1762
1763 lsend_packet_endgame_player(dest, &ppacket);
1764 }
1765}
1766
1767/**********************************************************************/
1770 static void page_conn(struct conn_list *dest, const char *caption,
1771 const char *headline, const char *lines)
1772{
1773 page_conn_etype(dest, caption, headline, lines, E_REPORT);
1774}
1775
1776/**********************************************************************/
1787 static void page_conn_etype(struct conn_list *dest, const char *caption,
1788 const char *headline, const char *lines,
1789 enum event_type event)
1790{
1791 struct packet_page_msg packet;
1792 int i;
1793 int len;
1794
1795 sz_strlcpy(packet.caption, caption);
1796 sz_strlcpy(packet.headline, headline);
1797 packet.event = event;
1798 len = strlen(lines);
1799 if ((len % (MAX_LEN_CONTENT - 1)) == 0) {
1800 packet.parts = len / (MAX_LEN_CONTENT - 1);
1801 } else {
1802 packet.parts = len / (MAX_LEN_CONTENT - 1) + 1;
1803 }
1804 packet.len = len;
1805
1806 lsend_packet_page_msg(dest, &packet);
1807
1808 for (i = 0; i < packet.parts; i++) {
1809 struct packet_page_msg_part part;
1810 int plen;
1811
1812 plen = MIN(len, (MAX_LEN_CONTENT - 1));
1813 strncpy(part.lines, &(lines[(MAX_LEN_CONTENT - 1) * i]), plen);
1814 part.lines[plen] = '\0';
1815
1816 lsend_packet_page_msg_part(dest, &part);
1817
1818 len -= plen;
1819 }
1820}
1821
1822/**********************************************************************/
1825 struct history_report *history_report_get(void)
1826{
1827 return &latest_history_report;
1828}
achievement_player_has
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
Definition achievements.c:364
get_literacy
int get_literacy(const struct player *pplayer)
Definition achievements.c:386
achievement_name_translation
const char * achievement_name_translation(struct achievement *pach)
Definition achievements.c:106
achievements.h
achievements_iterate_end
#define achievements_iterate_end
Definition achievements.h:70
achievements_iterate
#define achievements_iterate(_ach_)
Definition achievements.h:64
bitvector.h
BV_DEFINE
#define BV_DEFINE(name, bits)
Definition bitvector.h:132
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
calendar_text
const char * calendar_text(void)
Definition calendar.c:141
calendar.h
city_improvement_name_translation
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:663
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1133
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:508
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
city_owner
#define city_owner(_pcity_)
Definition city.h:563
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:510
city_built_iterate
#define city_built_iterate(_pcity, _p)
Definition city.h:825
city_built_iterate_end
#define city_built_iterate_end
Definition city.h:831
citytools.h
incite_cost
char * incite_cost
Definition comments.c:74
MAX_LEN_CONTENT
#define MAX_LEN_CONTENT
Definition conn_types.h:32
connection.h
caption
const char * caption
Definition dialogs_g.h:37
headline
const char const char * headline
Definition dialogs_g.h:38
punit
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
event
enum event_type event
Definition events.c:81
events.h
MAX_LEN_GAME_IDENTIFIER
#define MAX_LEN_GAME_IDENTIFIER
Definition fc_types.h:71
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
O_TRADE
@ O_TRADE
Definition fc_types.h:101
get_internal_string_length
size_t get_internal_string_length(const char *text)
Definition fciconv.c:396
fciconv.h
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
N_
#define N_(String)
Definition fcintl.h:69
population_to_text
const char * population_to_text(int thousand_citizen)
Definition game.c:737
game
struct civ_game game
Definition game.c:61
game.h
GAME_DEFAULT_SCORETURN
#define GAME_DEFAULT_SCORETURN
Definition game.h:579
SL_HUMANS
@ SL_HUMANS
Definition game.h:69
SL_ALL
@ SL_ALL
Definition game.h:68
government_of_player
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
government_name_for_player
const char * government_name_for_player(const struct player *pplayer)
Definition government.c:154
government_number
Government_type_id government_number(const struct government *pgovern)
Definition government.c:91
government.h
great_wonder_is_destroyed
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
Definition improvement.c:993
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:772
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:243
city_from_great_wonder
struct city * city_from_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:1016
improvement_iterate_end
#define improvement_iterate_end
Definition improvement.h:205
improvement_iterate
#define improvement_iterate(_p)
Definition improvement.h:199
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_debug
#define log_debug(message,...)
Definition log.h:115
log_error
#define log_error(message,...)
Definition log.h:103
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
nation_adjective_for_player
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
nation.h
packets.h
lsend_packet_endgame_player
void lsend_packet_endgame_player(struct conn_list *dest, const struct packet_endgame_player *packet)
Definition packets_gen.c:2920
lsend_packet_endgame_report
void lsend_packet_endgame_report(struct conn_list *dest, const struct packet_endgame_report *packet)
Definition packets_gen.c:2709
lsend_packet_page_msg
void lsend_packet_page_msg(struct conn_list *dest, const struct packet_page_msg *packet)
Definition packets_gen.c:42969
lsend_packet_page_msg_part
void lsend_packet_page_msg_part(struct conn_list *dest, const struct packet_page_msg_part *packet)
Definition packets_gen.c:43161
lines
char * lines
Definition packhand.c:131
len
int len
Definition packhand.c:127
player_slot_is_used
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
player_count
int player_count(void)
Definition player.c:817
player_slot_count
int player_slot_count(void)
Definition player.c:418
player_number
int player_number(const struct player *pplayer)
Definition player.c:837
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:895
player_slot_index
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
team_has_embassy
bool team_has_embassy(const struct team *pteam, const struct player *tgt_player)
Definition player.c:220
player_index
int player_index(const struct player *pplayer)
Definition player.c:829
player_slot_get_player
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:539
players_iterate
#define players_iterate(_pplayer)
Definition player.h:534
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
player_slots_iterate
#define player_slots_iterate(_pslot)
Definition player.h:525
is_ai
#define is_ai(plr)
Definition player.h:232
player_slots_iterate_end
#define player_slots_iterate_end
Definition player.h:529
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:108
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:56
get_units_killed
static int get_units_killed(const struct player *pplayer)
Definition report.c:775
get_units_built
static int get_units_built(const struct player *pplayer)
Definition report.c:767
get_contentpop
static int get_contentpop(const struct player *pplayer)
Definition report.c:855
score_log
static struct logging_civ_score * score_log
Definition report.c:69
nr_wonders
static int nr_wonders(struct city *pcity)
Definition report.c:315
ranking
static const char * ranking[]
Definition report.c:197
report_final_scores
void report_final_scores(struct conn_list *dest)
Definition report.c:1690
economics_to_text
static const char * economics_to_text(int value)
Definition report.c:969
production_to_text
static const char * production_to_text(int value)
Definition report.c:957
get_munits
static int get_munits(const struct player *pplayer)
Definition report.c:698
science_to_text
static const char * science_to_text(int value)
Definition report.c:979
get_pollution
static int get_pollution(const struct player *pplayer)
Definition report.c:666
HISTORIAN_LAST
#define HISTORIAN_LAST
Definition report.c:91
get_economics
static int get_economics(const struct player *pplayer)
Definition report.c:658
get_techs
static int get_techs(const struct player *pplayer)
Definition report.c:690
plrdata_slot_init
static void plrdata_slot_init(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1220
page_conn_etype
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:1787
get_pop
static int get_pop(const struct player *pplayer)
Definition report.c:610
get_riots
static int get_riots(const struct player *pplayer)
Definition report.c:831
historian_generic
static void historian_generic(struct history_report *report, enum historian_type which_news)
Definition report.c:242
pollution_to_text
static const char * pollution_to_text(int value)
Definition report.c:997
plrdata_slot_replace
static void plrdata_slot_replace(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1232
get_production
static int get_production(const struct player *pplayer)
Definition report.c:650
latest_history_report
struct history_report latest_history_report
Definition report.c:67
scan_score_log
static bool scan_score_log(char *id)
Definition report.c:1258
get_scirate
static int get_scirate(const struct player *pplayer)
Definition report.c:815
get_taxrate
static int get_taxrate(const struct player *pplayer)
Definition report.c:807
send_current_history_report
void send_current_history_report(struct conn_list *dest)
Definition report.c:302
get_spaceship
static int get_spaceship(const struct player *pplayer)
Definition report.c:759
report_wonders_of_the_world
void report_wonders_of_the_world(struct conn_list *dest)
Definition report.c:525
dem_flag
dem_flag
Definition report.c:185
DEM_COL_BEST
@ DEM_COL_BEST
Definition report.c:188
DEM_COL_RANK
@ DEM_COL_RANK
Definition report.c:187
DEM_COL_QUANTITY
@ DEM_COL_QUANTITY
Definition report.c:186
DEM_COL_LAST
@ DEM_COL_LAST
Definition report.c:189
historian_type
historian_type
Definition report.c:83
HISTORIAN_LARGEST
@ HISTORIAN_LARGEST
Definition report.c:88
HISTORIAN_MILITARY
@ HISTORIAN_MILITARY
Definition report.c:86
HISTORIAN_ADVANCED
@ HISTORIAN_ADVANCED
Definition report.c:85
HISTORIAN_RICHEST
@ HISTORIAN_RICHEST
Definition report.c:84
HISTORIAN_HAPPIEST
@ HISTORIAN_HAPPIEST
Definition report.c:87
report_demographics
void report_demographics(struct connection *pconn)
Definition report.c:1126
historian_message
static const char * historian_message[]
Definition report.c:93
get_corruption
static int get_corruption(const struct player *pplayer)
Definition report.c:893
get_wonders
static int get_wonders(const struct player *pplayer)
Definition report.c:734
report_wonders_of_the_world_long
void report_wonders_of_the_world_long(struct conn_list *dest)
Definition report.c:414
get_landarea
static int get_landarea(const struct player *pplayer)
Definition report.c:626
get_total_score
static int get_total_score(const struct player *pplayer)
Definition report.c:907
area_to_text
static const char * area_to_text(int value)
Definition report.c:938
scorelog_magic
static const char scorelog_magic[]
Definition report.c:128
get_population
static int get_population(const struct player *pplayer)
Definition report.c:602
coltable
static struct dem_col coltable[]
get_units_used
static int get_units_used(const struct player *pplayer)
Definition report.c:791
historian_name
static const char * historian_name[]
Definition report.c:106
GOOD_PLAYER
#define GOOD_PLAYER(p)
Definition report.c:159
history_report_get
struct history_report * history_report_get(void)
Definition report.c:1825
make_history_report
void make_history_report(void)
Definition report.c:1668
log_civ_score_free
void log_civ_score_free(void)
Definition report.c:1435
get_culture
static int get_culture(const struct player *pplayer)
Definition report.c:915
value_units
static const char * value_units(int val, const char *uni)
Definition report.c:923
get_techout
static int get_techout(const struct player *pplayer)
Definition report.c:742
get_specialists
static int get_specialists(const struct player *pplayer)
Definition report.c:871
rowtable
static struct dem_row rowtable[]
get_unhappypop
static int get_unhappypop(const struct player *pplayer)
Definition report.c:863
is_valid_demography
bool is_valid_demography(const char *demography, int *error)
Definition report.c:1079
report_top_cities
void report_top_cities(struct conn_list *dest)
Definition report.c:331
get_settledarea
static int get_settledarea(const struct player *pplayer)
Definition report.c:634
log_civ_score_init
void log_civ_score_init(void)
Definition report.c:1412
get_literacy2
static int get_literacy2(const struct player *pplayer)
Definition report.c:751
dem_line_item
static void dem_line_item(char *outptr, size_t out_size, struct player *pplayer, struct dem_row *prow, bv_cols selcols)
Definition report.c:1015
culture_to_text
static const char * culture_to_text(int value)
Definition report.c:1006
get_mil_service
static int get_mil_service(const struct player *pplayer)
Definition report.c:674
report_achievements
void report_achievements(struct connection *pconn)
Definition report.c:1190
percent_to_text
static const char * percent_to_text(int value)
Definition report.c:948
secompare
static int secompare(const void *a, const void *b)
Definition report.c:233
get_happypop
static int get_happypop(const struct player *pplayer)
Definition report.c:847
plrdata_slot_free
static void plrdata_slot_free(struct plrdata_slot *plrdata)
Definition report.c:1243
page_conn
static void page_conn(struct conn_list *dest, const char *caption, const char *headline, const char *lines)
Definition report.c:1770
get_settlers
static int get_settlers(const struct player *pplayer)
Definition report.c:715
get_real_pop
static int get_real_pop(const struct player *pplayer)
Definition report.c:618
get_luxrate
static int get_luxrate(const struct player *pplayer)
Definition report.c:823
log_civ_score_now
void log_civ_score_now(void)
Definition report.c:1465
get_units_lost
static int get_units_lost(const struct player *pplayer)
Definition report.c:783
get_gold
static int get_gold(const struct player *pplayer)
Definition report.c:799
MAX_SCORELOG_LINE_LEN
#define MAX_SCORELOG_LINE_LEN
Definition report.c:126
get_cities
static int get_cities(const struct player *pplayer)
Definition report.c:682
mil_service_to_text
static const char * mil_service_to_text(int value)
Definition report.c:988
get_gov
static int get_gov(const struct player *pplayer)
Definition report.c:885
get_research
static int get_research(const struct player *pplayer)
Definition report.c:642
report.h
REPORT_BODYSIZE
#define REPORT_BODYSIZE
Definition report.h:23
REPORT_TITLESIZE
#define REPORT_TITLESIZE
Definition report.h:22
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:128
research.h
total_player_citizens
int total_player_citizens(const struct player *pplayer)
Definition score.c:382
score.h
compare_strings_strvec
int compare_strings_strvec(const char *const *first, const char *const *second)
Definition shared.c:383
int_to_text
const char * int_to_text(unsigned int number)
Definition shared.c:237
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
MAX
#define MAX(x, y)
Definition shared.h:54
specialist.h
specialist_type_iterate_end
#define specialist_type_iterate_end
Definition specialist.h:79
specialist_type_iterate
#define specialist_type_iterate(sp)
Definition specialist.h:73
size
size_t size
Definition specvec.h:72
srv_main.h
strvec_sort
void strvec_sort(struct strvec *psv, int(*sort_func)(const char *const *, const char *const *))
Definition string_vector.c:259
strvec_from_str
void strvec_from_str(struct strvec *psv, char separator, const char *str)
Definition string_vector.c:137
strvec_new
struct strvec * strvec_new(void)
Definition string_vector.c:59
strvec_remove_duplicate
void strvec_remove_duplicate(struct strvec *psv, int(*cmp_func)(const char *, const char *))
Definition string_vector.c:180
strvec_iterate
#define strvec_iterate(psv, str)
Definition string_vector.h:61
strvec_iterate_end
#define strvec_iterate_end
Definition string_vector.h:68
city_score_entry
Definition report.c:135
city_score_entry::value
int value
Definition report.c:137
city_score_entry::city
struct city * city
Definition report.c:136
city
Definition city.h:320
civ_game::scorefile
char scorefile[MAX_LEN_PATH]
Definition game.h:224
civ_game::demography
char demography[MAX_LEN_DEMOGRAPHY]
Definition game.h:240
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::scoreloglevel
enum scorelog_level scoreloglevel
Definition game.h:223
civ_game::start_year
int start_year
Definition game.h:191
civ_game::scoreturn
int scoreturn
Definition game.h:225
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civ_game::server
struct civ_game::@31::@35 server
civ_game::scorelog
bool scorelog
Definition game.h:222
connection
Definition connection.h:136
dem_col
Definition report.c:192
dem_col::key
char key
Definition report.c:193
dem_row
Definition report.c:164
dem_row::name
const char * name
Definition report.c:166
dem_row::get_value
int(* get_value)(const struct player *)
Definition report.c:167
dem_row::key
const char key
Definition report.c:165
dem_row::greater_values_are_better
bool greater_values_are_better
Definition report.c:169
history_report
Definition report.h:26
history_report::title
char title[REPORT_TITLESIZE]
Definition report.h:28
history_report::body
char body[REPORT_BODYSIZE]
Definition report.h:29
history_report::turn
int turn
Definition report.h:27
logging_civ_score
Definition report.c:59
logging_civ_score::last_turn
int last_turn
Definition report.c:61
logging_civ_score::fp
FILE * fp
Definition report.c:60
logging_civ_score::plrdata
struct plrdata_slot * plrdata
Definition report.c:62
packet_endgame_player
Definition packets_gen.h:93
packet_endgame_report
Definition packets_gen.h:87
packet_endgame_report::category_name
char category_name[32][MAX_LEN_NAME]
Definition packets_gen.h:89
packet_endgame_report::category_num
int category_num
Definition packets_gen.h:88
packet_endgame_report::player_num
int player_num
Definition packets_gen.h:90
packet_game_info::turn
int turn
Definition packets_gen.h:245
packet_game_info::year
int year
Definition packets_gen.h:247
packet_game_info::top_cities_count
int top_cities_count
Definition packets_gen.h:249
packet_page_msg_part
Definition packets_gen.h:845
packet_page_msg
Definition packets_gen.h:837
packet_page_msg::event
enum event_type event
Definition packets_gen.h:840
packet_page_msg::headline
char headline[MAX_LEN_MSG]
Definition packets_gen.h:839
packet_page_msg::parts
int parts
Definition packets_gen.h:842
packet_page_msg::caption
char caption[MAX_LEN_MSG]
Definition packets_gen.h:838
packet_page_msg::len
int len
Definition packets_gen.h:841
packet_scenario_info::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1597
part
Definition goto.c:52
player_economic::luxury
int luxury
Definition player.h:66
player_economic::science
int science
Definition player.h:65
player_economic::tax
int tax
Definition player.h:64
player_economic::gold
int gold
Definition player.h:63
player_score_entry
Definition report.c:130
player_score_entry::player
const struct player * player
Definition report.c:131
player_score_entry::value
int value
Definition report.c:132
player_score::units_killed
int units_killed
Definition player.h:105
player_score::landarea
int landarea
Definition player.h:94
player_score::mfg
int mfg
Definition player.h:102
player_score::population
int population
Definition player.h:96
player_score::pollution
int pollution
Definition player.h:99
player_score::wonders
int wonders
Definition player.h:91
player_score::settledarea
int settledarea
Definition player.h:95
player_score::units_used
int units_used
Definition player.h:108
player_score::specialists
int specialists[SP_MAX]
Definition player.h:90
player_score::units_lost
int units_lost
Definition player.h:106
player_score::techout
int techout
Definition player.h:93
player_score::game
int game
Definition player.h:110
player_score::units
int units
Definition player.h:98
player_score::units_built
int units_built
Definition player.h:104
player_score::content
int content
Definition player.h:87
player_score::happy
int happy
Definition player.h:86
player_score::spaceship
int spaceship
Definition player.h:103
player_score::culture
int culture
Definition player.h:109
player_score::unhappy
int unhappy
Definition player.h:88
player_score::cities
int cities
Definition player.h:97
player_score::bnp
int bnp
Definition player.h:101
player_score::literacy
int literacy
Definition player.h:100
player_score::techs
int techs
Definition player.h:92
player
Definition player.h:249
player::cities
struct city_list * cities
Definition player.h:281
player::is_winner
bool is_winner
Definition player.h:269
player::team
struct team * team
Definition player.h:261
player::units
struct unit_list * units
Definition player.h:282
player::is_alive
bool is_alive
Definition player.h:268
player::economic
struct player_economic economic
Definition player.h:284
player::score
struct player_score score
Definition player.h:283
plrdata_slot
Definition report.c:55
plrdata_slot::name
char * name
Definition report.c:56
research::future_tech
int future_tech
Definition research.h:42
server
Definition servers.h:29
strvec
Definition string_vector.c:29
team
Definition team.c:40
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
fc_strlcat
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:822
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
fc_fopen
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:505
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
sz_strlcat
#define sz_strlcat(dest, src)
Definition support.h:190
fc_strncmp
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:154
fc__fallthrough
#define fc__fallthrough
Definition support.h:119
team_count
int team_count(void)
Definition team.c:375
team_pretty_name
int team_pretty_name(const struct team *pteam, char *buf, size_t buf_len)
Definition team.c:432
best_value
static int best_value(const void *a, const void *b)
Definition traderoutes.c:400
unit_can_do_action
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:386
is_special_unit
bool is_special_unit(const struct unit *punit)
Definition unit.c:353
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
version.h