Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/report.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
report.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <string.h>
20
21/* utility */
22#include "bitvector.h"
23#include "fciconv.h"
24#include "fcintl.h"
25#include "log.h"
26#include "mem.h"
27#include "rand.h"
28#include "support.h"
29
30/* common */
31#include "achievements.h"
32#include "calendar.h"
33#include "connection.h"
34#include "events.h"
35#include "game.h"
36#include "government.h"
37#include "nation.h"
38#include "packets.h"
39#include "player.h"
40#include "research.h"
41#include "specialist.h"
42#include "unitlist.h"
43#include "version.h"
44
45/* server */
46#include "citytools.h"
47#include "plrhand.h"
48#include "score.h"
49#include "srv_main.h"
50
51#include "report.h"
52
53
54/* data needed for logging civ score */
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 = NULL;
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 = NULL;
344 }
345
346 shuffled_players_iterate(pplayer) {
347 city_list_iterate(pplayer->cities, pcity) {
348 int value_of_pcity = city_size_get(pcity)
349 + nr_wonders(pcity) * WONDER_FACTOR;
350
351 if (value_of_pcity > size[game.info.top_cities_count - 1].value) {
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 == NULL) {
364 /*
365 * There are less than game.info.top_cities_count cities in
366 * the whole game.
367 */
368 break;
369 }
370
371 if (player_count() > team_count()) {
372 /* There exists a team with more than one member. */
373 char team_name[2 * MAX_LEN_NAME];
374
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 /* TRANS: "M tons" = million tons, so always plural */
961 return value_units(clip, PL_(" M tons", " M tons", clip));
962}
963
964/**********************************************************************/
968 static const char *economics_to_text(int value)
969{
970 /* TRANS: "M goods" = million goods, so always plural */
971 return value_units(value, PL_(" M goods", " M goods", value));
972}
973
974/**********************************************************************/
978 static const char *science_to_text(int value)
979{
980 return value_units(value, PL_(" bulb", " bulbs", value));
981}
982
983/**********************************************************************/
987 static const char *mil_service_to_text(int value)
988{
989 return value_units(value, PL_(" month", " months", value));
990}
991
992/**********************************************************************/
996 static const char *pollution_to_text(int value)
997{
998 return value_units(value, PL_(" ton", " tons", value));
999}
1000
1001/**********************************************************************/
1005 static const char *culture_to_text(int value)
1006{
1007 /* TRANS: Unit(s) of culture */
1008 return value_units(value, PL_(" point", " points", value));
1009}
1010
1011/**********************************************************************/
1014 static void dem_line_item(char *outptr, size_t out_size,
1015 struct player *pplayer, struct dem_row *prow,
1016 bv_cols selcols)
1017{
1018 if (NULL != pplayer && BV_ISSET(selcols, DEM_COL_QUANTITY)) {
1019 const char *text = prow->to_text(prow->get_value(pplayer));
1020
1021 cat_snprintf(outptr, out_size, " %s", text);
1022 cat_snprintf(outptr, out_size, "%*s",
1023 18 - (int) get_internal_string_length(text), "");
1024 }
1025
1026 if (NULL != pplayer && BV_ISSET(selcols, DEM_COL_RANK)) {
1027 int basis = prow->get_value(pplayer);
1028 int place = 1;
1029
1030 players_iterate(other) {
1031 if (GOOD_PLAYER(other)
1032 && ((prow->greater_values_are_better
1033 && prow->get_value(other) > basis)
1034 || (!prow->greater_values_are_better
1035 && prow->get_value(other) < basis))) {
1036 place++;
1037 }
1038 } players_iterate_end;
1039
1040 cat_snprintf(outptr, out_size, _("(ranked %d)"), place);
1041 }
1042
1043 if (NULL == pplayer || BV_ISSET(selcols, DEM_COL_BEST)) {
1044 struct player *best_player = pplayer;
1045 int best_value = NULL != pplayer ? prow->get_value(pplayer) : 0;
1046
1047 players_iterate(other) {
1048 if (GOOD_PLAYER(other)) {
1049 int value = prow->get_value(other);
1050
1051 if (!best_player
1052 || (prow->greater_values_are_better && value > best_value)
1053 || (!prow->greater_values_are_better && value < best_value)) {
1054 best_player = other;
1055 best_value = value;
1056 }
1057 }
1058 } players_iterate_end;
1059
1060 if (NULL == pplayer
1061 || (team_has_embassy(pplayer->team, best_player)
1062 && (pplayer != best_player))) {
1063 cat_snprintf(outptr, out_size, " %s: %s",
1064 nation_plural_for_player(best_player),
1065 prow->to_text(prow->get_value(best_player)));
1066 }
1067 }
1068}
1069
1070/**********************************************************************/
1078 bool is_valid_demography(const char *demography, int *error)
1079{
1080 int len = strlen(demography), i;
1081
1082 /* We check each character individually to see if it's valid. This
1083 * does not check for duplicate entries. */
1084 for (i = 0; i < len; i++) {
1085 bool found = FALSE;
1086 int j;
1087
1088 /* See if the character is a valid column label. */
1089 for (j = 0; j < DEM_COL_LAST; j++) {
1090 if (demography[i] == coltable[j].key) {
1091 found = TRUE;
1092 break;
1093 }
1094 }
1095
1096 if (found) {
1097 continue;
1098 }
1099
1100 /* See if the character is a valid row label. */
1101 for (j = 0; j < ARRAY_SIZE(rowtable); j++) {
1102 if (demography[i] == rowtable[j].key) {
1103 found = TRUE;
1104 break;
1105 }
1106 }
1107
1108 if (!found) {
1109 if (error != NULL) {
1110 (*error) = i;
1111 }
1112 /* The character is invalid. */
1113 return FALSE;
1114 }
1115 }
1116
1117 /* Looks like all characters were valid. */
1118 return TRUE;
1119}
1120
1121/**********************************************************************/
1125 void report_demographics(struct connection *pconn)
1126{
1127 char civbuf[1024];
1128 char buffer[4096];
1129 int i;
1130 bool anyrows;
1131 bv_cols selcols;
1132 int numcols = 0;
1133 struct player *pplayer = pconn->playing;
1134
1135 BV_CLR_ALL(selcols);
1136 fc_assert_ret(ARRAY_SIZE(coltable) == DEM_COL_LAST);
1137 for (i = 0; i < DEM_COL_LAST; i++) {
1138 if (strchr(game.server.demography, coltable[i].key)) {
1139 BV_SET(selcols, i);
1140 numcols++;
1141 }
1142 }
1143
1144 anyrows = FALSE;
1145 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1146 if (strchr(game.server.demography, rowtable[i].key)) {
1147 anyrows = TRUE;
1148 break;
1149 }
1150 }
1151
1152 if ((!pconn->observer && !pplayer)
1153 || (pplayer && !pplayer->is_alive)
1154 || !anyrows
1155 || numcols == 0) {
1156 page_conn(pconn->self, _("Demographics Report:"),
1157 _("Sorry, the Demographics report is unavailable."), "");
1158 return;
1159 }
1160
1161 if (pplayer) {
1162 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1163 nation_adjective_for_player(pplayer),
1164 government_name_for_player(pplayer),
1165 calendar_text());
1166 } else {
1167 civbuf[0] = '\0';
1168 }
1169
1170 buffer[0] = '\0';
1171 for (i = 0; i < ARRAY_SIZE(rowtable); i++) {
1172 if (strchr(game.server.demography, rowtable[i].key)) {
1173 const char *name = Q_(rowtable[i].name);
1174
1175 cat_snprintf(buffer, sizeof(buffer), "%s", name);
1176 cat_snprintf(buffer, sizeof(buffer), "%*s",
1177 18 - (int) get_internal_string_length(name), "");
1178 dem_line_item(buffer, sizeof(buffer), pplayer, &rowtable[i], selcols);
1179 sz_strlcat(buffer, "\n");
1180 }
1181 }
1182
1183 page_conn(pconn->self, _("Demographics Report:"), civbuf, buffer);
1184}
1185
1186/**********************************************************************/
1189 void report_achievements(struct connection *pconn)
1190{
1191 char civbuf[1024];
1192 char buffer[4096];
1193 struct player *pplayer = pconn->playing;
1194
1195 if (pplayer == NULL) {
1196 return;
1197 }
1198
1199 fc_snprintf(civbuf, sizeof(civbuf), _("%s %s (%s)"),
1200 nation_adjective_for_player(pplayer),
1201 government_name_for_player(pplayer),
1202 calendar_text());
1203
1204 buffer[0] = '\0';
1205
1206 achievements_iterate(pach) {
1207 if (achievement_player_has(pach, pplayer)) {
1208 cat_snprintf(buffer, sizeof(buffer), "%s\n",
1209 achievement_name_translation(pach));
1210 }
1211 } achievements_iterate_end;
1212
1213 page_conn(pconn->self, _("Achievements List:"), civbuf, buffer);
1214}
1215
1216/**********************************************************************/
1219 static void plrdata_slot_init(struct plrdata_slot *plrdata,
1220 const char *name)
1221{
1222 fc_assert_ret(plrdata->name == NULL);
1223
1224 plrdata->name = fc_calloc(MAX_LEN_NAME, sizeof(plrdata->name));
1225 plrdata_slot_replace(plrdata, name);
1226}
1227
1228/**********************************************************************/
1231 static void plrdata_slot_replace(struct plrdata_slot *plrdata,
1232 const char *name)
1233{
1234 fc_assert_ret(plrdata->name != NULL);
1235
1236 fc_strlcpy(plrdata->name, name, MAX_LEN_NAME);
1237}
1238
1239/**********************************************************************/
1242 static void plrdata_slot_free(struct plrdata_slot *plrdata)
1243{
1244 if (plrdata->name != NULL) {
1245 free(plrdata->name);
1246 plrdata->name = NULL;
1247 }
1248}
1249
1250/**********************************************************************/
1257 static bool scan_score_log(char *id)
1258{
1259 int line_nr, turn, plr_no, spaces;
1260 struct plrdata_slot *plrdata;
1261 char line[MAX_SCORELOG_LINE_LEN], *ptr;
1262
1263 /* Must be big enough to contain any string there might be in "addplayer" line
1264 * to read.
1265 * Could have even strlen("addplayer 0 0 "), but maintenance not worth
1266 * saving couple of bytes. */
1267 char plr_name[MAX(MAX_LEN_NAME, MAX_SCORELOG_LINE_LEN - strlen("addplayer "))];
1268
1269 fc_assert_ret_val(score_log != NULL, FALSE);
1270 fc_assert_ret_val(score_log->fp != NULL, FALSE);
1271
1272 score_log->last_turn = -1;
1273 id[0] = '\0';
1274
1275 for (line_nr = 1;; line_nr++) {
1276 if (!fgets(line, sizeof(line), score_log->fp)) {
1277 if (feof(score_log->fp) != 0) {
1278 break;
1279 }
1280 log_error("[%s:-] Can't read scorelog file header!",
1281 game.server.scorefile);
1282 return FALSE;
1283 }
1284
1285 ptr = strchr(line, '\n');
1286 if (!ptr) {
1287 log_error("[%s:%d] Line too long!", game.server.scorefile, line_nr);
1288 return FALSE;
1289 }
1290 *ptr = '\0';
1291
1292 if (line_nr == 1) {
1293 if (fc_strncmp(line, scorelog_magic, strlen(scorelog_magic))) {
1294 log_error("[%s:%d] Bad file magic!", game.server.scorefile, line_nr);
1295 return FALSE;
1296 }
1297 }
1298
1299 if (!fc_strncmp(line, "id ", strlen("id "))) {
1300 if (strlen(id) > 0) {
1301 log_error("[%s:%d] Multiple ID entries!", game.server.scorefile,
1302 line_nr);
1303 return FALSE;
1304 }
1305 fc_strlcpy(id, line + strlen("id "), MAX_LEN_GAME_IDENTIFIER);
1306 if (strcmp(id, server.game_identifier) != 0) {
1307 log_error("[%s:%d] IDs don't match! game='%s' scorelog='%s'",
1308 game.server.scorefile, line_nr, server.game_identifier,
1309 id);
1310 return FALSE;
1311 }
1312 }
1313
1314 if (!fc_strncmp(line, "turn ", strlen("turn "))) {
1315 if (sscanf(line + strlen("turn "), "%d", &turn) != 1) {
1316 log_error("[%s:%d] Bad line (turn)!", game.server.scorefile,
1317 line_nr);
1318 return FALSE;
1319 }
1320
1321 fc_assert_ret_val(turn > score_log->last_turn, FALSE);
1322 score_log->last_turn = turn;
1323 }
1324
1325 if (!fc_strncmp(line, "addplayer ", strlen("addplayer "))) {
1326 /* If you change this, be sure to adjust plr_name buffer size to
1327 * match longest possible string read. */
1328 if (3 != sscanf(line + strlen("addplayer "), "%d %d %s",
1329 &turn, &plr_no, plr_name)) {
1330 log_error("[%s:%d] Bad line (addplayer)!",
1331 game.server.scorefile, line_nr);
1332 return FALSE;
1333 }
1334
1335 /* Now get the complete player name if there are several parts. */
1336 ptr = line + strlen("addplayer ");
1337 spaces = 0;
1338 while (*ptr != '\0' && spaces < 2) {
1339 if (*ptr == ' ') {
1340 spaces++;
1341 }
1342 ptr++;
1343 }
1344 fc_snprintf(plr_name, sizeof(plr_name), "%s", ptr);
1345 log_debug("add player '%s' (from line %d: '%s')", plr_name, line_nr,
1346 line);
1347
1348 if (0 > plr_no || plr_no >= player_slot_count()) {
1349 log_error("[%s:%d] Invalid player number: %d!",
1350 game.server.scorefile, line_nr, plr_no);
1351 return FALSE;
1352 }
1353
1354 plrdata = score_log->plrdata + plr_no;
1355 if (plrdata->name != NULL) {
1356 log_error("[%s:%d] Two names for one player (id %d)!",
1357 game.server.scorefile, line_nr, plr_no);
1358 return FALSE;
1359 }
1360
1361 plrdata_slot_init(plrdata, plr_name);
1362 }
1363
1364 if (!fc_strncmp(line, "delplayer ", strlen("delplayer "))) {
1365 if (2 != sscanf(line + strlen("delplayer "), "%d %d",
1366 &turn, &plr_no)) {
1367 log_error("[%s:%d] Bad line (delplayer)!",
1368 game.server.scorefile, line_nr);
1369 return FALSE;
1370 }
1371
1372 if (!(plr_no >= 0 && plr_no < player_slot_count())) {
1373 log_error("[%s:%d] Invalid player number: %d!",
1374 game.server.scorefile, line_nr, plr_no);
1375 return FALSE;
1376 }
1377
1378 plrdata = score_log->plrdata + plr_no;
1379 if (plrdata->name == NULL) {
1380 log_error("[%s:%d] Trying to remove undefined player (id %d)!",
1381 game.server.scorefile, line_nr, plr_no);
1382 return FALSE;
1383 }
1384
1385 plrdata_slot_free(plrdata);
1386 }
1387 }
1388
1389 if (score_log->last_turn == -1) {
1390 log_error("[%s:-] Scorelog contains no turn!", game.server.scorefile);
1391 return FALSE;
1392 }
1393
1394 if (strlen(id) == 0) {
1395 log_error("[%s:-] Scorelog contains no ID!", game.server.scorefile);
1396 return FALSE;
1397 }
1398
1399 if (score_log->last_turn + 1 != game.info.turn) {
1400 log_error("[%s:-] Scorelog doesn't match savegame!",
1401 game.server.scorefile);
1402 return FALSE;
1403 }
1404
1405 return TRUE;
1406}
1407
1408/**********************************************************************/
1411 void log_civ_score_init(void)
1412{
1413 if (score_log != NULL) {
1414 return;
1415 }
1416
1417 score_log = fc_calloc(1, sizeof(*score_log));
1418 score_log->fp = NULL;
1419 score_log->last_turn = -1;
1420 score_log->plrdata = fc_calloc(player_slot_count(),
1421 sizeof(*score_log->plrdata));
1422 player_slots_iterate(pslot) {
1423 struct plrdata_slot *plrdata = score_log->plrdata
1424 + player_slot_index(pslot);
1425 plrdata->name = NULL;
1426 } player_slots_iterate_end;
1427
1428 latest_history_report.turn = -2;
1429}
1430
1431/**********************************************************************/
1434 void log_civ_score_free(void)
1435{
1436 if (!score_log) {
1437 /* nothing to do */
1438 return;
1439 }
1440
1441 if (score_log->fp) {
1442 fclose(score_log->fp);
1443 score_log->fp = NULL;
1444 }
1445
1446 if (score_log->plrdata) {
1447 player_slots_iterate(pslot) {
1448 struct plrdata_slot *plrdata = score_log->plrdata
1449 + player_slot_index(pslot);
1450 if (plrdata->name != NULL) {
1451 free(plrdata->name);
1452 }
1453 } player_slots_iterate_end;
1454 free(score_log->plrdata);
1455 }
1456
1457 free(score_log);
1458 score_log = NULL;
1459}
1460
1461/**********************************************************************/
1464 void log_civ_score_now(void)
1465{
1466 enum { SL_CREATE, SL_APPEND, SL_UNSPEC } oper = SL_UNSPEC;
1467 char id[MAX_LEN_GAME_IDENTIFIER];
1468 int i = 0;
1469
1470 /* Add new tags only at end of this list. Maintaining the order of
1471 * old tags is critical. */
1472 static const struct {
1473 char *name;
1474 int (*get_value) (const struct player *);
1475 } score_tags[] = {
1476 {"pop", get_pop},
1477 {"bnp", get_economics},
1478 {"mfg", get_production},
1479 {"cities", get_cities},
1480 {"techs", get_techs},
1481 {"munits", get_munits},
1482 {"settlers", get_settlers}, /* "original" tags end here */
1483
1484 {"wonders", get_wonders},
1485 {"techout", get_techout},
1486 {"landarea", get_landarea},
1487 {"settledarea", get_settledarea},
1488 {"pollution", get_pollution},
1489 {"literacy", get_literacy2},
1490 {"spaceship", get_spaceship}, /* new 1.8.2 tags end here */
1491
1492 {"gold", get_gold},
1493 {"taxrate", get_taxrate},
1494 {"scirate", get_scirate},
1495 {"luxrate", get_luxrate},
1496 {"riots", get_riots},
1497 {"happypop", get_happypop},
1498 {"contentpop", get_contentpop},
1499 {"unhappypop", get_unhappypop},
1500 {"specialists", get_specialists},
1501 {"gov", get_gov},
1502 {"corruption", get_corruption}, /* new 1.11.5 tags end here */
1503
1504 {"score", get_total_score}, /* New 2.1.10 tag end here. */
1505
1506 {"unitsbuilt", get_units_built}, /* New tags since 2.3.0. */
1507 {"unitskilled", get_units_killed},
1508 {"unitslost", get_units_lost},
1509
1510 {"culture", get_culture}, /* New tag in 2.6.0. */
1511
1512 {"unitsused", get_units_used} /* New tag in 3.2.0. */
1513 };
1514
1515 if (!game.server.scorelog) {
1516 return;
1517 }
1518
1519 if (!score_log) {
1520 return;
1521 }
1522
1523 if (!score_log->fp) {
1524 if (game.info.year == game.server.start_year) {
1525 oper = SL_CREATE;
1526 } else {
1527 score_log->fp = fc_fopen(game.server.scorefile, "r");
1528 if (!score_log->fp) {
1529 oper = SL_CREATE;
1530 } else {
1531 if (!scan_score_log(id)) {
1532 goto log_civ_score_disable;
1533 }
1534 oper = SL_APPEND;
1535
1536 fclose(score_log->fp);
1537 score_log->fp = NULL;
1538 }
1539 }
1540
1541 switch (oper) {
1542 case SL_CREATE:
1543 score_log->fp = fc_fopen(game.server.scorefile, "w");
1544 if (!score_log->fp) {
1545 log_error("Can't open scorelog file '%s' for creation!",
1546 game.server.scorefile);
1547 goto log_civ_score_disable;
1548 }
1549 fprintf(score_log->fp, "%s%s\n", scorelog_magic, VERSION_STRING);
1550 fprintf(score_log->fp,
1551 "\n"
1552 "# For a specification of the format of this see doc/README.scorelog or \n"
1553 "# <https://raw.githubusercontent.com/freeciv/freeciv/S3_2/doc/README.scorelog>.\n"
1554 "\n");
1555
1556 fprintf(score_log->fp, "id %s\n", server.game_identifier);
1557 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1558 fprintf(score_log->fp, "tag %d %s\n", i, score_tags[i].name);
1559 }
1560 break;
1561 case SL_APPEND:
1562 score_log->fp = fc_fopen(game.server.scorefile, "a");
1563 if (!score_log->fp) {
1564 log_error("Can't open scorelog file '%s' for appending!",
1565 game.server.scorefile);
1566 goto log_civ_score_disable;
1567 }
1568 break;
1569 default:
1570 log_error("[%s] bad operation %d", __FUNCTION__, (int) oper);
1571 goto log_civ_score_disable;
1572 }
1573 }
1574
1575 if (game.info.turn > score_log->last_turn) {
1576 fprintf(score_log->fp, "turn %d %d %s\n", game.info.turn, game.info.year,
1577 calendar_text());
1578 score_log->last_turn = game.info.turn;
1579 }
1580
1581 player_slots_iterate(pslot) {
1582 struct plrdata_slot *plrdata = score_log->plrdata
1583 + player_slot_index(pslot);
1584 if (plrdata->name != NULL
1585 && player_slot_is_used(pslot)) {
1586 struct player *pplayer = player_slot_get_player(pslot);
1587
1588 if (!GOOD_PLAYER(pplayer)) {
1589 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1590 player_number(pplayer));
1591 plrdata_slot_free(plrdata);
1592 }
1593 }
1594 } player_slots_iterate_end;
1595
1596 players_iterate(pplayer) {
1597 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1598
1599 if (plrdata->name == NULL && GOOD_PLAYER(pplayer)) {
1600 switch (game.server.scoreloglevel) {
1601 case SL_HUMANS:
1602 if (is_ai(pplayer)) {
1603 break;
1604 }
1605
1606 fc__fallthrough; /* No break - continue to actual implementation
1607 * in SL_ALL case if reached here */
1608 case SL_ALL:
1609 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1610 player_number(pplayer), player_name(pplayer));
1611 plrdata_slot_init(plrdata, player_name(pplayer));
1612 }
1613 }
1614 } players_iterate_end;
1615
1616 players_iterate(pplayer) {
1617 struct plrdata_slot *plrdata = score_log->plrdata + player_index(pplayer);
1618
1619 if (GOOD_PLAYER(pplayer)) {
1620 switch (game.server.scoreloglevel) {
1621 case SL_HUMANS:
1622 if (is_ai(pplayer) && plrdata->name == NULL) {
1623 /* If a human player toggled into AI mode, don't break. */
1624 break;
1625 }
1626
1627 fc__fallthrough; /* No break - continue to actual implementation
1628 * in SL_ALL case if reached here */
1629 case SL_ALL:
1630 if (strcmp(plrdata->name, player_name(pplayer)) != 0) {
1631 log_debug("player names does not match '%s' != '%s'", plrdata->name,
1632 player_name(pplayer));
1633 fprintf(score_log->fp, "delplayer %d %d\n", game.info.turn - 1,
1634 player_number(pplayer));
1635 fprintf(score_log->fp, "addplayer %d %d %s\n", game.info.turn,
1636 player_number(pplayer), player_name(pplayer));
1637 plrdata_slot_replace(plrdata, player_name(pplayer));
1638 }
1639 }
1640 }
1641 } players_iterate_end;
1642
1643 for (i = 0; i < ARRAY_SIZE(score_tags); i++) {
1644 players_iterate(pplayer) {
1645 if (!GOOD_PLAYER(pplayer)
1646 || (game.server.scoreloglevel == SL_HUMANS && is_ai(pplayer))) {
1647 continue;
1648 }
1649
1650 fprintf(score_log->fp, "data %d %d %d %d\n", game.info.turn, i,
1651 player_number(pplayer), score_tags[i].get_value(pplayer));
1652 } players_iterate_end;
1653 }
1654
1655 fflush(score_log->fp);
1656
1657 return;
1658
1659 log_civ_score_disable:
1660
1661 log_civ_score_free();
1662}
1663
1664/**********************************************************************/
1667 void make_history_report(void)
1668{
1669 if (player_count() == 1) {
1670 return;
1671 }
1672
1673 if (game.server.scoreturn > game.info.turn) {
1674 return;
1675 }
1676
1677 game.server.scoreturn = (game.info.turn + GAME_DEFAULT_SCORETURN
1678 + fc_rand(GAME_DEFAULT_SCORETURN));
1679
1680 historian_generic(&latest_history_report, game.server.scoreturn
1681 % (HISTORIAN_LAST + 1));
1682 send_current_history_report(game.est_connections);
1683}
1684
1685/**********************************************************************/
1689 void report_final_scores(struct conn_list *dest)
1690{
1691 static const struct {
1692 const char *name;
1693 int (*score) (const struct player *);
1694 } score_categories[] = {
1695 { N_("Population\n"), get_real_pop },
1696 /* TRANS: "M goods" = million goods */
1697 { N_("Trade\n(M goods)"), get_economics },
1698 /* TRANS: "M tons" = million tons */
1699 { N_("Production\n(M tons)"), get_production },
1700 { N_("Cities\n"), get_cities },
1701 { N_("Technologies\n"), get_techs },
1702 { N_("Military Service\n(months)"), get_mil_service },
1703 { N_("Wonders\n"), get_wonders },
1704 { N_("Research Speed\n(bulbs)"), get_research },
1705 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1706 { N_("Land Area\n(sq. mi.)"), get_landarea },
1707 /* TRANS: "sq. mi." is abbreviation for "square miles" */
1708 { N_("Settled Area\n(sq. mi.)"), get_settledarea },
1709 { N_("Literacy\n(%)"), get_literacy },
1710 { N_("Culture\n"), get_culture },
1711 { N_("Spaceship\n"), get_spaceship },
1712 { N_("Built Units\n"), get_units_built },
1713 { N_("Killed Units\n"), get_units_killed },
1714 { N_("Unit Losses\n"), get_units_lost },
1715 { N_("Units Used\n"), get_units_used },
1716 };
1717 const size_t score_categories_num = ARRAY_SIZE(score_categories);
1718
1719 int i, j;
1720 struct player_score_entry size[player_count()];
1721 struct packet_endgame_report packet;
1722
1723 fc_assert(score_categories_num <= ARRAY_SIZE(packet.category_name));
1724
1725 if (!dest) {
1726 dest = game.est_connections;
1727 }
1728
1729 packet.category_num = score_categories_num;
1730 for (j = 0; j < score_categories_num; j++) {
1731 sz_strlcpy(packet.category_name[j], score_categories[j].name);
1732 }
1733
1734 i = 0;
1735 players_iterate(pplayer) {
1736 if (!is_barbarian(pplayer)) {
1737 size[i].value = pplayer->score.game;
1738 size[i].player = pplayer;
1739 i++;
1740 }
1741 } players_iterate_end;
1742
1743 qsort(size, i, sizeof(size[0]), secompare);
1744
1745 packet.player_num = i;
1746
1747 lsend_packet_endgame_report(dest, &packet);
1748
1749 for (i = 0; i < packet.player_num; i++) {
1750 struct packet_endgame_player ppacket;
1751 const struct player *pplayer = size[i].player;
1752
1753 ppacket.category_num = score_categories_num;
1754 ppacket.player_id = player_number(pplayer);
1755 ppacket.score = size[i].value;
1756 for (j = 0; j < score_categories_num; j++) {
1757 ppacket.category_score[j] = score_categories[j].score(pplayer);
1758 }
1759
1760 ppacket.winner = pplayer->is_winner;
1761
1762 lsend_packet_endgame_player(dest, &ppacket);
1763 }
1764}
1765
1766/**********************************************************************/
1769 static void page_conn(struct conn_list *dest, const char *caption,
1770 const char *headline, const char *lines)
1771{
1772 page_conn_etype(dest, caption, headline, lines, E_REPORT);
1773}
1774
1775/**********************************************************************/
1786 static void page_conn_etype(struct conn_list *dest, const char *caption,
1787 const char *headline, const char *lines,
1788 enum event_type event)
1789{
1790 struct packet_page_msg packet;
1791 int i;
1792 int len;
1793
1794 sz_strlcpy(packet.caption, caption);
1795 sz_strlcpy(packet.headline, headline);
1796 packet.event = event;
1797 len = strlen(lines);
1798 if ((len % (MAX_LEN_CONTENT - 1)) == 0) {
1799 packet.parts = len / (MAX_LEN_CONTENT - 1);
1800 } else {
1801 packet.parts = len / (MAX_LEN_CONTENT - 1) + 1;
1802 }
1803 packet.len = len;
1804
1805 lsend_packet_page_msg(dest, &packet);
1806
1807 for (i = 0; i < packet.parts; i++) {
1808 struct packet_page_msg_part part;
1809 int plen;
1810
1811 plen = MIN(len, (MAX_LEN_CONTENT - 1));
1812 strncpy(part.lines, &(lines[(MAX_LEN_CONTENT - 1) * i]), plen);
1813 part.lines[plen] = '\0';
1814
1815 lsend_packet_page_msg_part(dest, &part);
1816
1817 len -= plen;
1818 }
1819}
1820
1821/**********************************************************************/
1824 struct history_report *history_report_get(void)
1825{
1826 return &latest_history_report;
1827}
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:662
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1128
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:822
city_built_iterate_end
#define city_built_iterate_end
Definition city.h:828
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:395
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:732
game
struct civ_game game
Definition game.c:62
game.h
GAME_DEFAULT_SCORETURN
#define GAME_DEFAULT_SCORETURN
Definition game.h:578
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:3147
lsend_packet_endgame_report
void lsend_packet_endgame_report(struct conn_list *dest, const struct packet_endgame_report *packet)
Definition packets_gen.c:2975
lsend_packet_page_msg
void lsend_packet_page_msg(struct conn_list *dest, const struct packet_page_msg *packet)
Definition packets_gen.c:36664
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:36837
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:537
players_iterate
#define players_iterate(_pplayer)
Definition player.h:532
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
player_slots_iterate
#define player_slots_iterate(_pslot)
Definition player.h:523
is_ai
#define is_ai(plr)
Definition player.h:230
player_slots_iterate_end
#define player_slots_iterate_end
Definition player.h:527
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:1689
economics_to_text
static const char * economics_to_text(int value)
Definition report.c:968
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:978
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:1219
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:1786
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:996
plrdata_slot_replace
static void plrdata_slot_replace(struct plrdata_slot *plrdata, const char *name)
Definition report.c:1231
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:1257
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:1125
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:1824
make_history_report
void make_history_report(void)
Definition report.c:1667
log_civ_score_free
void log_civ_score_free(void)
Definition report.c:1434
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:1078
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:1411
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:1014
culture_to_text
static const char * culture_to_text(int value)
Definition report.c:1005
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:1189
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:1242
page_conn
static void page_conn(struct conn_list *dest, const char *caption, const char *headline, const char *lines)
Definition report.c:1769
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:1464
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:987
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:379
int_to_text
const char * int_to_text(unsigned int number)
Definition shared.c:234
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:258
strvec_from_str
void strvec_from_str(struct strvec *psv, char separator, const char *str)
Definition string_vector.c:136
strvec_new
struct strvec * strvec_new(void)
Definition string_vector.c:58
strvec_remove_duplicate
void strvec_remove_duplicate(struct strvec *psv, int(*cmp_func)(const char *, const char *))
Definition string_vector.c:179
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:239
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:91
packet_endgame_report
Definition packets_gen.h:85
packet_endgame_report::category_name
char category_name[32][MAX_LEN_NAME]
Definition packets_gen.h:87
packet_endgame_report::category_num
int category_num
Definition packets_gen.h:86
packet_endgame_report::player_num
int player_num
Definition packets_gen.h:88
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_game_info::year
int year
Definition packets_gen.h:243
packet_game_info::top_cities_count
int top_cities_count
Definition packets_gen.h:245
packet_page_msg_part
Definition packets_gen.h:840
packet_page_msg
Definition packets_gen.h:832
packet_page_msg::event
enum event_type event
Definition packets_gen.h:835
packet_page_msg::headline
char headline[MAX_LEN_MSG]
Definition packets_gen.h:834
packet_page_msg::parts
int parts
Definition packets_gen.h:837
packet_page_msg::caption
char caption[MAX_LEN_MSG]
Definition packets_gen.h:833
packet_page_msg::len
int len
Definition packets_gen.h:836
packet_scenario_info::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1610
part
Definition goto.c:52
player_economic::luxury
int luxury
Definition player.h:64
player_economic::science
int science
Definition player.h:63
player_economic::tax
int tax
Definition player.h:62
player_economic::gold
int gold
Definition player.h:61
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:103
player_score::landarea
int landarea
Definition player.h:92
player_score::mfg
int mfg
Definition player.h:100
player_score::population
int population
Definition player.h:94
player_score::pollution
int pollution
Definition player.h:97
player_score::wonders
int wonders
Definition player.h:89
player_score::settledarea
int settledarea
Definition player.h:93
player_score::units_used
int units_used
Definition player.h:106
player_score::specialists
int specialists[SP_MAX]
Definition player.h:88
player_score::units_lost
int units_lost
Definition player.h:104
player_score::techout
int techout
Definition player.h:91
player_score::game
int game
Definition player.h:108
player_score::units
int units
Definition player.h:96
player_score::units_built
int units_built
Definition player.h:102
player_score::content
int content
Definition player.h:85
player_score::happy
int happy
Definition player.h:84
player_score::spaceship
int spaceship
Definition player.h:101
player_score::culture
int culture
Definition player.h:107
player_score::unhappy
int unhappy
Definition player.h:86
player_score::cities
int cities
Definition player.h:95
player_score::bnp
int bnp
Definition player.h:99
player_score::literacy
int literacy
Definition player.h:98
player_score::techs
int techs
Definition player.h:90
player
Definition player.h:247
player::cities
struct city_list * cities
Definition player.h:279
player::is_winner
bool is_winner
Definition player.h:267
player::team
struct team * team
Definition player.h:259
player::units
struct unit_list * units
Definition player.h:280
player::is_alive
bool is_alive
Definition player.h:266
player::economic
struct player_economic economic
Definition player.h:282
player::score
struct player_score score
Definition player.h:281
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:974
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
fc_strlcat
size_t fc_strlcat(char *dest, const char *src, size_t n)
Definition support.c:836
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
fc_fopen
FILE * fc_fopen(const char *filename, const char *opentype)
Definition support.c:507
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:391
unit_can_do_action
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:361
is_special_unit
bool is_special_unit(const struct unit *punit)
Definition unit.c:352
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