Freeciv-3.2
Loading...
Searching...
No Matches
savegame3.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/*
15 This file includes the definition of a new savegame format introduced with
16 3.0. It is defined by the mandatory option '+version3'. The main load
17 function checks if this option is present. If not, the old (pre-3.0)
18 loading routines are used.
19 The format version is also saved in the settings section of the savefile, as an
20 integer (savefile.version). The integer is used to determine the version
21 of the savefile.
22
23 Structure of this file:
24
25 - The main function for saving is savegame3_save().
26
27 - The real work is done by savegame3_load() and savegame3_save_real().
28 This function call all submodules (settings, players, etc.)
29
30 - The remaining part of this file is split into several sections:
31 * helper functions
32 * save / load functions for all submodules (and their subsubmodules)
33
34 - If possible, all functions for load / save submodules should exit in
35 pairs named sg_load_<submodule> and sg_save_<submodule>. If one is not
36 needed please add a comment why.
37
38 - The submodules can be further divided as:
39 sg_load_<submodule>_<subsubmodule>
40
41 - If needed (due to static variables in the *.c files) these functions
42 can be located in the corresponding source files (as done for the settings
43 and the event_cache).
44
45 Creating a savegame:
46
47 (nothing at the moment)
48
49 Loading a savegame:
50
51 - The status of the process is saved within the static variable
52 'sg_success'. This variable is set to TRUE within savegame3_load().
53 If you encounter an error use sg_failure_*() to set it to FALSE and
54 return an error message. Furthermore, sg_check_* should be used at the
55 start of each (submodule) function to return if previous functions failed.
56
57 - While the loading process dependencies between different modules exits.
58 They can be handled within the struct loaddata *loading which is used as
59 first argument for all sg_load_*() function. Please indicate the
60 dependencies within the definition of this struct.
61
62*/
63
64#ifdef HAVE_CONFIG_H
65#include <fc_config.h>
66#endif
67
68#include <ctype.h>
69#include <stdarg.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73
74/* utility */
75#include "bitvector.h"
76#include "fcintl.h"
77#include "idex.h"
78#include "log.h"
79#include "mem.h"
80#include "rand.h"
81#include "registry.h"
82#include "shared.h"
83#include "support.h" /* bool type */
84#include "timing.h"
85
86/* common */
87#include "achievements.h"
88#include "ai.h"
89#include "bitvector.h"
90#include "capability.h"
91#include "citizens.h"
92#include "city.h"
93#include "counters.h"
94#include "game.h"
95#include "government.h"
96#include "map.h"
97#include "mapimg.h"
98#include "movement.h"
99#include "multipliers.h"
100#include "packets.h"
101#include "research.h"
102#include "rgbcolor.h"
103#include "sex.h"
104#include "specialist.h"
105#include "unit.h"
106#include "unitlist.h"
107#include "version.h"
108
109/* server */
110#include "barbarian.h"
111#include "citizenshand.h"
112#include "citytools.h"
113#include "cityturn.h"
114#include "diplhand.h"
115#include "maphand.h"
116#include "meta.h"
117#include "notify.h"
118#include "plrhand.h"
119#include "report.h"
120#include "ruleset.h"
121#include "sanitycheck.h"
122#include "savecompat.h"
123#include "score.h"
124#include "settings.h"
125#include "spacerace.h"
126#include "srv_main.h"
127#include "stdinhand.h"
128#include "techtools.h"
129#include "unittools.h"
130
131/* server/advisors */
132#include "advdata.h"
133#include "advbuilding.h"
134#include "infracache.h"
135
136/* server/generator */
137#include "mapgen.h"
138#include "mapgen_utils.h"
139
140/* server/scripting */
141#include "script_server.h"
142
143/* ai */
144#include "aitraits.h"
145#include "difficulty.h"
146
147#include "savegame3.h"
148
149extern bool sg_success;
150
151#define ACTIVITY_OLD_POLLUTION_SG3 (ACTIVITY_LAST + 1)
152#define ACTIVITY_OLD_FALLOUT_SG3 (ACTIVITY_OLD_POLLUTION_SG3 + 1)
153#define ACTIVITY_LAST_SAVEGAME3 (ACTIVITY_OLD_FALLOUT_SG3 + 1)
154
155#ifdef FREECIV_TESTMATIC
156#define SAVE_DUMMY_TURN_CHANGE_TIME 1
157#endif
158
159/*
160 * This loops over the entire map to save data. It collects all the data of
161 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
162 *
163 * Parameters:
164 * ptile: current tile within the line (used by GET_XY_CHAR)
165 * GET_XY_CHAR: macro returning the map character for each position
166 * secfile: a secfile struct
167 * secpath, ...: path as used for sprintf() with arguments; the last item
168 * will be the y coordinate
169 * Example:
170 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
171 */
172#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
173{ \
174 char _line[wld.map.xsize + 1]; \
175 int _nat_x, _nat_y; \
176 \
177 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
178 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
179 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
180 fc_assert_action(ptile != NULL, continue); \
181 _line[_nat_x] = (GET_XY_CHAR); \
182 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
183 "Trying to write invalid map data at position " \
184 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
185 secpath, _line[_nat_x], _line[_nat_x]); \
186 } \
187 _line[wld.map.xsize] = '\0'; \
188 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
189 } \
190}
191
192/*
193 * This loops over the entire map to load data. It inputs a line of data
194 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
195 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
196 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
197 * macro but definable by the caller.
198 *
199 * Parameters:
200 * ch: a variable to hold a char (data for a single position,
201 * used by SET_XY_CHAR)
202 * ptile: current tile within the line (used by SET_XY_CHAR)
203 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
204 * secfile: a secfile struct
205 * secpath, ...: path as used for sprintf() with arguments; the last item
206 * will be the y coordinate
207 * Example:
208 * LOAD_MAP_CHAR(ch, ptile,
209 * map_get_player_tile(ptile, plr)->terrain
210 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
211 *
212 * Note: some (but not all) of the code this is replacing used to skip over
213 * lines that did not exist. This allowed for backward-compatibility.
214 * We could add another parameter that specified whether it was OK to
215 * skip the data, but there's not really much advantage to exiting
216 * early in this case. Instead, we let any map data type to be empty,
217 * and just print an informative warning message about it.
218 */
219#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
220{ \
221 int _nat_x, _nat_y; \
222 bool _printed_warning = FALSE; \
223 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
224 const char *_line = secfile_lookup_str(secfile, secpath, \
225 ## __VA_ARGS__, _nat_y); \
226 if (NULL == _line) { \
227 char buf[64]; \
228 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
229 log_verbose("Line not found='%s'", buf); \
230 _printed_warning = TRUE; \
231 continue; \
232 } else if (strlen(_line) != wld.map.xsize) { \
233 char buf[64]; \
234 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
235 log_verbose("Line too short (expected %d got " SIZE_T_PRINTF \
236 ")='%s'", wld.map.xsize, strlen(_line), buf); \
237 _printed_warning = TRUE; \
238 continue; \
239 } \
240 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
241 const char ch = _line[_nat_x]; \
242 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
243 (SET_XY_CHAR); \
244 } \
245 } \
246 if (_printed_warning) { \
247 /* TRANS: Minor error message. */ \
248 log_sg(_("Saved game contains incomplete map data. This can" \
249 " happen with old saved games, or it may indicate an" \
250 " invalid saved game file. Proceed at your own risk.")); \
251 } \
252}
253
254/* Iterate on the extras half-bytes */
255#define halfbyte_iterate_extras(e, num_extras_types) \
256{ \
257 int e; \
258 for (e = 0; 4 * e < (num_extras_types); e++) {
259
260#define halfbyte_iterate_extras_end \
261 } \
262}
263
264struct savedata {
267
268 /* set by the caller */
269 const char *save_reason;
271
272 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
274};
275
276#define TOKEN_SIZE 10
277
278static const char savefile_options_default[] =
279 " +version3";
280/* The following savefile option are added if needed:
281 * - nothing at current version
282 * See also calls to sg_save_savefile_options(). */
283
284static void savegame3_save_real(struct section_file *file,
285 const char *save_reason,
286 bool scenario);
287static struct loaddata *loaddata_new(struct section_file *file);
288static void loaddata_destroy(struct loaddata *loading);
289
290static struct savedata *savedata_new(struct section_file *file,
291 const char *save_reason,
292 bool scenario);
293static void savedata_destroy(struct savedata *saving);
294
295static enum unit_orders char2order(char order);
296static char order2char(enum unit_orders order);
297static enum direction8 char2dir(char dir);
298static char dir2char(enum direction8 dir);
299static char activity2char(int activity);
300static enum unit_activity char2activity(char activity);
301static char *quote_block(const void *const data, int length);
302static int unquote_block(const char *const quoted_, void *dest,
303 int dest_length);
304static void worklist_load(struct section_file *file, int wlist_max_length,
305 struct worklist *pwl, const char *path, ...);
306static void worklist_save(struct section_file *file,
307 const struct worklist *pwl,
308 int max_length, const char *path, ...);
309static void unit_ordering_calc(void);
310static void unit_ordering_apply(void);
311static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx);
312static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx);
313static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
314 const int *idx);
315static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
316 const int *idx);
317static struct terrain *char2terrain(char ch);
318static char terrain2char(const struct terrain *pterrain);
319static Tech_type_id technology_load(struct section_file *file,
320 const char *path, int plrno);
321static void technology_save(struct section_file *file,
322 const char *path, int plrno, Tech_type_id tech);
323
324static void sg_load_savefile(struct loaddata *loading);
325static void sg_save_savefile(struct savedata *saving);
326static void sg_save_savefile_options(struct savedata *saving,
327 const char *option);
328
329static void sg_load_game(struct loaddata *loading);
330static void sg_save_game(struct savedata *saving);
331
332static void sg_load_ruledata(struct loaddata *loading);
333static void sg_save_ruledata(struct savedata *saving);
334
335static void sg_load_random(struct loaddata *loading);
336static void sg_save_random(struct savedata *saving);
337
338static void sg_load_script(struct loaddata *loading);
339static void sg_save_script(struct savedata *saving);
340
341static void sg_load_scenario(struct loaddata *loading);
342static void sg_save_scenario(struct savedata *saving);
343
344static void sg_load_settings(struct loaddata *loading);
345static void sg_save_settings(struct savedata *saving);
346
347static void sg_load_counters (struct loaddata * loading);
348static void sg_save_counters (struct savedata * saving);
349
350static void sg_load_map(struct loaddata *loading);
351static void sg_save_map(struct savedata *saving);
352static void sg_load_map_tiles(struct loaddata *loading);
353static void sg_save_map_tiles(struct savedata *saving);
354static void sg_load_map_tiles_extras(struct loaddata *loading);
355static void sg_save_map_tiles_extras(struct savedata *saving);
356
357static void sg_load_map_startpos(struct loaddata *loading);
358static void sg_save_map_startpos(struct savedata *saving);
359static void sg_load_map_owner(struct loaddata *loading);
360static void sg_save_map_owner(struct savedata *saving);
361static void sg_load_map_worked(struct loaddata *loading);
362static void sg_save_map_worked(struct savedata *saving);
363static void sg_load_map_known(struct loaddata *loading);
364static void sg_save_map_known(struct savedata *saving);
365
366static void sg_load_players_basic(struct loaddata *loading);
367static void sg_load_players(struct loaddata *loading);
368static void sg_load_player_main(struct loaddata *loading,
369 struct player *plr);
370static void sg_load_player_cities(struct loaddata *loading,
371 struct player *plr);
372static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
373 struct city *pcity, const char *citystr,
376 struct player *plr,
377 struct city *pcity,
378 const char *citystr);
379static void sg_load_player_units(struct loaddata *loading,
380 struct player *plr);
381static bool sg_load_player_unit(struct loaddata *loading,
382 struct player *plr, struct unit *punit,
384 const char *unitstr);
386 struct player *plr);
387static void sg_load_player_attributes(struct loaddata *loading,
388 struct player *plr);
389static void sg_load_player_vision(struct loaddata *loading,
390 struct player *plr);
392 struct player *plr,
393 struct vision_site *pdcity,
394 const char *citystr);
395static void sg_save_players(struct savedata *saving);
396static void sg_save_player_main(struct savedata *saving,
397 struct player *plr);
398static void sg_save_player_cities(struct savedata *saving,
399 struct player *plr);
400static void sg_save_player_units(struct savedata *saving,
401 struct player *plr);
402static void sg_save_player_attributes(struct savedata *saving,
403 struct player *plr);
404static void sg_save_player_vision(struct savedata *saving,
405 struct player *plr);
406
407static void sg_load_researches(struct loaddata *loading);
408static void sg_save_researches(struct savedata *saving);
409
410static void sg_load_event_cache(struct loaddata *loading);
411static void sg_save_event_cache(struct savedata *saving);
412
413static void sg_load_treaties(struct loaddata *loading);
414static void sg_save_treaties(struct savedata *saving);
415
416static void sg_load_history(struct loaddata *loading);
417static void sg_save_history(struct savedata *saving);
418
419static void sg_load_mapimg(struct loaddata *loading);
420static void sg_save_mapimg(struct savedata *saving);
421
422static void sg_load_sanitycheck(struct loaddata *loading);
423static void sg_save_sanitycheck(struct savedata *saving);
424
425
426/************************************************************************/
429void savegame3_save(struct section_file *sfile, const char *save_reason,
430 bool scenario)
431{
432 fc_assert_ret(sfile != NULL);
433
434#ifdef DEBUG_TIMERS
435 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
437#endif
438
439 log_verbose("saving game in new format ...");
440 savegame3_save_real(sfile, save_reason, scenario);
441
442#ifdef DEBUG_TIMERS
444 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
446#endif /* DEBUG_TIMERS */
447}
448
449/* =======================================================================
450 * Basic load / save functions.
451 * ======================================================================= */
452
453/************************************************************************/
456void savegame3_load(struct section_file *file)
457{
458 struct loaddata *loading;
460
461 /* initialise loading */
466
467 /* Load the savegame data. */
468 /* [compat] */
470 /* [scenario] */
472 /* [savefile] */
474 /* [game] */
476 /* [random] */
478 /* [settings] */
480 /* [ruledata] */
482 /* [players] (basic data) */
484 /* [map]; needs width and height loaded by [settings] */
486 /* [research] */
488 /* [player<i>] */
490 /* [counters] */
492 /* [event_cache] */
494 /* [treaties] */
496 /* [history] */
498 /* [mapimg] */
500 /* [script] -- must come last as may reference game objects */
502 /* [post_load_compat]; needs the game loaded by [savefile] */
504
505 /* Sanity checks for the loaded game. */
507
508 /* deinitialise loading */
512
513 if (!sg_success) {
514 log_error("Failure loading savegame!");
515 /* Try to get the server back to a vaguely sane state */
519 }
520}
521
522/************************************************************************/
526 const char *save_reason,
527 bool scenario)
528{
529 struct savedata *saving;
530
531 /* initialise loading */
534
535 /* [scenario] */
536 /* This should be first section so scanning through all scenarios just for
537 * names and descriptions would go faster. */
539 /* [savefile] */
541 /* [counters] */
543 /* [game] */
545 /* [random] */
547 /* [script] */
549 /* [settings] */
551 /* [ruledata] */
553 /* [map] */
555 /* [player<i>] */
557 /* [research] */
559 /* [event_cache] */
561 /* [treaty<i>] */
563 /* [history] */
565 /* [mapimg] */
567
568 /* Sanity checks for the saved game. */
570
571 /* deinitialise saving */
573
574 if (!sg_success) {
575 log_error("Failure saving savegame!");
576 }
577}
578
579/************************************************************************/
582static struct loaddata *loaddata_new(struct section_file *file)
583{
584 struct loaddata *loading = calloc(1, sizeof(*loading));
585 loading->file = file;
586 loading->secfile_options = NULL;
587
588 loading->improvement.order = NULL;
589 loading->improvement.size = -1;
590 loading->technology.order = NULL;
591 loading->technology.size = -1;
592 loading->activities.order = NULL;
593 loading->activities.size = -1;
594 loading->trait.order = NULL;
595 loading->trait.size = -1;
596 loading->extra.order = NULL;
597 loading->extra.size = -1;
598 loading->multiplier.order = NULL;
599 loading->multiplier.size = -1;
600 loading->specialist.order = NULL;
601 loading->specialist.size = -1;
602 loading->action.order = NULL;
603 loading->action.size = -1;
604 loading->act_dec.order = NULL;
605 loading->act_dec.size = -1;
606 loading->ssa.order = NULL;
607 loading->ssa.size = -1;
608 loading->coptions.order = NULL;
609 loading->coptions.size = -1;
610
611 loading->server_state = S_S_INITIAL;
612 loading->rstate = fc_rand_state();
613 loading->worked_tiles = NULL;
614
615 return loading;
616}
617
618/************************************************************************/
622{
623 if (loading->improvement.order != NULL) {
624 free(loading->improvement.order);
625 }
626
627 if (loading->technology.order != NULL) {
628 free(loading->technology.order);
629 }
630
631 if (loading->activities.order != NULL) {
632 free(loading->activities.order);
633 }
634
635 if (loading->trait.order != NULL) {
636 free(loading->trait.order);
637 }
638
639 if (loading->extra.order != NULL) {
640 free(loading->extra.order);
641 }
642
643 if (loading->multiplier.order != NULL) {
644 free(loading->multiplier.order);
645 }
646
647 if (loading->specialist.order != NULL) {
648 free(loading->specialist.order);
649 }
650
651 if (loading->action.order != NULL) {
652 free(loading->action.order);
653 }
654
655 if (loading->act_dec.order != NULL) {
656 free(loading->act_dec.order);
657 }
658
659 if (loading->ssa.order != NULL) {
660 free(loading->ssa.order);
661 }
662
663 if (loading->coptions.order != NULL) {
664 free(loading->coptions.order);
665 }
666
667 if (loading->worked_tiles != NULL) {
668 free(loading->worked_tiles);
669 }
670
671 free(loading);
672}
673
674/************************************************************************/
677static struct savedata *savedata_new(struct section_file *file,
678 const char *save_reason,
679 bool scenario)
680{
681 struct savedata *saving = calloc(1, sizeof(*saving));
682 saving->file = file;
683 saving->secfile_options[0] = '\0';
684
685 saving->save_reason = save_reason;
686 saving->scenario = scenario;
687
688 saving->save_players = FALSE;
689
690 return saving;
691}
692
693/************************************************************************/
696static void savedata_destroy(struct savedata *saving)
697{
698 free(saving);
699}
700
701/* =======================================================================
702 * Helper functions.
703 * ======================================================================= */
704
705/************************************************************************/
708static enum unit_orders char2order(char order)
709{
710 switch (order) {
711 case 'm':
712 case 'M':
713 return ORDER_MOVE;
714 case 'w':
715 case 'W':
716 return ORDER_FULL_MP;
717 case 'a':
718 case 'A':
719 return ORDER_ACTIVITY;
720 case 'x':
721 case 'X':
722 return ORDER_ACTION_MOVE;
723 case 'p':
724 case 'P':
726 }
727
728 /* This can happen if the savegame is invalid. */
729 return ORDER_LAST;
730}
731
732/************************************************************************/
735static char order2char(enum unit_orders order)
736{
737 switch (order) {
738 case ORDER_MOVE:
739 return 'm';
740 case ORDER_FULL_MP:
741 return 'w';
742 case ORDER_ACTIVITY:
743 return 'a';
745 return 'x';
747 return 'p';
748 case ORDER_LAST:
749 break;
750 }
751
753 return '?';
754}
755
756/************************************************************************/
759static enum direction8 char2dir(char dir)
760{
761 /* Numberpad values for the directions. */
762 switch (dir) {
763 case '1':
764 return DIR8_SOUTHWEST;
765 case '2':
766 return DIR8_SOUTH;
767 case '3':
768 return DIR8_SOUTHEAST;
769 case '4':
770 return DIR8_WEST;
771 case '6':
772 return DIR8_EAST;
773 case '7':
774 return DIR8_NORTHWEST;
775 case '8':
776 return DIR8_NORTH;
777 case '9':
778 return DIR8_NORTHEAST;
779 }
780
781 /* This can happen if the savegame is invalid. */
782 return direction8_invalid();
783}
784
785/************************************************************************/
788static char dir2char(enum direction8 dir)
789{
790 /* Numberpad values for the directions. */
791 switch (dir) {
792 case DIR8_NORTH:
793 return '8';
794 case DIR8_SOUTH:
795 return '2';
796 case DIR8_EAST:
797 return '6';
798 case DIR8_WEST:
799 return '4';
800 case DIR8_NORTHEAST:
801 return '9';
802 case DIR8_NORTHWEST:
803 return '7';
804 case DIR8_SOUTHEAST:
805 return '3';
806 case DIR8_SOUTHWEST:
807 return '1';
808 }
809
811
812 return '?';
813}
814
815/************************************************************************/
821static char activity2char(int activity)
822{
823 switch (activity) {
824 case ACTIVITY_IDLE:
825 return 'w';
826 case ACTIVITY_CLEAN:
827 return 'C';
829 return 'p';
830 case ACTIVITY_MINE:
831 return 'm';
832 case ACTIVITY_PLANT:
833 return 'M';
835 return 'i';
837 return 'I';
839 return 'f';
840 case ACTIVITY_SENTRY:
841 return 's';
842 case ACTIVITY_PILLAGE:
843 return 'e';
844 case ACTIVITY_GOTO:
845 return 'g';
846 case ACTIVITY_EXPLORE:
847 return 'x';
849 return 'o';
851 return 'y';
853 return 'u';
854 case ACTIVITY_BASE:
855 return 'b';
857 return 'R';
858 case ACTIVITY_CONVERT:
859 return 'c';
860 case ACTIVITY_LAST:
861 break;
862 }
863
865
866 return '?';
867}
868
869/************************************************************************/
872static enum unit_activity char2activity(char activity)
873{
874 enum unit_activity a;
875
876 for (a = 0; a < ACTIVITY_LAST_SAVEGAME3; a++) {
877 /* Skip ACTIVITY_LAST. The SAVEGAME3 specific values are after it. */
878 if (a != ACTIVITY_LAST) {
879 char achar = activity2char(a);
880
881 if (activity == achar) {
882 return a;
883 }
884 }
885 }
886
887 /* This can happen if the savegame is invalid. */
888 return ACTIVITY_LAST;
889}
890
891/************************************************************************/
895static char *quote_block(const void *const data, int length)
896{
897 char *buffer = fc_malloc(length * 3 + 10);
898 size_t offset;
899 int i;
900
901 sprintf(buffer, "%d:", length);
902 offset = strlen(buffer);
903
904 for (i = 0; i < length; i++) {
905 sprintf(buffer + offset, "%02x ", ((unsigned char *) data)[i]);
906 offset += 3;
907 }
908 return buffer;
909}
910
911/************************************************************************/
916static int unquote_block(const char *const quoted_, void *dest,
917 int dest_length)
918{
919 int i, length, parsed, tmp;
920 char *endptr;
921 const char *quoted = quoted_;
922
923 parsed = sscanf(quoted, "%d", &length);
924
925 if (parsed != 1) {
926 log_error(_("Syntax error in attribute block."));
927 return 0;
928 }
929
930 if (length > dest_length) {
931 return 0;
932 }
933
934 quoted = strchr(quoted, ':');
935
936 if (quoted == NULL) {
937 log_error(_("Syntax error in attribute block."));
938 return 0;
939 }
940
941 quoted++;
942
943 for (i = 0; i < length; i++) {
944 tmp = strtol(quoted, &endptr, 16);
945
946 if ((endptr - quoted) != 2
947 || *endptr != ' '
948 || (tmp & 0xff) != tmp) {
949 log_error(_("Syntax error in attribute block."));
950 return 0;
951 }
952
953 ((unsigned char *) dest)[i] = tmp;
954 quoted += 3;
955 }
956
957 return length;
958}
959
960/************************************************************************/
965 struct worklist *pwl, const char *path, ...)
966{
967 int i;
968 const char *kind;
969 const char *name;
970 char path_str[1024];
971 va_list ap;
972
973 /* The first part of the registry path is taken from the varargs to the
974 * function. */
975 va_start(ap, path);
976 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
977 va_end(ap);
978
981 "%s.wl_length", path_str);
982
983 for (i = 0; i < pwl->length; i++) {
984 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
985
986 /* We lookup the production value by name. An invalid entry isn't a
987 * fatal error; we just truncate the worklist. */
988 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
989 path_str, i);
990 pwl->entries[i] = universal_by_rule_name(kind, name);
991 if (pwl->entries[i].kind == universals_n_invalid()) {
992 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
993 name);
994 pwl->length = i;
995 break;
996 }
997 }
998
999 /* Padding entries */
1000 for (; i < wlist_max_length; i++) {
1001 (void) secfile_entry_lookup(file, "%s.wl_kind%d", path_str, i);
1002 (void) secfile_entry_lookup(file, "%s.wl_value%d", path_str, i);
1003 }
1004}
1005
1006/************************************************************************/
1010static void worklist_save(struct section_file *file,
1011 const struct worklist *pwl,
1012 int max_length, const char *path, ...)
1013{
1014 char path_str[1024];
1015 int i;
1016 va_list ap;
1017
1018 /* The first part of the registry path is taken from the varargs to the
1019 * function. */
1020 va_start(ap, path);
1021 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1022 va_end(ap);
1023
1024 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1025
1026 for (i = 0; i < pwl->length; i++) {
1027 const struct universal *entry = pwl->entries + i;
1029 "%s.wl_kind%d", path_str, i);
1031 "%s.wl_value%d", path_str, i);
1032 }
1033
1035
1036 /* We want to keep savegame in tabular format, so each line has to be
1037 * of equal length. Fill table up to maximum worklist size. */
1038 for (i = pwl->length ; i < max_length; i++) {
1039 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1040 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1041 }
1042}
1043
1044/************************************************************************/
1048static void unit_ordering_calc(void)
1049{
1050 int j;
1051
1052 players_iterate(pplayer) {
1053 /* to avoid junk values for unsupported units: */
1054 unit_list_iterate(pplayer->units, punit) {
1055 punit->server.ord_city = 0;
1057 city_list_iterate(pplayer->cities, pcity) {
1058 j = 0;
1059 unit_list_iterate(pcity->units_supported, punit) {
1060 punit->server.ord_city = j++;
1064
1065 whole_map_iterate(&(wld.map), ptile) {
1066 j = 0;
1067 unit_list_iterate(ptile->units, punit) {
1068 punit->server.ord_map = j++;
1071}
1072
1073/************************************************************************/
1077static void unit_ordering_apply(void)
1078{
1079 players_iterate(pplayer) {
1080 city_list_iterate(pplayer->cities, pcity) {
1081 unit_list_sort_ord_city(pcity->units_supported);
1082 }
1085
1086 whole_map_iterate(&(wld.map), ptile) {
1087 unit_list_sort_ord_map(ptile->units);
1089}
1090
1091/************************************************************************/
1098static void sg_extras_set_dbv(struct dbv *extras, char ch,
1099 struct extra_type **idx)
1100{
1101 int i, bin;
1102 const char *pch = strchr(hex_chars, ch);
1103
1104 if (!pch || ch == '\0') {
1105 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1106 bin = 0;
1107 } else {
1108 bin = pch - hex_chars;
1109 }
1110
1111 for (i = 0; i < 4; i++) {
1112 struct extra_type *pextra = idx[i];
1113
1114 if (pextra == NULL) {
1115 continue;
1116 }
1117 if ((bin & (1 << i))
1118 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1119 dbv_set(extras, extra_index(pextra));
1120 }
1121 }
1122}
1123
1124/************************************************************************/
1132 struct extra_type **idx)
1133{
1134 int i, bin;
1135 const char *pch = strchr(hex_chars, ch);
1136
1137 if (!pch || ch == '\0') {
1138 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1139 bin = 0;
1140 } else {
1141 bin = pch - hex_chars;
1142 }
1143
1144 for (i = 0; i < 4; i++) {
1145 struct extra_type *pextra = idx[i];
1146
1147 if (pextra == NULL) {
1148 continue;
1149 }
1150 if ((bin & (1 << i))
1151 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1152 BV_SET(*extras, extra_index(pextra));
1153 }
1154 }
1155}
1156
1157/************************************************************************/
1163static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1164 const int *idx)
1165{
1166 int i, bin = 0;
1167 int max = dbv_bits(extras);
1168
1169 for (i = 0; i < 4; i++) {
1170 int extra = idx[i];
1171
1172 if (extra < 0) {
1173 break;
1174 }
1175
1176 if (extra < max
1177 && (dbv_isset(extras, extra)
1178 /* An invalid resource, a resource that can't exist at the tile's
1179 * current terrain, isn't in the bit extra vector. Save it so it
1180 * can return if the tile's terrain changes to something it can
1181 * exist on. */
1182 || extra_by_number(extra) == presource)) {
1183 bin |= (1 << i);
1184 }
1185 }
1186
1187 return hex_chars[bin];
1188}
1189
1190/************************************************************************/
1196static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1197 const int *idx)
1198{
1199 int i, bin = 0;
1200
1201 for (i = 0; i < 4; i++) {
1202 int extra = idx[i];
1203
1204 if (extra < 0) {
1205 break;
1206 }
1207
1208 if (BV_ISSET(extras, extra)
1209 /* An invalid resource, a resource that can't exist at the tile's
1210 * current terrain, isn't in the bit extra vector. Save it so it
1211 * can return if the tile's terrain changes to something it can
1212 * exist on. */
1213 || extra_by_number(extra) == presource) {
1214 bin |= (1 << i);
1215 }
1216 }
1217
1218 return hex_chars[bin];
1219}
1220
1221/************************************************************************/
1225static struct terrain *char2terrain(char ch)
1226{
1227 /* terrain_by_identifier plus fatal error */
1229 return T_UNKNOWN;
1230 }
1231 terrain_type_iterate(pterrain) {
1232 if (pterrain->identifier_load == ch) {
1233 return pterrain;
1234 }
1236
1237 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1238
1240
1242}
1243
1244/************************************************************************/
1248static char terrain2char(const struct terrain *pterrain)
1249{
1250 if (pterrain == T_UNKNOWN) {
1252 } else {
1253 return pterrain->identifier;
1254 }
1255}
1256
1257/************************************************************************/
1262 const char *path, int plrno)
1263{
1264 char path_with_name[128];
1265 const char *name;
1266 struct advance *padvance;
1267
1269 "%s_name", path);
1270
1272
1273 if (!name || name[0] == '\0') {
1274 /* used by researching_saved */
1275 return A_UNKNOWN;
1276 }
1277 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1278 return A_FUTURE;
1279 }
1280 if (fc_strcasecmp(name, "A_NONE") == 0) {
1281 return A_NONE;
1282 }
1283 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1284 return A_UNSET;
1285 }
1286
1289 "%s: unknown technology \"%s\".", path_with_name, name);
1290
1291 return advance_number(padvance);
1292}
1293
1294/************************************************************************/
1297static void technology_save(struct section_file *file,
1298 const char *path, int plrno, Tech_type_id tech)
1299{
1300 char path_with_name[128];
1301 const char *name;
1302
1304 "%s_name", path);
1305
1306 switch (tech) {
1307 case A_UNKNOWN: /* used by researching_saved */
1308 name = "";
1309 break;
1310 case A_NONE:
1311 name = "A_NONE";
1312 break;
1313 case A_UNSET:
1314 name = "A_UNSET";
1315 break;
1316 case A_FUTURE:
1317 name = "A_FUTURE";
1318 break;
1319 default:
1321 break;
1322 }
1323
1325}
1326
1327/* =======================================================================
1328 * Load / save savefile data.
1329 * ======================================================================= */
1330
1331/************************************************************************/
1335{
1336 int i;
1337 const char *terr_name;
1338 bool ruleset_datafile;
1340 const char *str;
1341
1342 /* Check status and return if not OK (sg_success FALSE). */
1343 sg_check_ret();
1344
1345 /* Load savefile options. */
1346 loading->secfile_options
1347 = secfile_lookup_str(loading->file, "savefile.options");
1348
1349 /* We don't need these entries, but read them anyway to avoid
1350 * warnings about unread secfile entries. */
1351 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1352 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1353
1354 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1356
1357 if (game.scenario.datafile[0] != '\0') {
1359 } else {
1361 }
1362
1365 const char *req_caps;
1366
1369 /* Failed to load correct ruleset */
1370 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1372 }
1373
1374 req_caps = secfile_lookup_str_default(loading->file, "",
1375 "scenario.ruleset_caps");
1376 strncpy(game.scenario.req_caps, req_caps,
1377 sizeof(game.scenario.req_caps) - 1);
1378 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1379
1380 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1381 /* Current ruleset lacks required capabilities. */
1382 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1383 log_normal(_("Ruleset has capabilities: %s"),
1385 /* TRANS: ... ruleset dir ... scenario name ... */
1386 log_error(_("Current ruleset %s not compatible with the scenario %s."
1387 " Trying to switch to the ruleset specified by the"
1388 " scenario."),
1390
1392 }
1393 }
1394
1397 const char *ruleset, *alt_dir;
1398
1401 "savefile.rulesetdir");
1402
1403 /* Load ruleset. */
1405 if (!strcmp("default", game.server.rulesetdir)) {
1406 /* Here 'default' really means current default.
1407 * Saving happens with real ruleset name, so savegames containing this
1408 * are special scenarios. */
1410 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1412 }
1413
1414 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1415 "savefile.ruleset_alt_dir");
1416
1417 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1418 if (alt_dir) {
1420 _("Failed to load either of rulesets '%s' or '%s' "
1421 "needed for savegame."),
1422 ruleset, alt_dir);
1423 } else {
1425 _("Failed to load ruleset '%s' needed for savegame."),
1426 ruleset);
1427 }
1428 }
1429
1431 /* TRANS: ruleset dir */
1432 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1433 }
1434 }
1435
1436 /* Remove all aifill players. Correct number of them get created later
1437 * with correct skill level etc. */
1438 (void) aifill(0);
1439
1440 /* Time to load scenario specific luadata */
1441 if (game.scenario.datafile[0] != '\0') {
1442 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1444 } else {
1445 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1446 const struct strvec **path;
1447 const char *found = NULL;
1448 char testfile[MAX_LEN_PATH];
1449 struct section_file *secfile;
1450
1451 for (path = paths; found == NULL && *path != NULL; path++) {
1452 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1453
1454 found = fileinfoname(*path, testfile);
1455 }
1456
1457 if (found == NULL) {
1458 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1459 sg_success = FALSE;
1460 return;
1461 }
1462
1463 secfile = secfile_load(found, FALSE);
1464 if (secfile == NULL) {
1465 log_error(_("Failed to load scenario luadata file %s.luadata"),
1467 sg_success = FALSE;
1468 return;
1469 }
1470
1471 game.server.luadata = secfile;
1472 }
1473 }
1474
1476 "savefile.dbid");
1477
1478 /* This is in the savegame only if the game has been started before savegame3.c time,
1479 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1481 "savefile.last_updated_as_year");
1482
1483 /* Load improvements. */
1484 loading->improvement.size
1486 "savefile.improvement_size");
1487 if (loading->improvement.size) {
1488 loading->improvement.order
1489 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1490 "savefile.improvement_vector");
1491 sg_failure_ret(loading->improvement.size != 0,
1492 "Failed to load improvement order: %s",
1493 secfile_error());
1494 }
1495
1496 /* Load technologies. */
1497 loading->technology.size
1499 "savefile.technology_size");
1500 if (loading->technology.size) {
1501 loading->technology.order
1502 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1503 "savefile.technology_vector");
1504 sg_failure_ret(loading->technology.size != 0,
1505 "Failed to load technology order: %s",
1506 secfile_error());
1507 }
1508
1509 /* Load Activities. */
1510 loading->activities.size
1512 "savefile.activities_size");
1513 if (loading->activities.size) {
1514 loading->activities.order
1515 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1516 "savefile.activities_vector");
1517 sg_failure_ret(loading->activities.size != 0,
1518 "Failed to load activity order: %s",
1519 secfile_error());
1520 }
1521
1522 /* Load traits. */
1523 loading->trait.size
1525 "savefile.trait_size");
1526 if (loading->trait.size) {
1527 loading->trait.order
1528 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1529 "savefile.trait_vector");
1530 sg_failure_ret(loading->trait.size != 0,
1531 "Failed to load trait order: %s",
1532 secfile_error());
1533 }
1534
1535 /* Load extras. */
1536 loading->extra.size
1538 "savefile.extras_size");
1539 if (loading->extra.size) {
1540 const char **modname;
1541 size_t nmod;
1542 int j;
1543
1544 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1545 "savefile.extras_vector");
1546 sg_failure_ret(loading->extra.size != 0,
1547 "Failed to load extras order: %s",
1548 secfile_error());
1550 "Number of extras defined by the ruleset (= %d) are "
1551 "lower than the number in the savefile (= %d).",
1552 game.control.num_extra_types, (int)loading->extra.size);
1553 /* make sure that the size of the array is divisible by 4 */
1554 nmod = 4 * ((loading->extra.size + 3) / 4);
1555 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1556 for (j = 0; j < loading->extra.size; j++) {
1557 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1558 }
1559 free(modname);
1560 for (; j < nmod; j++) {
1561 loading->extra.order[j] = NULL;
1562 }
1563 }
1564
1565 /* Load multipliers. */
1566 loading->multiplier.size
1568 "savefile.multipliers_size");
1569 if (loading->multiplier.size) {
1570 const char **modname;
1571 int j;
1572
1573 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1574 "savefile.multipliers_vector");
1575 sg_failure_ret(loading->multiplier.size != 0,
1576 "Failed to load multipliers order: %s",
1577 secfile_error());
1578 /* It's OK for the set of multipliers in the savefile to differ
1579 * from those in the ruleset. */
1580 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1581 sizeof(*loading->multiplier.order));
1582 for (j = 0; j < loading->multiplier.size; j++) {
1583 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1584 if (!loading->multiplier.order[j]) {
1585 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1586 "discarding", modname[j]);
1587 }
1588 }
1589 free(modname);
1590 }
1591
1592 /* Load specialists. */
1593 loading->specialist.size
1595 "savefile.specialists_size");
1596 if (loading->specialist.size) {
1597 const char **modname;
1598 size_t nmod;
1599 int j;
1600
1601 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1602 "savefile.specialists_vector");
1603 sg_failure_ret(loading->specialist.size != 0,
1604 "Failed to load specialists order: %s",
1605 secfile_error());
1607 "Number of specialists defined by the ruleset (= %d) are "
1608 "lower than the number in the savefile (= %d).",
1609 game.control.num_specialist_types, (int)loading->specialist.size);
1610 /* make sure that the size of the array is divisible by 4 */
1611 /* That's not really needed with specialists at the moment, but done this way
1612 * for consistency with other types, and to be prepared for the time it needs
1613 * to be this way. */
1614 nmod = 4 * ((loading->specialist.size + 3) / 4);
1615 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1616 for (j = 0; j < loading->specialist.size; j++) {
1617 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1618 }
1619 free(modname);
1620 for (; j < nmod; j++) {
1621 loading->specialist.order[j] = NULL;
1622 }
1623 }
1624
1625 /* Load action order. */
1626 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1627 "savefile.action_size");
1628
1629 sg_failure_ret(loading->action.size > 0,
1630 "Failed to load action order: %s",
1631 secfile_error());
1632
1633 if (loading->action.size) {
1634 const char **modname;
1635 int j;
1636
1637 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1638 "savefile.action_vector");
1639
1640 loading->action.order = fc_calloc(loading->action.size,
1641 sizeof(*loading->action.order));
1642
1643 for (j = 0; j < loading->action.size; j++) {
1645
1646 if (real_action) {
1647 loading->action.order[j] = real_action->id;
1648 } else {
1649 log_sg("Unknown action \'%s\'", modname[j]);
1650 loading->action.order[j] = ACTION_NONE;
1651 }
1652 }
1653
1654 free(modname);
1655 }
1656
1657 /* Load action decision order. */
1658 loading->act_dec.size
1660 "savefile.action_decision_size");
1661
1662 sg_failure_ret(loading->act_dec.size > 0,
1663 "Failed to load action decision order: %s",
1664 secfile_error());
1665
1666 if (loading->act_dec.size) {
1667 const char **modname;
1668 int j;
1669
1670 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1671 "savefile.action_decision_vector");
1672
1673 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1674 sizeof(*loading->act_dec.order));
1675
1676 for (j = 0; j < loading->act_dec.size; j++) {
1677 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1679 }
1680
1681 free(modname);
1682 }
1683
1684 /* Load server side agent order. */
1685 loading->ssa.size
1687 "savefile.server_side_agent_size");
1688
1689 sg_failure_ret(loading->ssa.size > 0,
1690 "Failed to load server side agent order: %s",
1691 secfile_error());
1692
1693 if (loading->ssa.size) {
1694 const char **modname;
1695 int j;
1696
1697 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1698 "savefile.server_side_agent_list");
1699
1700 loading->ssa.order = fc_calloc(loading->ssa.size,
1701 sizeof(*loading->ssa.order));
1702
1703 for (j = 0; j < loading->ssa.size; j++) {
1704 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1706 }
1707
1708 free(modname);
1709 }
1710
1711 /* Load city options order. */
1712 loading->coptions.size
1714 "savefile.city_options_size");
1715
1716 sg_failure_ret(loading->coptions.size > 0,
1717 "Failed to load city options order: %s",
1718 secfile_error());
1719
1720 if (loading->coptions.size) {
1721 const char **modname;
1722 int j;
1723
1724 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1725 "savefile.city_options_vector");
1726
1727 loading->coptions.order = fc_calloc(loading->coptions.size,
1728 sizeof(*loading->coptions.order));
1729
1730 for (j = 0; j < loading->coptions.size; j++) {
1731 loading->coptions.order[j] = city_options_by_name(modname[j],
1733 }
1734
1735 free(modname);
1736 }
1737
1738 /* Terrain identifiers */
1740 pterr->identifier_load = '\0';
1742
1743 i = 0;
1745 "savefile.terrident%d.name", i)) != NULL) {
1747
1748 if (pterr != NULL) {
1749 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1750 "savefile.terrident%d.identifier", i);
1751
1752 pterr->identifier_load = *iptr;
1753 } else {
1754 log_error("Identifier for unknown terrain type %s.", terr_name);
1755 }
1756 i++;
1757 }
1758
1761 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1762 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1763 "%s and %s share a saved identifier",
1765 }
1768}
1769
1770/************************************************************************/
1774{
1775 int i;
1776
1777 /* Check status and return if not OK (sg_success FALSE). */
1778 sg_check_ret();
1779
1780 /* Save savefile options. */
1782
1783 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1784
1785 /* Save reason of the savefile generation. */
1786 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1787
1788 /* Save as accurate freeciv revision information as possible */
1789 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1790
1791 /* Freeciv version used in the very first launch of this game -
1792 * or even saving in pregame. */
1794 "savefile.orig_version");
1795
1796 /* Save rulesetdir at this point as this ruleset is required by this
1797 * savefile. */
1798 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1799
1800 if (game.control.version[0] != '\0') {
1801 /* Current ruleset has version information, save it.
1802 * This is never loaded, but exist in savegame file only for debugging purposes. */
1803 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1804 }
1805
1806 if (game.control.alt_dir[0] != '\0') {
1807 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1808 }
1809
1811 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1812 }
1813
1814 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1815
1816 /* Save improvement order in savegame, so we are not dependent on ruleset
1817 * order. If the game isn't started improvements aren't loaded so we can
1818 * not save the order. */
1820 "savefile.improvement_size");
1821 if (improvement_count() > 0) {
1822 const char *buf[improvement_count()];
1823
1824 improvement_iterate(pimprove) {
1825 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1827
1829 "savefile.improvement_vector");
1830 }
1831
1832 /* Save technology order in savegame, so we are not dependent on ruleset
1833 * order. If the game isn't started advances aren't loaded so we can not
1834 * save the order. */
1836 "savefile.technology_size");
1837 if (game.control.num_tech_types > 0) {
1838 const char *buf[game.control.num_tech_types];
1839
1840 buf[A_NONE] = "A_NONE";
1841 advance_iterate(a) {
1845 "savefile.technology_vector");
1846 }
1847
1848 /* Save activities order in the savegame. */
1850 "savefile.activities_size");
1851 if (ACTIVITY_LAST > 0) {
1852 const char **modname;
1853 int j;
1854
1855 i = 0;
1856
1858
1859 for (j = 0; j < ACTIVITY_LAST; j++) {
1861 }
1862
1865 "savefile.activities_vector");
1866 free(modname);
1867 }
1868
1869 /* Save specialists order in the savegame. */
1871 "savefile.specialists_size");
1872 {
1873 const char **modname;
1874
1875 i = 0;
1877
1881
1883 "savefile.specialists_vector");
1884
1885 free(modname);
1886 }
1887
1888 /* Save trait order in savegame. */
1890 "savefile.trait_size");
1891 {
1892 const char **modname;
1893 enum trait tr;
1894 int j;
1895
1896 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1897
1898 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1899 modname[j] = trait_name(tr);
1900 }
1901
1903 "savefile.trait_vector");
1904 free(modname);
1905 }
1906
1907 /* Save extras order in the savegame. */
1909 "savefile.extras_size");
1910 if (game.control.num_extra_types > 0) {
1911 const char **modname;
1912
1913 i = 0;
1915
1916 extra_type_iterate(pextra) {
1917 modname[i++] = extra_rule_name(pextra);
1919
1922 "savefile.extras_vector");
1923 free(modname);
1924 }
1925
1926 /* Save multipliers order in the savegame. */
1928 "savefile.multipliers_size");
1929 if (multiplier_count() > 0) {
1930 const char **modname;
1931
1933
1934 multipliers_iterate(pmul) {
1937
1940 "savefile.multipliers_vector");
1941 free(modname);
1942 }
1943
1944 /* Save city_option order in the savegame. */
1946 "savefile.city_options_size");
1947 if (CITYO_LAST > 0) {
1948 const char **modname;
1949 int j;
1950
1951 i = 0;
1952 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1953
1954 for (j = 0; j < CITYO_LAST; j++) {
1955 modname[i++] = city_options_name(j);
1956 }
1957
1959 CITYO_LAST,
1960 "savefile.city_options_vector");
1961 free(modname);
1962 }
1963
1964 /* Save action order in the savegame. */
1966 "savefile.action_size");
1967 if (NUM_ACTIONS > 0) {
1968 const char **modname;
1969 int j;
1970
1971 i = 0;
1972 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1973
1974 for (j = 0; j < NUM_ACTIONS; j++) {
1976 }
1977
1980 "savefile.action_vector");
1981 free(modname);
1982 }
1983
1984 /* Save action decision order in the savegame. */
1986 "savefile.action_decision_size");
1987 if (ACT_DEC_COUNT > 0) {
1988 const char **modname;
1989 int j;
1990
1991 i = 0;
1993
1994 for (j = 0; j < ACT_DEC_COUNT; j++) {
1996 }
1997
2000 "savefile.action_decision_vector");
2001 free(modname);
2002 }
2003
2004 /* Save server side agent order in the savegame. */
2006 "savefile.server_side_agent_size");
2007 if (SSA_COUNT > 0) {
2008 const char **modname;
2009 int j;
2010
2011 i = 0;
2012 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2013
2014 for (j = 0; j < SSA_COUNT; j++) {
2016 }
2017
2019 SSA_COUNT,
2020 "savefile.server_side_agent_list");
2021 free(modname);
2022 }
2023
2024 /* Save terrain character mapping in the savegame. */
2025 i = 0;
2027 char buf[2];
2028
2029 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2031 buf[1] = '\0';
2032 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2034}
2035
2036/************************************************************************/
2040 const char *option)
2041{
2042 /* Check status and return if not OK (sg_success FALSE). */
2043 sg_check_ret();
2044
2045 if (option == NULL) {
2046 /* no additional option */
2047 return;
2048 }
2049
2050 sz_strlcat(saving->secfile_options, option);
2051 secfile_replace_str(saving->file, saving->secfile_options,
2052 "savefile.options");
2053}
2054
2055/* =======================================================================
2056 * Load / save game status.
2057 * ======================================================================= */
2058
2059/************************************************************************/
2063{
2064 int i;
2065 const char *name;
2066
2067 /* Check status and return if not OK (sg_success FALSE). */
2068 sg_check_ret();
2069
2070 for (i = 0;
2072 "ruledata.government%d.name", i));
2073 i++) {
2075
2076 if (gov != NULL) {
2078 "ruledata.government%d.changes", i);
2079 }
2080 }
2081}
2082
2083/************************************************************************/
2086static void sg_load_game(struct loaddata *loading)
2087{
2088 const char *str;
2089 int i;
2090
2091 /* Check status and return if not OK (sg_success FALSE). */
2092 sg_check_ret();
2093
2094 /* Load server state. */
2095 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2096 "game.server_state");
2097 loading->server_state = server_states_by_name(str, strcmp);
2098 if (!server_states_is_valid(loading->server_state)) {
2099 /* Don't take any risk! */
2100 loading->server_state = S_S_INITIAL;
2101 }
2102
2104 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2105
2108 "game.meta_patches");
2110
2112 /* Do not overwrite this if the user requested a specific metaserver
2113 * from the command line (option --Metaserver). */
2117 "game.meta_server"));
2118 }
2119
2120 if ('\0' == srvarg.serverid[0]) {
2121 /* Do not overwrite this if the user requested a specific metaserver
2122 * from the command line (option --serverid). */
2125 "game.serverid"));
2126 }
2127 sz_strlcpy(server.game_identifier,
2128 secfile_lookup_str_default(loading->file, "", "game.id"));
2129 /* We are not checking game_identifier legality just yet.
2130 * That's done when we are sure that rand seed has been initialized,
2131 * so that we can generate new game_identifier, if needed.
2132 * See sq_load_sanitycheck(). */
2133
2135 "game.phase_mode");
2136 if (str != NULL) {
2139 log_error("Illegal phase mode \"%s\"", str);
2141 }
2142 } else {
2143 log_error("Phase mode missing");
2144 }
2145
2147 "game.phase_mode_stored");
2148 if (str != NULL) {
2151 log_error("Illegal stored phase mode \"%s\"", str);
2153 }
2154 } else {
2155 log_error("Stored phase mode missing");
2156 }
2159 "game.phase");
2163 "game.scoreturn");
2164
2167 "game.timeoutint");
2170 "game.timeoutintinc");
2173 "game.timeoutinc");
2176 "game.timeoutincmult");
2179 "game.timeoutcounter");
2180
2181 game.info.turn
2182 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2184 "game.year"), "%s", secfile_error());
2186 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2187
2189 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2191 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2193 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2194
2196 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2198 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2200 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2201
2202 /* Savegame may have stored random_seed for documentation purposes only,
2203 * but we want to keep it for resaving. */
2204 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2205
2206 /* Global advances. */
2208 "game.global_advances");
2209 if (str != NULL) {
2210 sg_failure_ret(strlen(str) == loading->technology.size,
2211 "Invalid length of 'game.global_advances' ("
2212 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2213 strlen(str), loading->technology.size);
2214 for (i = 0; i < loading->technology.size; i++) {
2215 sg_failure_ret(str[i] == '1' || str[i] == '0',
2216 "Undefined value '%c' within 'game.global_advances'.",
2217 str[i]);
2218 if (str[i] == '1') {
2219 struct advance *padvance =
2220 advance_by_rule_name(loading->technology.order[i]);
2221
2222 if (padvance != NULL) {
2224 }
2225 }
2226 }
2227 }
2228
2230 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2231
2233 = secfile_lookup_int_default(loading->file, 0, "game.last_turn_change_time") / 100.0;
2234}
2235
2236/************************************************************************/
2240{
2241 int set_count = 0;
2242
2244 char path[256];
2245
2246 fc_snprintf(path, sizeof(path),
2247 "ruledata.government%d", set_count++);
2248
2250 "%s.name", path);
2251 secfile_insert_int(saving->file, pgov->changed_to_times,
2252 "%s.changes", path);
2254}
2255
2256/************************************************************************/
2259static void sg_save_game(struct savedata *saving)
2260{
2262 char global_advances[game.control.num_tech_types + 1];
2263 int i;
2264
2265 /* Check status and return if not OK (sg_success FALSE). */
2266 sg_check_ret();
2267
2268 /* Game state: once the game is no longer a new game (ie, has been
2269 * started the first time), it should always be considered a running
2270 * game for savegame purposes. */
2271 if (saving->scenario && !game.scenario.players) {
2273 } else {
2275 }
2277 "game.server_state");
2278
2279 if (game.server.phase_timer != NULL) {
2283 "game.phase_seconds");
2284 }
2285
2287 "game.meta_patches");
2288 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2289
2290 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2291 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2292
2295 "game.phase_mode");
2298 "game.phase_mode_stored");
2300 "game.phase");
2302 "game.scoreturn");
2303
2305 "game.timeoutint");
2307 "game.timeoutintinc");
2309 "game.timeoutinc");
2311 "game.timeoutincmult");
2313 "game.timeoutcounter");
2314
2315 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2316 secfile_insert_int(saving->file, game.info.year, "game.year");
2318 "game.year_0_hack");
2319
2321 "game.globalwarming");
2323 "game.heating");
2325 "game.warminglevel");
2326
2328 "game.nuclearwinter");
2330 "game.cooling");
2332 "game.coolinglevel");
2333 /* For debugging purposes only.
2334 * Do not save it if it's 0 (not known);
2335 * this confuses people reading this 'document' less than
2336 * saving 0. */
2337 if (game.server.seed != 0) {
2339 "game.random_seed");
2340 }
2341
2342 /* Global advances. */
2343 for (i = 0; i < game.control.num_tech_types; i++) {
2344 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2345 }
2346 global_advances[i] = '\0';
2347 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2348
2349 if (!game_was_started()) {
2350 saving->save_players = FALSE;
2351 } else {
2352 if (saving->scenario) {
2353 saving->save_players = game.scenario.players;
2354 } else {
2355 saving->save_players = TRUE;
2356 }
2357#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2359 "game.last_turn_change_time");
2360#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2362 "game.last_turn_change_time");
2363#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2364 }
2365 secfile_insert_bool(saving->file, saving->save_players,
2366 "game.save_players");
2367
2368 if (srv_state != S_S_INITIAL) {
2369 const char *ainames[ai_type_get_count()];
2370
2371 i = 0;
2372 ai_type_iterate(ait) {
2373 ainames[i] = ait->name;
2374 i++;
2376
2378 "game.ai_types");
2379 }
2380}
2381
2382/* =======================================================================
2383 * Load / save random status.
2384 * ======================================================================= */
2385
2386/************************************************************************/
2389static void sg_load_random(struct loaddata *loading)
2390{
2391 /* Check status and return if not OK (sg_success FALSE). */
2392 sg_check_ret();
2393
2394 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2395 const char *str;
2396 int i;
2397
2399 "random.index_J"), "%s", secfile_error());
2401 "random.index_K"), "%s", secfile_error());
2403 "random.index_X"), "%s", secfile_error());
2404
2405 for (i = 0; i < 8; i++) {
2406 str = secfile_lookup_str(loading->file, "random.table%d",i);
2407 sg_failure_ret(NULL != str, "%s", secfile_error());
2408 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2409 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2410 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2411 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2412 }
2413 loading->rstate.is_init = TRUE;
2414 fc_rand_set_state(loading->rstate);
2415 } else {
2416 /* No random values - mark the setting. */
2417 (void) secfile_entry_by_path(loading->file, "random.saved");
2418
2419 /* We're loading a game without a seed (which is okay, if it's a scenario).
2420 * We need to generate the game seed now because it will be needed later
2421 * during the load. */
2423 loading->rstate = fc_rand_state();
2424 }
2425}
2426
2427/************************************************************************/
2430static void sg_save_random(struct savedata *saving)
2431{
2432 /* Check status and return if not OK (sg_success FALSE). */
2433 sg_check_ret();
2434
2435 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2436 int i;
2437 RANDOM_STATE rstate = fc_rand_state();
2438
2439 secfile_insert_bool(saving->file, TRUE, "random.saved");
2440 fc_assert(rstate.is_init);
2441
2442 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2443 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2444 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2445
2446 for (i = 0; i < 8; i++) {
2447 char vec[100];
2448
2449 fc_snprintf(vec, sizeof(vec),
2450 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2451 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2452 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2453 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2454 secfile_insert_str(saving->file, vec, "random.table%d", i);
2455 }
2456 } else {
2457 secfile_insert_bool(saving->file, FALSE, "random.saved");
2458 }
2459}
2460
2461/* =======================================================================
2462 * Load / save lua script data.
2463 * ======================================================================= */
2464
2465/************************************************************************/
2468static void sg_load_script(struct loaddata *loading)
2469{
2470 /* Check status and return if not OK (sg_success FALSE). */
2471 sg_check_ret();
2472
2474}
2475
2476/************************************************************************/
2479static void sg_save_script(struct savedata *saving)
2480{
2481 /* Check status and return if not OK (sg_success FALSE). */
2482 sg_check_ret();
2483
2485}
2486
2487/* =======================================================================
2488 * Load / save scenario data.
2489 * ======================================================================= */
2490
2491/************************************************************************/
2495{
2496 const char *buf;
2497 int game_version;
2498
2499 /* Check status and return if not OK (sg_success FALSE). */
2500 sg_check_ret();
2501
2502 /* Load version. */
2504 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2505 /* We require at least version 2.90.99 - and at that time we saved version
2506 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2507 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2508 "version 2.90.99 required.");
2509
2510 loading->full_version = game_version;
2511
2512 game.scenario.datafile[0] = '\0';
2513
2515 "scenario.is_scenario"), "%s", secfile_error());
2516 if (!game.scenario.is_scenario) {
2517 return;
2518 }
2519
2520 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2521 if (buf[0] != '\0') {
2523 }
2524
2526 "scenario.authors");
2527 if (buf[0] != '\0') {
2529 } else {
2530 game.scenario.authors[0] = '\0';
2531 }
2532
2534 "scenario.description");
2535 if (buf[0] != '\0') {
2537 } else {
2538 game.scenario_desc.description[0] = '\0';
2539 }
2541 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2543 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2546 "scenario.startpos_nations");
2549 "scenario.prevent_new_cities");
2552 "scenario.lake_flooding");
2555 "scenario.handmade");
2558 "scenario.allow_ai_type_fallback");
2559
2562 "scenario.ruleset_locked");
2563
2565 "scenario.datafile");
2566 if (buf[0] != '\0') {
2568 }
2569
2570 sg_failure_ret(loading->server_state == S_S_INITIAL
2571 || (loading->server_state == S_S_RUNNING
2572 && game.scenario.players),
2573 "Invalid scenario definition (server state '%s' and "
2574 "players are %s).",
2575 server_states_name(loading->server_state),
2576 game.scenario.players ? "saved" : "not saved");
2577}
2578
2579/************************************************************************/
2583{
2584 struct entry *mod_entry;
2585 int game_version;
2586
2587 /* Check status and return if not OK (sg_success FALSE). */
2588 sg_check_ret();
2589
2590 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2591#ifdef EMERGENCY_VERSION
2593#endif /* EMERGENCY_VERSION */
2594 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2595
2596 if (!saving->scenario || !game.scenario.is_scenario) {
2597 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2598 return;
2599 }
2600
2601 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2602
2603 /* Name is mandatory to the level that is saved even if empty. */
2604 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2606
2607 /* Authors list is saved only if it exist */
2608 if (game.scenario.authors[0] != '\0') {
2610 "scenario.authors");
2612 }
2613
2614 /* Description is saved only if it exist */
2615 if (game.scenario_desc.description[0] != '\0') {
2617 "scenario.description");
2619 }
2620
2621 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2622 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2624 "scenario.startpos_nations");
2627 "scenario.prevent_new_cities");
2628 }
2630 "scenario.lake_flooding");
2631 if (game.scenario.handmade) {
2633 "scenario.handmade");
2634 }
2637 "scenario.allow_ai_type_fallback");
2638 }
2639
2640 if (game.scenario.datafile[0] != '\0') {
2642 "scenario.datafile");
2643 }
2645 "scenario.ruleset_locked");
2646 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2648 "scenario.ruleset_caps");
2649 }
2650}
2651
2652/* =======================================================================
2653 * Load / save game settings.
2654 * ======================================================================= */
2655
2656/************************************************************************/
2660{
2661 /* Check status and return if not OK (sg_success FALSE). */
2662 sg_check_ret();
2663
2664 settings_game_load(loading->file, "settings");
2665
2666 /* Save current status of fogofwar. */
2668
2669 /* Add all compatibility settings here. */
2670}
2671
2672/************************************************************************/
2676{
2678
2679 /* Check status and return if not OK (sg_success FALSE). */
2680 sg_check_ret();
2681
2682 if (saving->scenario) {
2683 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2684 }
2685
2686 settings_game_save(saving->file, "settings");
2687 /* Restore real map generator. */
2689
2690 /* Add all compatibility settings here. */
2691}
2692
2693
2694/************************************************************************/
2698{
2699 struct city *pcity;
2700 int i, j;
2701 size_t length, length2;
2702 int *city_count;
2704 "savefile.city_counters_order_size");
2705
2706 if (0==length) {
2707
2708 return;
2709 }
2710
2711 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2712
2713 sg_failure_ret(loading->counter.order != 0,
2714 "Failed to load counter's ruleset order: %s",
2715 secfile_error());
2716 sg_failure_ret(loading->counter.size = length,
2717 "Counter vector in savegame have bad size: %s",
2718 secfile_error());
2719
2720 int corder[length];
2721
2722 for (i = 0; i < length; i++) {
2723
2724 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2726 }
2727
2728 i = 0;
2729 while (NULL != (city_count =
2731 "counters.c%d", i))) {
2732
2733 sg_failure_ret((length2 -1 == (size_t) length), ( "Bad city counters vector size. Should be " SIZE_T_PRINTF ". Is " SIZE_T_PRINTF "." ), length, length2 - 1);
2734
2735 pcity = game_city_by_number(city_count[0]);
2736
2737 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2738
2739 for (j = 0; j < length; j++) {
2740
2741 pcity->counter_values[corder[j]] = city_count[j+1];
2742 }
2743 i++;
2744 }
2745}
2746
2747/************************************************************************/
2751{
2752 /* Check status and return if not OK (sg_success FALSE). */
2753 sg_check_ret();
2754
2755 const char **countnames;;
2756 int *countvalues;
2757 int i, j, count;
2758
2760
2761 secfile_insert_int(saving->file, count,
2762 "savefile.city_counters_order_size");
2763
2764 if (0 == count) {
2765
2766 return;
2767 }
2768
2769 countnames = fc_calloc(count, sizeof(*countnames));
2770 for (j = 0; j < count; j++) {
2772 }
2773
2775 "savefile.city_counters_order_vector");
2776
2778
2779 // Saving city's counters
2780
2781 j = 0;
2782 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2783
2785
2786 city_list_iterate(_pplayer->cities, pcity) {
2787
2788 countvalues[0] = pcity->id;
2789 for (i = 0; i < count; ++i) {
2790
2791 countvalues[i+1] = pcity->counter_values[i];
2792 }
2793
2794 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2795 ++j;
2798
2800}
2801
2802/* =======================================================================
2803 * Load / save the main map.
2804 * ======================================================================= */
2805
2806/************************************************************************/
2809static void sg_load_map(struct loaddata *loading)
2810{
2811 /* Check status and return if not OK (sg_success FALSE). */
2812 sg_check_ret();
2813
2814 /* This defaults to TRUE even if map has not been generated.
2815 * We rely on that
2816 * 1) scenario maps have it explicitly right.
2817 * 2) when map is actually generated, it re-initialize this to FALSE. */
2819 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2821 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2822
2824
2825 /* Savegame may have stored random_seed for documentation purposes only,
2826 * but we want to keep it for resaving. */
2828 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2829
2830 if (S_S_INITIAL == loading->server_state
2832 /* Generator MAPGEN_SCENARIO is used;
2833 * this map was done with the map editor. */
2834
2835 /* Load tiles. */
2839
2840 /* Nothing more needed for a scenario. */
2841 return;
2842 }
2843
2844 if (S_S_INITIAL == loading->server_state) {
2845 /* Nothing more to do if it is not a scenario but in initial state. */
2846 return;
2847 }
2848
2855}
2856
2857/************************************************************************/
2860static void sg_save_map(struct savedata *saving)
2861{
2862 /* Check status and return if not OK (sg_success FALSE). */
2863 sg_check_ret();
2864
2865 if (map_is_empty()) {
2866 /* No map. */
2867 return;
2868 }
2869
2870 if (saving->scenario) {
2872 "map.have_huts");
2874 "map.have_resources");
2875 } else {
2876 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2877 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2878 }
2879
2880 /* For debugging purposes only.
2881 * Do not save it if it's 0 (not known);
2882 * this confuses people reading this 'document' less than
2883 * saving 0. */
2884 if (wld.map.server.seed != 0) {
2886 "map.random_seed");
2887 }
2888
2895}
2896
2897/************************************************************************/
2901{
2902 /* Check status and return if not OK (sg_success FALSE). */
2903 sg_check_ret();
2904
2905 /* Initialize the map for the current topology. 'map.xsize' and
2906 * 'map.ysize' must be set. */
2908
2909 /* Allocate map. */
2911
2912 /* get the terrain type */
2913 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2914 "map.t%04d");
2916
2917 /* Check for special tile sprites. */
2918 whole_map_iterate(&(wld.map), ptile) {
2919 const char *spec_sprite;
2920 const char *label;
2921 int nat_x, nat_y;
2922
2924 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2925 nat_x, nat_y);
2926 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2927 nat_x, nat_y);
2928 if (NULL != ptile->spec_sprite) {
2929 ptile->spec_sprite = fc_strdup(spec_sprite);
2930 }
2931 if (label != NULL) {
2932 tile_set_label(ptile, label);
2933 }
2935}
2936
2937/************************************************************************/
2941{
2942 /* Check status and return if not OK (sg_success FALSE). */
2943 sg_check_ret();
2944
2945 /* Save the terrain type. */
2946 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2947 "map.t%04d");
2948
2949 /* Save special tile sprites. */
2950 whole_map_iterate(&(wld.map), ptile) {
2951 int nat_x, nat_y;
2952
2954 if (ptile->spec_sprite) {
2955 secfile_insert_str(saving->file, ptile->spec_sprite,
2956 "map.spec_sprite_%d_%d", nat_x, nat_y);
2957 }
2958 if (ptile->label != NULL) {
2959 secfile_insert_str(saving->file, ptile->label,
2960 "map.label_%d_%d", nat_x, nat_y);
2961 }
2963}
2964
2965/************************************************************************/
2969{
2970 /* Check status and return if not OK (sg_success FALSE). */
2971 sg_check_ret();
2972
2973 /* Load extras. */
2974 halfbyte_iterate_extras(j, loading->extra.size) {
2975 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
2976 loading->extra.order + 4 * j),
2977 loading->file, "map.e%02d_%04d", j);
2979
2980 if (S_S_INITIAL != loading->server_state
2983 whole_map_iterate(&(wld.map), ptile) {
2985 if (tile_has_extra(ptile, pres)) {
2986 tile_set_resource(ptile, pres);
2987
2988 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
2989 BV_CLR(ptile->extras, extra_index(pres));
2990 }
2991 }
2994 }
2995}
2996
2997/************************************************************************/
3001{
3002 /* Check status and return if not OK (sg_success FALSE). */
3003 sg_check_ret();
3004
3005 /* Save extras. */
3007 int mod[4];
3008 int l;
3009
3010 for (l = 0; l < 4; l++) {
3011 if (4 * j + 1 > game.control.num_extra_types) {
3012 mod[l] = -1;
3013 } else {
3014 mod[l] = 4 * j + l;
3015 }
3016 }
3017 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3018 saving->file, "map.e%02d_%04d", j);
3020}
3021
3022/************************************************************************/
3027{
3028 struct nation_type *pnation;
3029 struct startpos *psp;
3030 struct tile *ptile;
3031 const char SEPARATOR = '#';
3032 const char *nation_names;
3033 int nat_x, nat_y;
3034 bool exclude;
3035 int i, startpos_count;
3036
3037 /* Check status and return if not OK (sg_success FALSE). */
3038 sg_check_ret();
3039
3041 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3042
3043 if (0 == startpos_count) {
3044 /* Nothing to do. */
3045 return;
3046 }
3047
3048 for (i = 0; i < startpos_count; i++) {
3049 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3050 || !secfile_lookup_int(loading->file, &nat_y,
3051 "map.startpos%d.y", i)) {
3052 log_sg("Warning: Undefined coordinates for startpos %d", i);
3053 continue;
3054 }
3055
3056 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3057 if (NULL == ptile) {
3058 log_error("Start position native coordinates (%d, %d) do not exist "
3059 "in this map. Skipping...", nat_x, nat_y);
3060 continue;
3061 }
3062
3063 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3064 "map.startpos%d.exclude", i);
3065
3066 psp = map_startpos_new(ptile);
3067
3069 "map.startpos%d.nations", i);
3070 if (NULL != nation_names && '\0' != nation_names[0]) {
3071 const size_t size = strlen(nation_names) + 1;
3072 char buf[size], *start, *end;
3073
3075 for (start = buf - 1; NULL != start; start = end) {
3076 start++;
3077 if ((end = strchr(start, SEPARATOR))) {
3078 *end = '\0';
3079 }
3080
3081 pnation = nation_by_rule_name(start);
3082 if (NO_NATION_SELECTED != pnation) {
3083 if (exclude) {
3084 startpos_disallow(psp, pnation);
3085 } else {
3086 startpos_allow(psp, pnation);
3087 }
3088 } else {
3089 log_verbose("Missing nation \"%s\".", start);
3090 }
3091 }
3092 }
3093 }
3094
3095 if (0 < map_startpos_count()
3096 && loading->server_state == S_S_INITIAL
3098 log_verbose("Number of starts (%d) are lower than rules.max_players "
3099 "(%d), lowering rules.max_players.",
3102 }
3103
3104 /* Re-initialize nation availability in light of start positions.
3105 * This has to be after loading [scenario] and [map].startpos and
3106 * before we seek nations for players. */
3108}
3109
3110/************************************************************************/
3114{
3115 struct tile *ptile;
3116 const char SEPARATOR = '#';
3117 int i = 0;
3118
3119 /* Check status and return if not OK (sg_success FALSE). */
3120 sg_check_ret();
3121
3123 return;
3124 }
3125
3127 "map.startpos_count");
3128
3130 int nat_x, nat_y;
3131
3132 ptile = startpos_tile(psp);
3133
3135 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3136 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3137
3139 "map.startpos%d.exclude", i);
3140 if (startpos_allows_all(psp)) {
3141 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3142 } else {
3143 const struct nation_hash *nations = startpos_raw_nations(psp);
3145
3146 nation_names[0] = '\0';
3147 nation_hash_iterate(nations, pnation) {
3148 if ('\0' == nation_names[0]) {
3150 sizeof(nation_names));
3151 } else {
3153 "%c%s", SEPARATOR, nation_rule_name(pnation));
3154 }
3157 "map.startpos%d.nations", i);
3158 }
3159 i++;
3161
3163}
3164
3165/************************************************************************/
3169{
3170 int x, y;
3171 struct tile *claimer = NULL;
3172 struct extra_type *placing = NULL;
3173
3174 /* Check status and return if not OK (sg_success FALSE). */
3175 sg_check_ret();
3176
3177 if (game.info.is_new_game) {
3178 /* No owner/source information for a new game / scenario. */
3179 return;
3180 }
3181
3182 /* Owner, ownership source, and infra turns are stored as plain numbers */
3183 for (y = 0; y < wld.map.ysize; y++) {
3184 const char *buffer1 = secfile_lookup_str(loading->file,
3185 "map.owner%04d", y);
3186 const char *buffer2 = secfile_lookup_str(loading->file,
3187 "map.source%04d", y);
3188 const char *buffer3 = secfile_lookup_str(loading->file,
3189 "map.eowner%04d", y);
3191 NULL,
3192 "map.placing%04d", y);
3194 NULL,
3195 "map.infra_turns%04d", y);
3196 const char *ptr1 = buffer1;
3197 const char *ptr2 = buffer2;
3198 const char *ptr3 = buffer3;
3199 const char *ptr_placing = buffer_placing;
3200 const char *ptr_turns = buffer_turns;
3201
3205
3206 for (x = 0; x < wld.map.xsize; x++) {
3207 char token1[TOKEN_SIZE];
3208 char token2[TOKEN_SIZE];
3209 char token3[TOKEN_SIZE];
3211 char token_turns[TOKEN_SIZE];
3212 struct player *owner = NULL;
3213 struct player *eowner = NULL;
3214 int turns;
3215 int number;
3216 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3217
3218 scanin(&ptr1, ",", token1, sizeof(token1));
3219 sg_failure_ret(token1[0] != '\0',
3220 "Map size not correct (map.owner%d).", y);
3221 if (strcmp(token1, "-") == 0) {
3222 owner = NULL;
3223 } else {
3225 "Got map owner %s in (%d, %d).", token1, x, y);
3226 owner = player_by_number(number);
3227 }
3228
3229 scanin(&ptr2, ",", token2, sizeof(token2));
3230 sg_failure_ret(token2[0] != '\0',
3231 "Map size not correct (map.source%d).", y);
3232 if (strcmp(token2, "-") == 0) {
3233 claimer = NULL;
3234 } else {
3236 "Got map source %s in (%d, %d).", token2, x, y);
3237 claimer = index_to_tile(&(wld.map), number);
3238 }
3239
3240 scanin(&ptr3, ",", token3, sizeof(token3));
3241 sg_failure_ret(token3[0] != '\0',
3242 "Map size not correct (map.eowner%d).", y);
3243 if (strcmp(token3, "-") == 0) {
3244 eowner = NULL;
3245 } else {
3247 "Got base owner %s in (%d, %d).", token3, x, y);
3248 eowner = player_by_number(number);
3249 }
3250
3251 if (ptr_placing != NULL) {
3253 sg_failure_ret(token_placing[0] != '\0',
3254 "Map size not correct (map.placing%d).", y);
3255 if (strcmp(token_placing, "-") == 0) {
3256 placing = NULL;
3257 } else {
3259 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3260 placing = extra_by_number(number);
3261 }
3262 } else {
3263 placing = NULL;
3264 }
3265
3266 if (ptr_turns != NULL) {
3267 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3268 sg_failure_ret(token_turns[0] != '\0',
3269 "Map size not correct (map.infra_turns%d).", y);
3271 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3272 turns = number;
3273 } else {
3274 turns = 1;
3275 }
3276
3278 tile_claim_bases(ptile, eowner);
3279 ptile->placing = placing;
3280 ptile->infra_turns = turns;
3281 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3282 }
3283 }
3284}
3285
3286/************************************************************************/
3290{
3291 int x, y;
3292
3293 /* Check status and return if not OK (sg_success FALSE). */
3294 sg_check_ret();
3295
3296 if (saving->scenario && !saving->save_players) {
3297 /* Nothing to do for a scenario without saved players. */
3298 return;
3299 }
3300
3301 /* Store owner and ownership source as plain numbers. */
3302 for (y = 0; y < wld.map.ysize; y++) {
3303 char line[wld.map.xsize * TOKEN_SIZE];
3304
3305 line[0] = '\0';
3306 for (x = 0; x < wld.map.xsize; x++) {
3307 char token[TOKEN_SIZE];
3308 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3309
3310 if (!saving->save_players || tile_owner(ptile) == NULL) {
3311 strcpy(token, "-");
3312 } else {
3313 fc_snprintf(token, sizeof(token), "%d",
3314 player_number(tile_owner(ptile)));
3315 }
3316 strcat(line, token);
3317 if (x + 1 < wld.map.xsize) {
3318 strcat(line, ",");
3319 }
3320 }
3321 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3322 }
3323
3324 for (y = 0; y < wld.map.ysize; y++) {
3325 char line[wld.map.xsize * TOKEN_SIZE];
3326
3327 line[0] = '\0';
3328 for (x = 0; x < wld.map.xsize; x++) {
3329 char token[TOKEN_SIZE];
3330 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3331
3332 if (ptile->claimer == NULL) {
3333 strcpy(token, "-");
3334 } else {
3335 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3336 }
3337 strcat(line, token);
3338 if (x + 1 < wld.map.xsize) {
3339 strcat(line, ",");
3340 }
3341 }
3342 secfile_insert_str(saving->file, line, "map.source%04d", y);
3343 }
3344
3345 for (y = 0; y < wld.map.ysize; y++) {
3346 char line[wld.map.xsize * TOKEN_SIZE];
3347
3348 line[0] = '\0';
3349 for (x = 0; x < wld.map.xsize; x++) {
3350 char token[TOKEN_SIZE];
3351 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3352
3353 if (!saving->save_players || extra_owner(ptile) == NULL) {
3354 strcpy(token, "-");
3355 } else {
3356 fc_snprintf(token, sizeof(token), "%d",
3357 player_number(extra_owner(ptile)));
3358 }
3359 strcat(line, token);
3360 if (x + 1 < wld.map.xsize) {
3361 strcat(line, ",");
3362 }
3363 }
3364 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3365 }
3366
3367 for (y = 0; y < wld.map.ysize; y++) {
3368 char line[wld.map.xsize * TOKEN_SIZE];
3369
3370 line[0] = '\0';
3371 for (x = 0; x < wld.map.xsize; x++) {
3372 char token[TOKEN_SIZE];
3373 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3374
3375 if (ptile->placing == NULL) {
3376 strcpy(token, "-");
3377 } else {
3378 fc_snprintf(token, sizeof(token), "%d",
3379 extra_number(ptile->placing));
3380 }
3381 strcat(line, token);
3382 if (x + 1 < wld.map.xsize) {
3383 strcat(line, ",");
3384 }
3385 }
3386 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3387 }
3388
3389 for (y = 0; y < wld.map.ysize; y++) {
3390 char line[wld.map.xsize * TOKEN_SIZE];
3391
3392 line[0] = '\0';
3393 for (x = 0; x < wld.map.xsize; x++) {
3394 char token[TOKEN_SIZE];
3395 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3396
3397 if (ptile->placing != NULL) {
3398 fc_snprintf(token, sizeof(token), "%d",
3399 ptile->infra_turns);
3400 } else {
3401 fc_snprintf(token, sizeof(token), "0");
3402 }
3403 strcat(line, token);
3404 if (x + 1 < wld.map.xsize) {
3405 strcat(line, ",");
3406 }
3407 }
3408 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3409 }
3410}
3411
3412/************************************************************************/
3416{
3417 int x, y;
3418
3419 /* Check status and return if not OK (sg_success FALSE). */
3420 sg_check_ret();
3421
3422 sg_failure_ret(loading->worked_tiles == NULL,
3423 "City worked map not loaded!");
3424
3425 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3426 sizeof(*loading->worked_tiles));
3427
3428 for (y = 0; y < wld.map.ysize; y++) {
3429 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3430 y);
3431 const char *ptr = buffer;
3432
3433 sg_failure_ret(NULL != buffer,
3434 "Savegame corrupt - map line %d not found.", y);
3435 for (x = 0; x < wld.map.xsize; x++) {
3436 char token[TOKEN_SIZE];
3437 int number;
3438 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3439
3440 scanin(&ptr, ",", token, sizeof(token));
3441 sg_failure_ret('\0' != token[0],
3442 "Savegame corrupt - map size not correct.");
3443 if (strcmp(token, "-") == 0) {
3444 number = -1;
3445 } else {
3446 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3447 "Savegame corrupt - got tile worked by city "
3448 "id=%s in (%d, %d).", token, x, y);
3449 }
3450
3451 loading->worked_tiles[ptile->index] = number;
3452 }
3453 }
3454}
3455
3456/************************************************************************/
3460{
3461 int x, y;
3462
3463 /* Check status and return if not OK (sg_success FALSE). */
3464 sg_check_ret();
3465
3466 if (saving->scenario && !saving->save_players) {
3467 /* Nothing to do for a scenario without saved players. */
3468 return;
3469 }
3470
3471 /* additionally save the tiles worked by the cities */
3472 for (y = 0; y < wld.map.ysize; y++) {
3473 char line[wld.map.xsize * TOKEN_SIZE];
3474
3475 line[0] = '\0';
3476 for (x = 0; x < wld.map.xsize; x++) {
3477 char token[TOKEN_SIZE];
3478 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3479 struct city *pcity = tile_worked(ptile);
3480
3481 if (pcity == NULL) {
3482 strcpy(token, "-");
3483 } else {
3484 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3485 }
3486 strcat(line, token);
3487 if (x < wld.map.xsize) {
3488 strcat(line, ",");
3489 }
3490 }
3491 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3492 }
3493}
3494
3495/************************************************************************/
3499{
3500 /* Check status and return if not OK (sg_success FALSE). */
3501 sg_check_ret();
3502
3503 players_iterate(pplayer) {
3504 /* Allocate player private map here; it is needed in different modules
3505 * besides this one ((i.e. sg_load_player_*()). */
3506 player_map_init(pplayer);
3508
3510 "game.save_known")) {
3511 int lines = player_slot_max_used_number()/32 + 1, j, p, l, i;
3512 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3513
3514 for (l = 0; l < lines; l++) {
3515 for (j = 0; j < 8; j++) {
3516 for (i = 0; i < 4; i++) {
3517 /* Only bother trying to load the map for this halfbyte if at least
3518 * one of the corresponding player slots is in use. */
3519 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3520 LOAD_MAP_CHAR(ch, ptile,
3521 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3522 |= ascii_hex2bin(ch, j),
3523 loading->file, "map.k%02d_%04d", l * 8 + j);
3524 break;
3525 }
3526 }
3527 }
3528 }
3529
3530 players_iterate(pplayer) {
3531 dbv_clr_all(&pplayer->tile_known);
3533
3534 /* HACK: we read the known data from hex into 32-bit integers, and
3535 * now we convert it to the known tile data of each player. */
3536 whole_map_iterate(&(wld.map), ptile) {
3537 players_iterate(pplayer) {
3538 p = player_index(pplayer);
3539 l = player_index(pplayer) / 32;
3540
3541 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3542 map_set_known(ptile, pplayer);
3543 }
3546
3547 FC_FREE(known);
3548 }
3549}
3550
3551/************************************************************************/
3555{
3556 /* Check status and return if not OK (sg_success FALSE). */
3557 sg_check_ret();
3558
3559 if (!saving->save_players) {
3560 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3561 return;
3562 } else {
3563 int lines = player_slot_max_used_number()/32 + 1;
3564
3566 "game.save_known");
3568 int j, p, l, i;
3569 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3570
3571 /* HACK: we convert the data into a 32-bit integer, and then save it as
3572 * hex. */
3573
3574 whole_map_iterate(&(wld.map), ptile) {
3575 players_iterate(pplayer) {
3576 if (map_is_known(ptile, pplayer)) {
3577 p = player_index(pplayer);
3578 l = p / 32;
3579 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3580 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3581 }
3584
3585 for (l = 0; l < lines; l++) {
3586 for (j = 0; j < 8; j++) {
3587 for (i = 0; i < 4; i++) {
3588 /* Only bother saving the map for this halfbyte if at least one
3589 * of the corresponding player slots is in use */
3590 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3591 /* put 4-bit segments of the 32-bit "known" field */
3593 + tile_index(ptile)], j),
3594 saving->file, "map.k%02d_%04d", l * 8 + j);
3595 break;
3596 }
3597 }
3598 }
3599 }
3600
3601 FC_FREE(known);
3602 }
3603 }
3604}
3605
3606/* =======================================================================
3607 * Load / save player data.
3608 *
3609 * This is split into two parts as some data can only be loaded if the
3610 * number of players is known and the corresponding player slots are
3611 * defined.
3612 * ======================================================================= */
3613
3614/************************************************************************/
3618{
3619 int i, k, nplayers;
3620 const char *str;
3621 bool shuffle_loaded = TRUE;
3622
3623 /* Check status and return if not OK (sg_success FALSE). */
3624 sg_check_ret();
3625
3626 if (S_S_INITIAL == loading->server_state
3627 || game.info.is_new_game) {
3628 /* Nothing more to do. */
3629 return;
3630 }
3631
3632 /* Load destroyed wonders: */
3634 "players.destroyed_wonders");
3635 sg_failure_ret(str != NULL, "%s", secfile_error());
3636 sg_failure_ret(strlen(str) == loading->improvement.size,
3637 "Invalid length for 'players.destroyed_wonders' ("
3638 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3639 strlen(str), loading->improvement.size);
3640 for (k = 0; k < loading->improvement.size; k++) {
3641 sg_failure_ret(str[k] == '1' || str[k] == '0',
3642 "Undefined value '%c' within "
3643 "'players.destroyed_wonders'.", str[k]);
3644
3645 if (str[k] == '1') {
3646 struct impr_type *pimprove =
3647 improvement_by_rule_name(loading->improvement.order[k]);
3648 if (pimprove) {
3651 }
3652 }
3653 }
3654
3655 server.identity_number
3656 = secfile_lookup_int_default(loading->file, server.identity_number,
3657 "players.identity_number_used");
3658
3659 /* First remove all defined players. */
3660 players_iterate(pplayer) {
3661 server_remove_player(pplayer);
3663
3664 /* Now, load the players from the savefile. */
3665 player_slots_iterate(pslot) {
3666 struct player *pplayer;
3667 struct rgbcolor *prgbcolor = NULL;
3668 int pslot_id = player_slot_index(pslot);
3669
3670 if (NULL == secfile_section_lookup(loading->file, "player%d",
3671 pslot_id)) {
3672 continue;
3673 }
3674
3675 /* Get player AI type. */
3676 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3677 player_slot_index(pslot));
3678 sg_failure_ret(str != NULL, "%s", secfile_error());
3679
3680 /* Get player color */
3681 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3682 pslot_id)) {
3683 if (game_was_started()) {
3684 log_sg("Game has started, yet player %d has no color defined.",
3685 pslot_id);
3686 /* This will be fixed up later */
3687 } else {
3688 log_verbose("No color defined for player %d.", pslot_id);
3689 /* Colors will be assigned on game start, or at end of savefile
3690 * loading if game has already started */
3691 }
3692 }
3693
3694 /* Create player. */
3695 pplayer = server_create_player(player_slot_index(pslot), str,
3696 prgbcolor,
3699 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3700
3701 server_player_init(pplayer, FALSE, FALSE);
3702
3703 /* Free the color definition. */
3705
3706 /* Multipliers (policies) */
3707
3708 /* First initialise player values with ruleset defaults; this will
3709 * cover any in the ruleset not known when the savefile was created. */
3710 multipliers_iterate(pmul) {
3711 pplayer->multipliers[multiplier_index(pmul)].value
3712 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3714
3715 /* Now override with any values from the savefile. */
3716 for (k = 0; k < loading->multiplier.size; k++) {
3717 const struct multiplier *pmul = loading->multiplier.order[k];
3718
3719 if (pmul) {
3721 int val =
3723 "player%d.multiplier%d.val",
3724 player_slot_index(pslot), k);
3725 int rval = (((CLIP(pmul->start, val, pmul->stop)
3726 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3727
3728 if (rval != val) {
3729 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3730 "was %d, clamped to %d", pslot_id,
3731 multiplier_rule_name(pmul), val, rval);
3732 }
3733 pplayer->multipliers[idx].value = rval;
3734
3735 val =
3737 pplayer->multipliers[idx].value,
3738 "player%d.multiplier%d.target",
3739 player_slot_index(pslot), k);
3740 rval = (((CLIP(pmul->start, val, pmul->stop)
3741 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3742
3743 if (rval != val) {
3744 log_verbose("Player %d had illegal value for multiplier_target "
3745 " \"%s\": was %d, clamped to %d", pslot_id,
3746 multiplier_rule_name(pmul), val, rval);
3747 }
3748 pplayer->multipliers[idx].target = rval;
3749
3750 pplayer->multipliers[idx].changed
3752 "player%d.multiplier%d.changed",
3753 player_slot_index(pslot), k);
3754 } /* else silently discard multiplier not in current ruleset */
3755 }
3756
3757 /* Must be loaded before tile owner is set. */
3758 pplayer->server.border_vision =
3760 "player%d.border_vision",
3761 player_slot_index(pslot));
3762
3764 "player%d.autoselect_weight",
3765 pslot_id);
3767
3768 /* check number of players */
3769 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3770 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3771 "(%d) from the loaded game does not match the number of "
3772 "players present (%d).", nplayers, player_count());
3773
3774 /* Load team information. */
3775 players_iterate(pplayer) {
3776 int team;
3777 struct team_slot *tslot = NULL;
3778
3780 "player%d.team_no",
3781 player_number(pplayer))
3783 "Invalid team definition for player %s (nb %d).",
3784 player_name(pplayer), player_number(pplayer));
3785 /* Should never fail when slot given is not NULL */
3786 team_add_player(pplayer, team_new(tslot));
3788
3789 /* Loading the shuffle list is quite complex. At the time of saving the
3790 * shuffle data is saved as
3791 * shuffled_player_<number> = player_slot_id
3792 * where number is an increasing number and player_slot_id is a number
3793 * between 0 and the maximum number of player slots. Now we have to create
3794 * a list
3795 * shuffler_players[number] = player_slot_id
3796 * where all player slot IDs are used exactly one time. The code below
3797 * handles this ... */
3798 if (secfile_lookup_int_default(loading->file, -1,
3799 "players.shuffled_player_%d", 0) >= 0) {
3800 int slots = player_slot_count();
3801 int plrcount = player_count();
3804
3805 for (i = 0; i < slots; i++) {
3806 /* Array to save used numbers. */
3808 /* List of all player IDs (needed for set_shuffled_players()). It is
3809 * initialised with the value -1 to indicate that no value is set. */
3810 shuffled_players[i] = -1;
3811 }
3812
3813 /* Load shuffled player list. */
3814 for (i = 0; i < plrcount; i++) {
3815 int shuffle
3817 "players.shuffled_player_%d", i);
3818
3819 if (shuffle == -1) {
3820 log_sg("Missing player shuffle information (index %d) "
3821 "- reshuffle player list!", i);
3823 break;
3824 } else if (shuffled_player_set[shuffle]) {
3825 log_sg("Player shuffle %d used two times "
3826 "- reshuffle player list!", shuffle);
3828 break;
3829 }
3830 /* Set this ID as used. */
3832
3833 /* Save the player ID in the shuffle list. */
3835 }
3836
3837 if (shuffle_loaded) {
3838 /* Insert missing numbers. */
3839 int shuffle_index = plrcount;
3840
3841 for (i = 0; i < slots; i++) {
3842 if (!shuffled_player_set[i]) {
3844 }
3845
3846 /* shuffle_index must not grow higher than size of shuffled_players. */
3848 "Invalid player shuffle data!");
3849 }
3850
3851#ifdef FREECIV_DEBUG
3852 log_debug("[load shuffle] player_count() = %d", player_count());
3853 player_slots_iterate(pslot) {
3854 int plrid = player_slot_index(pslot);
3855
3856 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3858 shuffled_player_set[plrid] ? "is used" : "-");
3860#endif /* FREECIV_DEBUG */
3861
3862 /* Set shuffle list from savegame. */
3864 }
3865 }
3866
3867 if (!shuffle_loaded) {
3868 /* No shuffled players included or error loading them, so shuffle them
3869 * (this may include scenarios). */
3871 }
3872}
3873
3874/************************************************************************/
3878{
3879 /* Check status and return if not OK (sg_success FALSE). */
3880 sg_check_ret();
3881
3882 if (game.info.is_new_game) {
3883 /* Nothing to do. */
3884 return;
3885 }
3886
3887 players_iterate(pplayer) {
3888 sg_load_player_main(loading, pplayer);
3890 sg_load_player_units(loading, pplayer);
3892
3893 /* Check the success of the functions above. */
3894 sg_check_ret();
3895
3896 /* Print out some information */
3897 if (is_ai(pplayer)) {
3898 log_normal(_("%s has been added as %s level AI-controlled player "
3899 "(%s)."), player_name(pplayer),
3900 ai_level_translated_name(pplayer->ai_common.skill_level),
3901 ai_name(pplayer->ai));
3902 } else {
3903 log_normal(_("%s has been added as human player."),
3904 player_name(pplayer));
3905 }
3907
3908 /* Also load the transport status of the units here. It must be a special
3909 * case as all units must be known (unit on an allied transporter). */
3910 players_iterate(pplayer) {
3911 /* Load unit transport status. */
3914
3915 /* Savegame may contain nation assignments that are incompatible with the
3916 * current nationset. Ensure they are compatible, one way or another. */
3918
3919 /* Some players may have invalid nations in the ruleset. Once all players
3920 * are loaded, pick one of the remaining nations for them. */
3921 players_iterate(pplayer) {
3922 if (pplayer->nation == NO_NATION_SELECTED) {
3925 /* TRANS: Minor error message: <Leader> ... <Poles>. */
3926 log_sg(_("%s had invalid nation; changing to %s."),
3927 player_name(pplayer), nation_plural_for_player(pplayer));
3928
3929 ai_traits_init(pplayer);
3930 }
3932
3933 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
3936 if (pplayers_allied(plr, aplayer)) {
3938 DS_ALLIANCE);
3939
3942 log_sg("Illegal alliance structure detected: "
3943 "%s alliance to %s reduced to peace treaty.",
3948 }
3949 }
3952
3953 /* Update cached city illness. This can depend on trade routes,
3954 * so can't be calculated until all players have been loaded. */
3955 if (game.info.illness_on) {
3956 cities_iterate(pcity) {
3957 pcity->server.illness
3958 = city_illness_calc(pcity, NULL, NULL,
3959 &(pcity->illness_trade), NULL);
3961 }
3962
3963 /* Update all city information. This must come after all cities are
3964 * loaded (in player_load) but before player (dumb) cities are loaded
3965 * in player_load_vision(). */
3966 players_iterate(plr) {
3967 city_list_iterate(plr->cities, pcity) {
3968 city_refresh(pcity);
3969 sanity_check_city(pcity);
3970 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
3973
3974 /* Since the cities must be placed on the map to put them on the
3975 player map we do this afterwards */
3976 players_iterate(pplayer) {
3978 /* Check the success of the function above. */
3979 sg_check_ret();
3981
3982 /* Check shared vision and tiles. */
3983 players_iterate(pplayer) {
3984 BV_CLR_ALL(pplayer->gives_shared_vision);
3985 BV_CLR_ALL(pplayer->gives_shared_tiles);
3986 BV_CLR_ALL(pplayer->server.really_gives_vision);
3988
3989 /* Set up shared vision... */
3990 players_iterate(pplayer) {
3991 int plr1 = player_index(pplayer);
3992
3994 int plr2 = player_index(pplayer2);
3995
3997 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
3998 give_shared_vision(pplayer, pplayer2);
3999 }
4001 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4002 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4003 }
4006
4007 /* ...and check it */
4010 /* TODO: Is there a good reason player is not marked as
4011 * giving shared vision to themselves -> really_gives_vision()
4012 * returning FALSE when pplayer1 == pplayer2 */
4013 if (pplayer1 != pplayer2
4016 sg_regr(3000900,
4017 _("%s did not give shared vision to team member %s."),
4020 }
4022 sg_regr(3000900,
4023 _("%s did not give shared vision to team member %s."),
4026 }
4027 }
4030
4033
4034 /* All vision is ready; this calls city_thaw_workers_queue(). */
4036
4037 /* Make sure everything is consistent. */
4038 players_iterate(pplayer) {
4039 unit_list_iterate(pplayer->units, punit) {
4041 struct tile *ptile = unit_tile(punit);
4042
4043 log_sg("%s doing illegal activity in savegame!",
4045 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4049 : "missing",
4050 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4052 }
4055
4056 cities_iterate(pcity) {
4057 city_refresh(pcity);
4058 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4060
4061 /* Player colors are always needed once game has started. Pre-2.4 savegames
4062 * lack them. This cannot be in compatibility conversion layer as we need
4063 * all the player data available to be able to assign best colors. */
4064 if (game_was_started()) {
4066 }
4067}
4068
4069/************************************************************************/
4072static void sg_save_players(struct savedata *saving)
4073{
4074 /* Check status and return if not OK (sg_success FALSE). */
4075 sg_check_ret();
4076
4077 if ((saving->scenario && !saving->save_players)
4078 || !game_was_started()) {
4079 /* Nothing to do for a scenario without saved players or a game in
4080 * INITIAL state. */
4081 return;
4082 }
4083
4084 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4085
4086 /* Save destroyed wonders as bitvector. Note that improvement order
4087 * is saved in 'savefile.improvement.order'. */
4088 {
4089 char destroyed[B_LAST+1];
4090
4091 improvement_iterate(pimprove) {
4092 if (is_great_wonder(pimprove)
4093 && great_wonder_is_destroyed(pimprove)) {
4094 destroyed[improvement_index(pimprove)] = '1';
4095 } else {
4096 destroyed[improvement_index(pimprove)] = '0';
4097 }
4099 destroyed[improvement_count()] = '\0';
4101 "players.destroyed_wonders");
4102 }
4103
4104 secfile_insert_int(saving->file, server.identity_number,
4105 "players.identity_number_used");
4106
4107 /* Save player order. */
4108 {
4109 int i = 0;
4110 shuffled_players_iterate(pplayer) {
4111 secfile_insert_int(saving->file, player_number(pplayer),
4112 "players.shuffled_player_%d", i);
4113 i++;
4115 }
4116
4117 /* Sort units. */
4119
4120 /* Save players. */
4121 players_iterate(pplayer) {
4122 sg_save_player_main(saving, pplayer);
4123 sg_save_player_cities(saving, pplayer);
4124 sg_save_player_units(saving, pplayer);
4126 sg_save_player_vision(saving, pplayer);
4128}
4129
4130/************************************************************************/
4134 struct player *plr)
4135{
4136 const char **slist;
4137 int i, plrno = player_number(plr);
4138 const char *str;
4139 struct government *gov;
4140 const char *level;
4141 const char *barb_str;
4142 size_t nval;
4143 const char *kind;
4144
4145 /* Check status and return if not OK (sg_success FALSE). */
4146 sg_check_ret();
4147
4148 /* Basic player data. */
4149 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4150 sg_failure_ret(str != NULL, "%s", secfile_error());
4152 sz_strlcpy(plr->username,
4154 "player%d.username", plrno));
4156 "player%d.unassigned_user", plrno),
4157 "%s", secfile_error());
4160 "player%d.orig_username", plrno));
4163 "player%d.ranked_username",
4164 plrno));
4166 "player%d.unassigned_ranked", plrno),
4167 "%s", secfile_error());
4169 "player%d.delegation_username",
4170 plrno);
4171 /* Defaults to no delegation. */
4172 if (strlen(str)) {
4174 }
4175
4176 /* Player flags */
4177 BV_CLR_ALL(plr->flags);
4178 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4179 for (i = 0; i < nval; i++) {
4180 const char *sval = slist[i];
4182
4183 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4184
4185 BV_SET(plr->flags, fid);
4186 }
4187 free(slist);
4188
4189 /* Nation */
4190 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4192 if (plr->nation != NULL) {
4193 ai_traits_init(plr);
4194 }
4195
4196 /* Government */
4197 str = secfile_lookup_str(loading->file, "player%d.government_name",
4198 plrno);
4200 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4201 plrno, str);
4202 plr->government = gov;
4203
4204 /* Target government */
4206 "player%d.target_government_name", plrno);
4207 if (str != NULL) {
4209 } else {
4210 plr->target_government = NULL;
4211 }
4214 "player%d.revolution_finishes", plrno);
4215
4216 /* Load diplomatic data (diplstate + embassy + vision).
4217 * Shared vision is loaded in sg_load_players(). */
4219 players_iterate(pplayer) {
4220 char buf[32];
4221 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4222 i = player_index(pplayer);
4223
4224 /* Load diplomatic status */
4225 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4226
4227 ds->type =
4229 diplstate_type, "%s.current", buf);
4230 ds->max_state =
4232 diplstate_type, "%s.closest", buf);
4233
4234 /* FIXME: If either party is barbarian, we cannot enforce below check */
4235#if 0
4236 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4237 sg_regr(3020000,
4238 "Player%d: War with player %d who has never been met. "
4239 "Reverted to No Contact state.", plrno, i);
4240 ds->type = DS_NO_CONTACT;
4241 }
4242#endif
4243
4244 if (valid_dst_closest(ds) != ds->max_state) {
4245 sg_regr(3020000,
4246 "Player%d: closest diplstate to player %d less than current. "
4247 "Updated.", plrno, i);
4248 ds->max_state = ds->type;
4249 }
4250
4251 ds->first_contact_turn =
4253 "%s.first_contact_turn", buf);
4254 ds->turns_left =
4255 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4256 ds->has_reason_to_cancel =
4258 "%s.has_reason_to_cancel", buf);
4259 ds->contact_turns_left =
4261 "%s.contact_turns_left", buf);
4262
4263 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4264 buf)) {
4265 BV_SET(plr->real_embassy, i);
4266 }
4267 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4268 * must be known. */
4270
4271 /* load ai data */
4273 char buf[32];
4274
4275 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4277
4279 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4280 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4282
4284 "player%d.adv.wonder_city",
4285 plrno);
4286
4287 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4288
4289 /* Some sane defaults */
4290 plr->ai_common.fuzzy = 0;
4291 plr->ai_common.expand = 100;
4292 plr->ai_common.science_cost = 100;
4293
4294
4296 "player%d.ai.level", plrno);
4297 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4298 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4300 } else {
4302 }
4303
4305 log_sg("Player%d: Invalid AI level \"%s\". "
4306 "Changed to \"%s\".", plrno, level,
4309 }
4310
4312 "player%d.ai.barb_type", plrno);
4314
4316 log_sg("Player%d: Invalid barbarian type \"%s\". "
4317 "Changed to \"None\".", plrno, barb_str);
4319 }
4320
4321 if (is_barbarian(plr)) {
4322 server.nbarbarians++;
4323 }
4324
4325 if (is_ai(plr)) {
4327 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4328 }
4329
4330 /* Load nation style. */
4331 {
4332 struct nation_style *style;
4333
4334 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4335
4336 sg_failure_ret(str != NULL, "%s", secfile_error());
4337 style = style_by_rule_name(str);
4338 if (style == NULL) {
4339 style = style_by_number(0);
4340 log_sg("Player%d: unsupported city_style_name \"%s\". "
4341 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4342 }
4343 plr->style = style;
4344 }
4345
4347 "player%d.idle_turns", plrno),
4348 "%s", secfile_error());
4349 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4350 if (sex_by_name(kind) == SEX_MALE) {
4351 plr->is_male = TRUE;
4352 } else {
4353 plr->is_male = FALSE;
4354 }
4356 "player%d.is_alive", plrno),
4357 "%s", secfile_error());
4359 "player%d.turns_alive", plrno),
4360 "%s", secfile_error());
4362 "player%d.last_war", plrno),
4363 "%s", secfile_error());
4365 "player%d.phase_done", plrno);
4367 "player%d.gold", plrno),
4368 "%s", secfile_error());
4370 "player%d.rates.tax", plrno),
4371 "%s", secfile_error());
4373 "player%d.rates.science", plrno),
4374 "%s", secfile_error());
4376 "player%d.rates.luxury", plrno),
4377 "%s", secfile_error());
4379 "player%d.infrapts",
4380 plrno);
4381 plr->server.bulbs_last_turn =
4383 "player%d.research.bulbs_last_turn", plrno);
4384
4385 /* Traits */
4386 if (plr->nation) {
4387 for (i = 0; i < loading->trait.size; i++) {
4388 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4389
4390 if (trait_is_valid(tr)) {
4391 int val;
4392
4393 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4394 plrno, i),
4395 "%s", secfile_error());
4396 plr->ai_common.traits[tr].val = val;
4397
4399 "player%d.trait%d.mod", plrno, i),
4400 "%s", secfile_error());
4401 plr->ai_common.traits[tr].mod = val;
4402 }
4403 }
4404 }
4405
4406 /* Achievements */
4407 {
4408 int count;
4409
4410 count = secfile_lookup_int_default(loading->file, -1,
4411 "player%d.achievement_count", plrno);
4412
4413 if (count > 0) {
4414 for (i = 0; i < count; i++) {
4415 const char *name;
4416 struct achievement *pach;
4417 bool first;
4418
4420 "player%d.achievement%d.name", plrno, i);
4422
4424 "Unknown achievement \"%s\".", name);
4425
4427 "player%d.achievement%d.first",
4428 plrno, i),
4429 "achievement error: %s", secfile_error());
4430
4431 sg_failure_ret(pach->first == NULL || !first,
4432 "Multiple players listed as first to get achievement \"%s\".",
4433 name);
4434
4435 BV_SET(pach->achievers, player_index(plr));
4436
4437 if (first) {
4438 pach->first = plr;
4439 }
4440 }
4441 }
4442 }
4443
4444 /* Player score. */
4445 plr->score.happy =
4447 "score%d.happy", plrno);
4448 plr->score.content =
4450 "score%d.content", plrno);
4451 plr->score.unhappy =
4453 "score%d.unhappy", plrno);
4454 plr->score.angry =
4456 "score%d.angry", plrno);
4457
4458 /* Make sure that the score about specialists in current ruleset that
4459 * were not present at saving time are set to zero. */
4461 plr->score.specialists[sp] = 0;
4463
4464 for (i = 0; i < loading->specialist.size; i++) {
4465 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4467 "score%d.specialists%d", plrno, i);
4468 }
4469
4470 plr->score.wonders =
4472 "score%d.wonders", plrno);
4473 plr->score.techs =
4475 "score%d.techs", plrno);
4476 plr->score.techout =
4478 "score%d.techout", plrno);
4479 plr->score.landarea =
4481 "score%d.landarea", plrno);
4482 plr->score.settledarea =
4484 "score%d.settledarea", plrno);
4485 plr->score.population =
4487 "score%d.population", plrno);
4488 plr->score.cities =
4490 "score%d.cities", plrno);
4491 plr->score.units =
4493 "score%d.units", plrno);
4494 plr->score.pollution =
4496 "score%d.pollution", plrno);
4497 plr->score.literacy =
4499 "score%d.literacy", plrno);
4500 plr->score.bnp =
4502 "score%d.bnp", plrno);
4503 plr->score.mfg =
4505 "score%d.mfg", plrno);
4506 plr->score.spaceship =
4508 "score%d.spaceship", plrno);
4509 plr->score.units_built =
4511 "score%d.units_built", plrno);
4512 plr->score.units_killed =
4514 "score%d.units_killed", plrno);
4515 plr->score.units_lost =
4517 "score%d.units_lost", plrno);
4518 plr->score.units_used =
4520 "score%d.units_used", plrno);
4521 plr->score.culture =
4523 "score%d.culture", plrno);
4524 plr->score.game =
4526 "score%d.total", plrno);
4527
4528 /* Load space ship data. */
4529 {
4530 struct player_spaceship *ship = &plr->spaceship;
4531 char prefix[32];
4532 const char *st;
4533 int ei;
4534
4535 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4538 &ei,
4539 "%s.state", prefix),
4540 "%s", secfile_error());
4541 ship->state = ei;
4542
4543 if (ship->state != SSHIP_NONE) {
4544 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4545 "%s.structurals", prefix),
4546 "%s", secfile_error());
4547 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4548 "%s.components", prefix),
4549 "%s", secfile_error());
4551 "%s.modules", prefix),
4552 "%s", secfile_error());
4554 "%s.fuel", prefix),
4555 "%s", secfile_error());
4556 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4557 "%s.propulsion", prefix),
4558 "%s", secfile_error());
4559 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4560 "%s.habitation", prefix),
4561 "%s", secfile_error());
4562 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4563 "%s.life_support", prefix),
4564 "%s", secfile_error());
4565 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4566 "%s.solar_panels", prefix),
4567 "%s", secfile_error());
4568
4569 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4570 sg_failure_ret(st != NULL, "%s", secfile_error())
4571 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4572 sg_failure_ret(st[i] == '1' || st[i] == '0',
4573 "Undefined value '%c' within '%s.structure'.", st[i],
4574 prefix)
4575
4576 if (!(st[i] == '0')) {
4577 BV_SET(ship->structure, i);
4578 }
4579 }
4580 if (ship->state >= SSHIP_LAUNCHED) {
4581 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4582 "%s.launch_year", prefix),
4583 "%s", secfile_error());
4584 }
4586 }
4587 }
4588
4589 /* Load lost wonder data. */
4590 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4591 /* If not present, probably an old savegame; nothing to be done */
4592 if (str != NULL) {
4593 int k;
4594
4595 sg_failure_ret(strlen(str) == loading->improvement.size,
4596 "Invalid length for 'player%d.lost_wonders' ("
4597 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4598 plrno, strlen(str), loading->improvement.size);
4599 for (k = 0; k < loading->improvement.size; k++) {
4600 sg_failure_ret(str[k] == '1' || str[k] == '0',
4601 "Undefined value '%c' within "
4602 "'player%d.lost_wonders'.", plrno, str[k]);
4603
4604 if (str[k] == '1') {
4605 struct impr_type *pimprove =
4606 improvement_by_rule_name(loading->improvement.order[k]);
4607 if (pimprove) {
4608 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4609 }
4610 }
4611 }
4612 }
4613
4614 plr->history =
4615 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4616 plr->server.huts =
4617 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4618}
4619
4620/************************************************************************/
4624 struct player *plr)
4625{
4626 int i, k, plrno = player_number(plr);
4627 struct player_spaceship *ship = &plr->spaceship;
4628 const char *flag_names[PLRF_COUNT];
4629 int set_count;
4630
4631 /* Check status and return if not OK (sg_success FALSE). */
4632 sg_check_ret();
4633
4634 set_count = 0;
4635 for (i = 0; i < PLRF_COUNT; i++) {
4636 if (player_has_flag(plr, i)) {
4638 }
4639 }
4640
4642 "player%d.flags", plrno);
4643
4644 secfile_insert_str(saving->file, ai_name(plr->ai),
4645 "player%d.ai_type", plrno);
4647 "player%d.name", plrno);
4649 "player%d.username", plrno);
4651 "player%d.unassigned_user", plrno);
4652 if (plr->rgb != NULL) {
4653 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4654 } else {
4655 /* Colorless players are ok in pregame */
4656 if (game_was_started()) {
4657 log_sg("Game has started, yet player %d has no color defined.", plrno);
4658 }
4659 }
4661 "player%d.ranked_username", plrno);
4663 "player%d.unassigned_ranked", plrno);
4665 "player%d.orig_username", plrno);
4668 : "",
4669 "player%d.delegation_username", plrno);
4671 "player%d.nation", plrno);
4672 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4673 "player%d.team_no", plrno);
4674
4677 "player%d.government_name", plrno);
4678
4679 if (plr->target_government) {
4682 "player%d.target_government_name", plrno);
4683 }
4684
4686 "player%d.style_by_name", plrno);
4687
4689 "player%d.idle_turns", plrno);
4690 if (plr->is_male) {
4692 "player%d.kind", plrno);
4693 } else {
4695 "player%d.kind", plrno);
4696 }
4698 "player%d.is_alive", plrno);
4700 "player%d.turns_alive", plrno);
4702 "player%d.last_war", plrno);
4704 "player%d.phase_done", plrno);
4705
4706 players_iterate(pplayer) {
4707 char buf[32];
4708 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4709
4710 i = player_index(pplayer);
4711
4712 /* save diplomatic state */
4713 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4714
4715 secfile_insert_enum(saving->file, ds->type,
4716 diplstate_type, "%s.current", buf);
4717 secfile_insert_enum(saving->file, ds->max_state,
4718 diplstate_type, "%s.closest", buf);
4719 secfile_insert_int(saving->file, ds->first_contact_turn,
4720 "%s.first_contact_turn", buf);
4721 secfile_insert_int(saving->file, ds->turns_left,
4722 "%s.turns_left", buf);
4723 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4724 "%s.has_reason_to_cancel", buf);
4725 secfile_insert_int(saving->file, ds->contact_turns_left,
4726 "%s.contact_turns_left", buf);
4728 "%s.embassy", buf);
4729 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4730 "%s.gives_shared_vision", buf);
4731 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4732 "%s.gives_shared_tiles", buf);
4734
4737 /* save ai data */
4739 "player%d.ai%d.love", plrno, i);
4740 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4742
4744 "player%d.adv.wonder_city", plrno);
4745
4746 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4747
4748 /* Multipliers (policies) */
4749 i = multiplier_count();
4750
4751 for (k = 0; k < i; k++) {
4753 "player%d.multiplier%d.val", plrno, k);
4755 "player%d.multiplier%d.target", plrno, k);
4757 "player%d.multiplier%d.changed", plrno, k);
4758 }
4759
4761 "player%d.ai.level", plrno);
4763 "player%d.ai.barb_type", plrno);
4765 "player%d.gold", plrno);
4767 "player%d.rates.tax", plrno);
4769 "player%d.rates.science", plrno);
4771 "player%d.rates.luxury", plrno);
4773 "player%d.infrapts", plrno);
4775 "player%d.research.bulbs_last_turn", plrno);
4776
4777 /* Save traits */
4778 {
4779 enum trait tr;
4780 int j;
4781
4782 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4784 "player%d.trait%d.val", plrno, j);
4786 "player%d.trait%d.mod", plrno, j);
4787 }
4788 }
4789
4790 /* Save achievements */
4791 {
4792 int j = 0;
4793
4795 if (achievement_player_has(pach, plr)) {
4797 "player%d.achievement%d.name", plrno, j);
4798 if (pach->first == plr) {
4800 "player%d.achievement%d.first", plrno, j);
4801 } else {
4803 "player%d.achievement%d.first", plrno, j);
4804 }
4805
4806 j++;
4807 }
4809
4810 secfile_insert_int(saving->file, j,
4811 "player%d.achievement_count", plrno);
4812 }
4813
4815 "player%d.revolution_finishes", plrno);
4816
4817 /* Player score */
4819 "score%d.happy", plrno);
4821 "score%d.content", plrno);
4823 "score%d.unhappy", plrno);
4825 "score%d.angry", plrno);
4828 "score%d.specialists%d", plrno, sp);
4831 "score%d.wonders", plrno);
4833 "score%d.techs", plrno);
4835 "score%d.techout", plrno);
4837 "score%d.landarea", plrno);
4839 "score%d.settledarea", plrno);
4841 "score%d.population", plrno);
4843 "score%d.cities", plrno);
4845 "score%d.units", plrno);
4847 "score%d.pollution", plrno);
4849 "score%d.literacy", plrno);
4850 secfile_insert_int(saving->file, plr->score.bnp,
4851 "score%d.bnp", plrno);
4852 secfile_insert_int(saving->file, plr->score.mfg,
4853 "score%d.mfg", plrno);
4855 "score%d.spaceship", plrno);
4857 "score%d.units_built", plrno);
4859 "score%d.units_killed", plrno);
4861 "score%d.units_lost", plrno);
4863 "score%d.units_used", plrno);
4865 "score%d.culture", plrno);
4866 secfile_insert_int(saving->file, plr->score.game,
4867 "score%d.total", plrno);
4868
4869 /* Save space ship status. */
4870 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4871 plrno);
4872 if (ship->state != SSHIP_NONE) {
4873 char buf[32];
4874 char st[NUM_SS_STRUCTURALS+1];
4875 int ssi;
4876
4877 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4878
4879 secfile_insert_int(saving->file, ship->structurals,
4880 "%s.structurals", buf);
4881 secfile_insert_int(saving->file, ship->components,
4882 "%s.components", buf);
4883 secfile_insert_int(saving->file, ship->modules,
4884 "%s.modules", buf);
4885 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4886 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4887 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4888 secfile_insert_int(saving->file, ship->life_support,
4889 "%s.life_support", buf);
4890 secfile_insert_int(saving->file, ship->solar_panels,
4891 "%s.solar_panels", buf);
4892
4893 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4894 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4895 }
4896 st[ssi] = '\0';
4897 secfile_insert_str(saving->file, st, "%s.structure", buf);
4898 if (ship->state >= SSHIP_LAUNCHED) {
4899 secfile_insert_int(saving->file, ship->launch_year,
4900 "%s.launch_year", buf);
4901 }
4902 }
4903
4904 /* Save lost wonders info. */
4905 {
4906 char lost[B_LAST+1];
4907
4908 improvement_iterate(pimprove) {
4909 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
4910 lost[improvement_index(pimprove)] = '1';
4911 } else {
4912 lost[improvement_index(pimprove)] = '0';
4913 }
4915 lost[improvement_count()] = '\0';
4917 "player%d.lost_wonders", plrno);
4918 }
4919
4920 secfile_insert_int(saving->file, plr->history,
4921 "player%d.history", plrno);
4923 "player%d.hut_count", plrno);
4924
4926 "player%d.border_vision", plrno);
4927
4928 if (saving->scenario) {
4929 if (plr->autoselect_weight < 0) { /* Apply default behavior */
4930 int def = 1; /* We want users to get a player in a scenario */
4931
4933 /* This isn't usable player */
4934 def = 0;
4935 }
4936
4937 secfile_insert_int(saving->file, def,
4938 "player%d.autoselect_weight", plrno);
4939 } else {
4941 "player%d.autoselect_weight", plrno);
4942 }
4943 }
4944}
4945
4946/************************************************************************/
4950 struct player *plr)
4951{
4952 int ncities, i, plrno = player_number(plr);
4953 bool tasks_handled;
4955
4956 /* Check status and return if not OK (sg_success FALSE). */
4957 sg_check_ret();
4958
4960 "player%d.ncities", plrno),
4961 "%s", secfile_error());
4962
4963 if (!plr->is_alive && ncities > 0) {
4964 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
4965 ncities = 0;
4966 }
4967
4969 "player%d.wl_max_length",
4970 plrno);
4972 "player%d.routes_max_length", plrno);
4973
4974 /* Load all cities of the player. */
4975 for (i = 0; i < ncities; i++) {
4976 char buf[32];
4977 struct city *pcity;
4978
4979 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
4980
4981 /* Create a dummy city. */
4982 pcity = create_city_virtual(plr, NULL, buf);
4983 adv_city_alloc(pcity);
4984 if (!sg_load_player_city(loading, plr, pcity, buf,
4986 adv_city_free(pcity);
4987 destroy_city_virtual(pcity);
4988 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
4989 }
4990
4992 idex_register_city(&wld, pcity);
4993
4994 /* Load the information about the nationality of citizens. This is done
4995 * here because the city sanity check called by citizens_update() requires
4996 * that the city is registered. */
4998
4999 /* After everything is loaded, but before vision. */
5000 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
5001
5002 /* adding the city contribution to fog-of-war */
5003 pcity->server.vision = vision_new(plr, city_tile(pcity));
5005 city_refresh_vision(pcity);
5006
5007 city_list_append(plr->cities, pcity);
5008 }
5009
5011 for (i = 0; !tasks_handled; i++) {
5012 int city_id;
5013 struct city *pcity = NULL;
5014
5015 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5016 plrno, i);
5017
5018 if (city_id != -1) {
5019 pcity = player_city_by_number(plr, city_id);
5020 }
5021
5022 if (pcity != NULL) {
5023 const char *str;
5024 int nat_x, nat_y;
5025 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5026
5027 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5028 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5029
5030 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5031
5032 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5034
5036 "Unknown workertask activity %s", str);
5037
5038 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5039
5040 if (strcmp("-", str)) {
5042
5043 sg_failure_ret(ptask->tgt != NULL,
5044 "Unknown workertask target %s", str);
5045 } else {
5046 ptask->tgt = NULL;
5047
5048 if (ptask->act == ACTIVITY_IRRIGATE) {
5050 } else if (ptask->act == ACTIVITY_MINE) {
5051 ptask->act = ACTIVITY_MINE;
5052 }
5053 }
5054
5055 ptask->want = secfile_lookup_int_default(loading->file, 1,
5056 "player%d.task%d.want", plrno, i);
5057
5059 } else {
5061 }
5062 }
5063}
5064
5065/************************************************************************/
5068static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5069 struct city *pcity, const char *citystr,
5071{
5072 struct player *past;
5073 const char *kind, *name, *str;
5074 int id, i, repair, sp_count = 0, workers = 0, value;
5075 int nat_x, nat_y;
5076 citizens size;
5077 const char *stylename;
5078 int partner;
5079 int want;
5080 int tmp_int;
5081 const struct civ_map *nmap = &(wld.map);
5082
5084 FALSE, "%s", secfile_error());
5086 FALSE, "%s", secfile_error());
5087 pcity->tile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5088 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5089 "%s has invalid center tile (%d, %d)",
5090 citystr, nat_x, nat_y);
5092 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5093
5094 /* Instead of dying, use 'citystr' string for damaged name. */
5096 "%s.name", citystr));
5097
5098 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5099 citystr), FALSE, "%s", secfile_error());
5100
5102 "%s.original", citystr);
5103 past = player_by_number(id);
5104 if (NULL != past) {
5105 pcity->original = past;
5106 }
5107
5108 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5109 citystr), FALSE, "%s", secfile_error());
5110 size = (citizens)value; /* set the correct type */
5111 sg_warn_ret_val(value == (int)size, FALSE,
5112 "Invalid city size: %d, set to %d", value, size);
5113 city_size_set(pcity, size);
5114
5115 for (i = 0; i < loading->specialist.size; i++) {
5116 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5117 citystr, i),
5118 FALSE, "%s", secfile_error());
5119 pcity->specialists[specialist_index(loading->specialist.order[i])]
5120 = (citizens)value;
5121 sp_count += value;
5122 }
5123
5124 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5125 for (i = 0; partner != 0; i++) {
5126 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5127 const char *dir;
5128 const char *good_str;
5129
5130 /* Append to routes list immediately, so the pointer can be found for freeing
5131 * even if we abort */
5133
5134 proute->partner = partner;
5135 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5137 "No traderoute direction found for %s", citystr);
5140 "Illegal route direction %s", dir);
5141 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5143 "No good found for %s", citystr);
5145 sg_warn_ret_val(proute->goods != NULL, FALSE,
5146 "Illegal good %s", good_str);
5147
5148 /* Next one */
5150 "%s.traderoute%d", citystr, i + 1);
5151 }
5152
5153 for (; i < routes_max; i++) {
5154 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5155 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5156 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5157 }
5158
5160 "%s.food_stock", citystr),
5161 FALSE, "%s", secfile_error());
5163 "%s.shield_stock", citystr),
5164 FALSE, "%s", secfile_error());
5165 pcity->history =
5166 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5167
5168 pcity->airlift =
5169 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5170 pcity->was_happy =
5171 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5172 citystr);
5173 pcity->had_famine =
5174 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5175 citystr);
5176
5177 pcity->turn_plague =
5178 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5179
5181 "%s.anarchy", citystr),
5182 FALSE, "%s", secfile_error());
5183 pcity->rapture =
5184 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5185 pcity->steal =
5186 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5187
5189 "%s.turn_founded", citystr),
5190 FALSE, "%s", secfile_error());
5192 "%s.acquire_t", citystr),
5193 FALSE, "%s", secfile_error());
5194 pcity->acquire_t = tmp_int;
5195 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5196 citystr), FALSE, "%s", secfile_error());
5197 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5198 citystr), FALSE, "%s", secfile_error());
5199
5201 "%s.turn_last_built", citystr),
5202 FALSE, "%s", secfile_error());
5203
5204 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5205 citystr);
5206 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5207 citystr);
5208 pcity->production = universal_by_rule_name(kind, name);
5210 "%s.currently_building: unknown \"%s\" \"%s\".",
5211 citystr, kind, name);
5212
5213 want = secfile_lookup_int_default(loading->file, 0,
5214 "%s.current_want", citystr);
5215 if (pcity->production.kind == VUT_IMPROVEMENT) {
5216 pcity->server.adv->
5217 building_want[improvement_index(pcity->production.value.building)]
5218 = want;
5219 }
5220
5221 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5222 citystr);
5223 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5224 citystr);
5227 "%s.changed_from: unknown \"%s\" \"%s\".",
5228 citystr, kind, name);
5229
5230 pcity->before_change_shields =
5232 "%s.before_change_shields", citystr);
5233 pcity->caravan_shields =
5235 "%s.caravan_shields", citystr);
5236 pcity->disbanded_shields =
5238 "%s.disbanded_shields", citystr);
5241 "%s.last_turns_shield_surplus",
5242 citystr);
5243
5245 "%s.style", citystr);
5246 if (stylename != NULL) {
5248 } else {
5249 pcity->style = 0;
5250 }
5251 if (pcity->style < 0) {
5252 pcity->style = city_style(pcity);
5253 }
5254
5255 pcity->server.synced = FALSE; /* Must re-sync with clients */
5256
5257 /* Initialise list of city improvements. */
5258 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5259 pcity->built[i].turn = I_NEVER;
5260 }
5261
5262 /* Load city improvements. */
5263 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5265 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5266 "Invalid length of '%s.improvements' ("
5267 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5268 citystr, strlen(str), loading->improvement.size);
5269 for (i = 0; i < loading->improvement.size; i++) {
5270 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5271 "Undefined value '%c' within '%s.improvements'.",
5272 str[i], citystr)
5273
5274 if (str[i] == '1') {
5275 struct impr_type *pimprove
5276 = improvement_by_rule_name(loading->improvement.order[i]);
5277
5278 if (pimprove) {
5279 city_add_improvement(pcity, pimprove);
5280 }
5281 }
5282 }
5283
5284 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5285 "No worked tiles map defined.");
5286
5287 city_freeze_workers(pcity);
5288
5289 /* Load new savegame with variable (squared) city radius and worked
5290 * tiles map */
5291
5292 int radius_sq
5293 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5294 citystr);
5295 city_map_radius_sq_set(pcity, radius_sq);
5296
5298 if (loading->worked_tiles[ptile->index] == pcity->id) {
5299 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5300 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5301 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5302 TILE_XY(pcity->tile), TILE_XY(ptile));
5304 sp_count++;
5305 } else {
5306 tile_set_worked(ptile, pcity);
5307 workers++;
5308 }
5309
5310#ifdef FREECIV_DEBUG
5311 /* Set this tile to unused; a check for not reset tiles is
5312 * included in game_load_internal() */
5313 loading->worked_tiles[ptile->index] = -1;
5314#endif /* FREECIV_DEBUG */
5315 }
5317
5318 if (tile_worked(city_tile(pcity)) != pcity) {
5319 struct city *pwork = tile_worked(city_tile(pcity));
5320
5321 if (NULL != pwork) {
5322 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5323 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5326
5327 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5328 pwork->specialists[DEFAULT_SPECIALIST]++;
5330 } else {
5331 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5332 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5333 city_size_get(pcity));
5334 }
5335
5336 /* Repair pcity */
5337 tile_set_worked(city_tile(pcity), pcity);
5338 city_repair_size(pcity, -1);
5339 }
5340
5341 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5342 if (0 != repair) {
5343 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5344 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5345 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5346 workers, FREE_WORKED_TILES, sp_count);
5347
5348 /* Repair pcity */
5349 city_repair_size(pcity, repair);
5350 }
5351
5352 /* worklist_init() done in create_city_virtual() */
5353 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5354
5355 /* Load city options. */
5356 BV_CLR_ALL(pcity->city_options);
5357 for (i = 0; i < loading->coptions.size; i++) {
5358 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5359 citystr, i)) {
5360 BV_SET(pcity->city_options, loading->coptions.order[i]);
5361 }
5362 }
5364 "%s.wlcb", citystr),
5365 FALSE, "%s", secfile_error());
5366 pcity->wlcb = tmp_int;
5367
5368 /* Load the city rally point. */
5369 {
5370 int len = secfile_lookup_int_default(loading->file, 0,
5371 "%s.rally_point_length", citystr);
5372 int unconverted;
5373
5374 pcity->rally_point.length = len;
5375 if (len > 0) {
5377
5378 pcity->rally_point.orders
5379 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5380 pcity->rally_point.persistent
5382 "%s.rally_point_persistent", citystr);
5383 pcity->rally_point.vigilant
5385 "%s.rally_point_vigilant", citystr);
5386
5389 "%s.rally_point_orders", citystr);
5392 "%s.rally_point_dirs", citystr);
5395 "%s.rally_point_activities", citystr);
5396
5397 for (i = 0; i < len; i++) {
5398 struct unit_order *order = &pcity->rally_point.orders[i];
5399
5400 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5401 || rally_activities[i] == '\0') {
5402 log_sg("Invalid rally point.");
5403 free(pcity->rally_point.orders);
5404 pcity->rally_point.orders = NULL;
5405 pcity->rally_point.length = 0;
5406 break;
5407 }
5408 order->order = char2order(rally_orders[i]);
5409 order->dir = char2dir(rally_dirs[i]);
5410 order->activity = char2activity(rally_activities[i]);
5411
5413 "%s.rally_point_action_vec,%d",
5414 citystr, i);
5415
5416 if (unconverted == -1) {
5417 order->action = ACTION_NONE;
5418 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5419 /* Look up what action id the unconverted number represents. */
5420 order->action = loading->action.order[unconverted];
5421 } else {
5422 if (order->order == ORDER_PERFORM_ACTION) {
5423 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5424 pcity->id);
5425 }
5426
5427 order->action = ACTION_NONE;
5428 }
5429
5430 order->target
5432 "%s.rally_point_tgt_vec,%d",
5433 citystr, i);
5434 order->sub_target
5436 "%s.rally_point_sub_tgt_vec,%d",
5437 citystr, i);
5438 }
5439 } else {
5440 pcity->rally_point.orders = NULL;
5441
5442 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5443 citystr);
5444 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5445 citystr);
5446 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5447 citystr);
5448 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5449 citystr);
5450 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5451 citystr);
5452 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5453 citystr);
5455 "%s.rally_point_tgt_vec", citystr);
5457 "%s.rally_point_sub_tgt_vec", citystr);
5458 }
5459 }
5460
5461 /* Load the city manager parameters. */
5462 {
5463 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5464 "%s.cma_enabled", citystr);
5465 if (enabled) {
5466 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5467
5468 for (i = 0; i < O_LAST; i++) {
5470 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5472 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5473 }
5474
5476 loading->file, FALSE, "%s.max_growth", citystr);
5478 loading->file, FALSE, "%s.require_happy", citystr);
5480 loading->file, FALSE, "%s.allow_disorder", citystr);
5482 loading->file, FALSE, "%s.allow_specialists", citystr);
5484 loading->file, 0, "%s.happy_factor", citystr);
5485 pcity->cm_parameter = param;
5486 } else {
5487 pcity->cm_parameter = NULL;
5488
5489 for (i = 0; i < O_LAST; i++) {
5491 "%s.cma_minimal_surplus,%d", citystr, i);
5493 "%s.cma_factor,%d", citystr, i);
5494 }
5495
5496 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5497 citystr);
5498 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5499 citystr);
5500 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5501 citystr);
5502 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5503 citystr);
5504 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5505 citystr);
5506 }
5507 }
5508
5509 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5510
5511 return TRUE;
5512}
5513
5514/************************************************************************/
5518 struct player *plr,
5519 struct city *pcity,
5520 const char *citystr)
5521{
5523 citizens size;
5524
5525 citizens_init(pcity);
5526 player_slots_iterate(pslot) {
5527 int nationality;
5528
5529 nationality = secfile_lookup_int_default(loading->file, -1,
5530 "%s.citizen%d", citystr,
5531 player_slot_index(pslot));
5532 if (nationality > 0 && !player_slot_is_used(pslot)) {
5533 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5534 city_name_get(pcity), player_slot_index(pslot));
5535 continue;
5536 }
5537
5538 if (nationality != -1 && player_slot_is_used(pslot)) {
5539 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5540 "Invalid value for citizens of player %d in %s: %d.",
5541 player_slot_index(pslot), city_name_get(pcity), nationality);
5542 citizens_nation_set(pcity, pslot, nationality);
5543 }
5545 /* Sanity check. */
5546 size = citizens_count(pcity);
5547 if (size != city_size_get(pcity)) {
5548 if (size != 0) {
5549 /* size == 0 can be result from the fact that ruleset had no
5550 * nationality enabled at saving time, so no citizens at all
5551 * were saved. But something more serious must be going on if
5552 * citizens have been saved partially - if some of them are there. */
5553 log_sg("City size and number of citizens does not match in %s "
5554 "(%d != %d)! Repairing ...", city_name_get(pcity),
5555 city_size_get(pcity), size);
5556 }
5557 citizens_update(pcity, NULL);
5558 }
5559 }
5560}
5561
5562/************************************************************************/
5566 struct player *plr)
5567{
5569 int i = 0;
5570 int plrno = player_number(plr);
5572
5573 /* Check status and return if not OK (sg_success FALSE). */
5574 sg_check_ret();
5575
5577 "player%d.ncities", plrno);
5578
5580 /* Initialise the nation list for the citizens information. */
5581 player_slots_iterate(pslot) {
5584 }
5585
5586 /* First determine length of longest worklist, rally point order, and the
5587 * nationalities we have. */
5588 city_list_iterate(plr->cities, pcity) {
5589 int routes;
5590
5591 /* Check the sanity of the city. */
5592 city_refresh(pcity);
5593 sanity_check_city(pcity);
5594
5595 if (pcity->worklist.length > wlist_max_length) {
5596 wlist_max_length = pcity->worklist.length;
5597 }
5598
5599 if (pcity->rally_point.length > rally_point_max_length) {
5600 rally_point_max_length = pcity->rally_point.length;
5601 }
5602
5603 routes = city_num_trade_routes(pcity);
5604 if (routes > routes_max) {
5605 routes_max = routes;
5606 }
5607
5609 /* Find all nations of the citizens,*/
5610 players_iterate(pplayer) {
5611 if (!nations[player_index(pplayer)]
5612 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5613 nations[player_index(pplayer)] = TRUE;
5614 }
5616 }
5618
5620 "player%d.wl_max_length", plrno);
5622 "player%d.routes_max_length", plrno);
5623
5624 city_list_iterate(plr->cities, pcity) {
5625 struct tile *pcenter = city_tile(pcity);
5626 char impr_buf[B_LAST + 1];
5627 char buf[32];
5628 int j, nat_x, nat_y;
5629
5630 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5631
5632
5634 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5635 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5636
5637 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5638
5639 if (pcity->original != NULL) {
5640 secfile_insert_int(saving->file, player_number(pcity->original),
5641 "%s.original", buf);
5642 } else {
5643 secfile_insert_int(saving->file, -1, "%s.original", buf);
5644 }
5645 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5646
5647 j = 0;
5649 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5650 buf, j++);
5652
5653 j = 0;
5655 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5656 buf, j);
5658 "%s.route_direction%d", buf, j);
5660 "%s.route_good%d", buf, j);
5661 j++;
5663
5664 /* Save dummy values to keep tabular format happy */
5665 for (; j < routes_max; j++) {
5666 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5668 "%s.route_direction%d", buf, j);
5670 "%s.route_good%d", buf, j);
5671 }
5672
5673 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5674 buf);
5675 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5676 buf);
5677 secfile_insert_int(saving->file, pcity->history, "%s.history",
5678 buf);
5679
5680 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5681 buf);
5682 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5683 buf);
5684 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5685 buf);
5686 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5687 buf);
5688
5689 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5690 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5691 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5692 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5693 buf);
5694 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5695 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5696 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5697 secfile_insert_int(saving->file, pcity->turn_last_built,
5698 "%s.turn_last_built", buf);
5699
5700 /* For visual debugging, variable length strings together here */
5701 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5702
5703 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5704 "%s.currently_building_kind", buf);
5705 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5706 "%s.currently_building_name", buf);
5707
5708 if (pcity->production.kind == VUT_IMPROVEMENT) {
5710 pcity->server.adv->
5711 building_want[improvement_index(pcity->production.value.building)],
5712 "%s.current_want", buf);
5713 } else {
5714 secfile_insert_int(saving->file, 0,
5715 "%s.current_want", buf);
5716 }
5717
5718 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5719 "%s.changed_from_kind", buf);
5720 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5721 "%s.changed_from_name", buf);
5722
5723 secfile_insert_int(saving->file, pcity->before_change_shields,
5724 "%s.before_change_shields", buf);
5725 secfile_insert_int(saving->file, pcity->caravan_shields,
5726 "%s.caravan_shields", buf);
5727 secfile_insert_int(saving->file, pcity->disbanded_shields,
5728 "%s.disbanded_shields", buf);
5729 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5730 "%s.last_turns_shield_surplus", buf);
5731
5732 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5733 "%s.style", buf);
5734
5735 /* Save the squared city radius and all tiles within the corresponding
5736 * city map. */
5737 secfile_insert_int(saving->file, pcity->city_radius_sq,
5738 "player%d.c%d.city_radius_sq", plrno, i);
5739 /* The tiles worked by the city are saved using the main map.
5740 * See also sg_save_map_worked(). */
5741
5742 /* Save improvement list as bytevector. Note that improvement order
5743 * is saved in savefile.improvement_order. */
5744 improvement_iterate(pimprove) {
5745 impr_buf[improvement_index(pimprove)]
5746 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5747 : '1';
5749 impr_buf[improvement_count()] = '\0';
5750
5752 "Invalid size of the improvement vector (%s.improvements: "
5753 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5754 strlen(impr_buf), sizeof(impr_buf));
5755 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5756
5757 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5758 buf);
5759
5760 for (j = 0; j < CITYO_LAST; j++) {
5761 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5762 "%s.option%d", buf, j);
5763 }
5764 secfile_insert_int(saving->file, pcity->wlcb,
5765 "%s.wlcb", buf);
5766
5767 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5768
5770 /* Save nationality of the citizens,*/
5771 players_iterate(pplayer) {
5772 if (nations[player_index(pplayer)]) {
5774 citizens_nation_get(pcity, pplayer->slot),
5775 "%s.citizen%d", buf, player_index(pplayer));
5776 }
5778 }
5779
5780 secfile_insert_int(saving->file, pcity->rally_point.length,
5781 "%s.rally_point_length", buf);
5782 if (pcity->rally_point.length) {
5783 int len = pcity->rally_point.length;
5784 char orders[len + 1], dirs[len + 1], activities[len + 1];
5785 int actions[len];
5786 int targets[len];
5787 int sub_targets[len];
5788
5789 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5790 "%s.rally_point_persistent", buf);
5791 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5792 "%s.rally_point_vigilant", buf);
5793
5794 for (j = 0; j < len; j++) {
5795 orders[j] = order2char(pcity->rally_point.orders[j].order);
5796 dirs[j] = '?';
5797 activities[j] = '?';
5798 targets[j] = NO_TARGET;
5799 sub_targets[j] = NO_TARGET;
5800 actions[j] = -1;
5801 switch (pcity->rally_point.orders[j].order) {
5802 case ORDER_MOVE:
5803 case ORDER_ACTION_MOVE:
5804 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5805 break;
5806 case ORDER_ACTIVITY:
5807 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5808 activities[j]
5809 = activity2char(pcity->rally_point.orders[j].activity);
5810 break;
5812 actions[j] = pcity->rally_point.orders[j].action;
5813 targets[j] = pcity->rally_point.orders[j].target;
5814 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5815 break;
5816 case ORDER_FULL_MP:
5817 case ORDER_LAST:
5818 break;
5819 }
5820
5821 if (actions[j] == ACTION_NONE) {
5822 actions[j] = -1;
5823 }
5824 }
5825 orders[len] = dirs[len] = activities[len] = '\0';
5826
5827 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5828 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5829 secfile_insert_str(saving->file, activities,
5830 "%s.rally_point_activities", buf);
5831
5833 "%s.rally_point_action_vec", buf);
5834 /* Fill in dummy values for order targets so the registry will save
5835 * the unit table in a tabular format. */
5836 for (j = len; j < rally_point_max_length; j++) {
5837 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5838 buf, j);
5839 }
5840
5841 secfile_insert_int_vec(saving->file, targets, len,
5842 "%s.rally_point_tgt_vec", buf);
5843 /* Fill in dummy values for order targets so the registry will save
5844 * the unit table in a tabular format. */
5845 for (j = len; j < rally_point_max_length; j++) {
5847 "%s.rally_point_tgt_vec,%d", buf, j);
5848 }
5849
5850 secfile_insert_int_vec(saving->file, sub_targets, len,
5851 "%s.rally_point_sub_tgt_vec", buf);
5852 /* Fill in dummy values for order targets so the registry will save
5853 * the unit table in a tabular format. */
5854 for (j = len; j < rally_point_max_length; j++) {
5855 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5856 buf, j);
5857 }
5858 } else {
5859 /* Put all the same fields into the savegame - otherwise the
5860 * registry code can't correctly use a tabular format and the
5861 * savegame will be bigger. */
5862 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5863 buf);
5864 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5865 buf);
5866 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5867 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5868 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5869 buf);
5870
5871 /* Fill in dummy values for order targets so the registry will save
5872 * the unit table in a tabular format. */
5873
5874 /* The start of a vector has no number. */
5875 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5876 buf);
5877 for (j = 1; j < rally_point_max_length; j++) {
5878 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5879 buf, j);
5880 }
5881
5882 /* The start of a vector has no number. */
5883 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5884 buf);
5885 for (j = 1; j < rally_point_max_length; j++) {
5887 "%s.rally_point_tgt_vec,%d", buf, j);
5888 }
5889
5890 /* The start of a vector has no number. */
5891 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5892 buf);
5893 for (j = 1; j < rally_point_max_length; j++) {
5894 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5895 buf, j);
5896 }
5897 }
5898
5899 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5900 "%s.cma_enabled", buf);
5901 if (pcity->cm_parameter) {
5903 pcity->cm_parameter->minimal_surplus, O_LAST,
5904 "%s.cma_minimal_surplus", buf);
5906 pcity->cm_parameter->factor, O_LAST,
5907 "%s.cma_factor", buf);
5908 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
5909 "%s.max_growth", buf);
5910 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
5911 "%s.require_happy", buf);
5912 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
5913 "%s.allow_disorder", buf);
5915 pcity->cm_parameter->allow_specialists,
5916 "%s.allow_specialists", buf);
5917 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
5918 "%s.happy_factor", buf);
5919 } else {
5920 int zeros[O_LAST];
5921
5922 memset(zeros, 0, sizeof(zeros));
5924 "%s.cma_minimal_surplus", buf);
5926 "%s.cma_factor", buf);
5927 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
5928 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
5929 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
5930 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
5931 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
5932 }
5933
5934 i++;
5936
5937 i = 0;
5938 city_list_iterate(plr->cities, pcity) {
5939 worker_task_list_iterate(pcity->task_reqs, ptask) {
5940 int nat_x, nat_y;
5941
5943 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
5944 plrno, i);
5945 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
5946 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
5948 "player%d.task%d.activity",
5949 plrno, i);
5950 if (ptask->tgt != NULL) {
5952 "player%d.task%d.target",
5953 plrno, i);
5954 } else {
5955 secfile_insert_str(saving->file, "-",
5956 "player%d.task%d.target",
5957 plrno, i);
5958 }
5959 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
5960
5961 i++;
5964}
5965
5966/************************************************************************/
5970 struct player *plr)
5971{
5972 int nunits, i, plrno = player_number(plr);
5973 size_t orders_max_length;
5974
5975 /* Check status and return if not OK (sg_success FALSE). */
5976 sg_check_ret();
5977
5979 "player%d.nunits", plrno),
5980 "%s", secfile_error());
5981 if (!plr->is_alive && nunits > 0) {
5982 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
5983 nunits = 0; /* Some old savegames may be buggy. */
5984 }
5985
5987 "player%d.orders_max_length",
5988 plrno);
5989
5990 for (i = 0; i < nunits; i++) {
5991 struct unit *punit;
5992 struct city *pcity;
5993 const char *name;
5994 char buf[32];
5995 struct unit_type *type;
5996 struct tile *ptile;
5997
5998 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
5999
6000 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6002 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6003
6004 /* Create a dummy unit. */
6005 punit = unit_virtual_create(plr, NULL, type, 0);
6008 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6009 }
6010
6013
6014 if ((pcity = game_city_by_number(punit->homecity))) {
6016 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6017 log_sg("%s: bad home city %d.", buf, punit->homecity);
6019 }
6020
6021 ptile = unit_tile(punit);
6022
6023 /* allocate the unit's contribution to fog of war */
6026 /* NOTE: There used to be some map_set_known calls here. These were
6027 * unneeded since unfogging the tile when the unit sees it will
6028 * automatically reveal that tile. */
6029
6032 }
6033}
6034
6035/************************************************************************/
6039 struct player *plr, struct unit *punit,
6041 const char *unitstr)
6042{
6043 enum unit_activity activity;
6044 int nat_x, nat_y;
6045 struct extra_type *pextra = NULL;
6046 struct tile *ptile;
6047 int extra_id;
6048 int ei;
6049 const char *facing_str;
6050 int natnbr;
6051 int unconverted;
6052 const char *str;
6053
6055 unitstr), FALSE, "%s", secfile_error());
6057 FALSE, "%s", secfile_error());
6059 FALSE, "%s", secfile_error());
6060
6061 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6062 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6063 unitstr, nat_x, nat_y);
6064 unit_tile_set(punit, ptile);
6065
6068 "%s.facing", unitstr);
6069 if (facing_str[0] != 'x') {
6070 /* We don't touch punit->facing if savegame does not contain that
6071 * information. Initial orientation set by unit_virtual_create()
6072 * is as good as any. */
6073 enum direction8 facing = char2dir(facing_str[0]);
6074
6075 if (direction8_is_valid(facing)) {
6076 punit->facing = facing;
6077 } else {
6078 log_error("Illegal unit orientation '%s'", facing_str);
6079 }
6080 }
6081
6082 /* If savegame has unit nationality, it doesn't hurt to
6083 * internally set it even if nationality rules are disabled. */
6085 player_number(plr),
6086 "%s.nationality", unitstr);
6087
6089 if (punit->nationality == NULL) {
6090 punit->nationality = plr;
6091 }
6092
6094 "%s.homecity", unitstr), FALSE,
6095 "%s", secfile_error());
6097 "%s.moves", unitstr), FALSE,
6098 "%s", secfile_error());
6100 "%s.fuel", unitstr), FALSE,
6101 "%s", secfile_error());
6103 "%s.activity", unitstr), FALSE,
6104 "%s", secfile_error());
6105 activity = unit_activity_by_name(loading->activities.order[ei],
6107
6110 "%s.born", unitstr);
6113 "%s.current_form_turn", unitstr);
6114
6116 "%s.activity_tgt", unitstr);
6117
6118 if (extra_id != -2) {
6119 if (extra_id >= 0 && extra_id < loading->extra.size) {
6120 pextra = loading->extra.order[extra_id];
6121 set_unit_activity_targeted(punit, activity, pextra);
6122 } else if (activity == ACTIVITY_IRRIGATE) {
6126 punit);
6127 if (tgt != NULL) {
6129 } else {
6131 }
6132 } else if (activity == ACTIVITY_MINE) {
6134 EC_MINE,
6136 punit);
6137 if (tgt != NULL) {
6139 } else {
6141 }
6142 } else {
6143 set_unit_activity(punit, activity);
6144 }
6145 } else {
6147 } /* activity_tgt == NULL */
6148
6150 "%s.activity_count", unitstr), FALSE,
6151 "%s", secfile_error());
6152
6155 "%s.changed_from", unitstr);
6156
6158 "%s.changed_from_tgt", unitstr), FALSE,
6159 "%s", secfile_error());
6160
6161 if (extra_id >= 0 && extra_id < loading->extra.size) {
6162 punit->changed_from_target = loading->extra.order[extra_id];
6163 } else {
6165 }
6166
6169 "%s.changed_from_count", unitstr);
6170
6171 /* Special case: for a long time, we accidentally incremented
6172 * activity_count while a unit was sentried, so it could increase
6173 * without bound (bug #20641) and be saved in old savefiles.
6174 * We zero it to prevent potential trouble overflowing the range
6175 * in network packets, etc. */
6176 if (activity == ACTIVITY_SENTRY) {
6177 punit->activity_count = 0;
6178 }
6181 }
6182
6183 punit->veteran
6184 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6185 {
6186 /* Protect against change in veteran system in ruleset */
6187 const int levels = utype_veteran_levels(unit_type_get(punit));
6188
6189 if (punit->veteran >= levels) {
6190 fc_assert(levels >= 1);
6191 punit->veteran = levels - 1;
6192 }
6193 }
6196 "%s.done_moving", unitstr);
6199 "%s.battlegroup", unitstr);
6200
6202 "%s.go", unitstr)) {
6203 int gnat_x, gnat_y;
6204
6206 "%s.goto_x", unitstr), FALSE,
6207 "%s", secfile_error());
6209 "%s.goto_y", unitstr), FALSE,
6210 "%s", secfile_error());
6211
6213 } else {
6214 punit->goto_tile = NULL;
6215
6216 /* These variables are not used but needed for saving the unit table.
6217 * Load them to prevent unused variables errors. */
6218 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6219 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6220 }
6221
6222 /* Load AI data of the unit. */
6223 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6224
6227 "%s.server_side_agent",
6228 unitstr);
6229 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6230 /* Look up what server side agent the unconverted number represents. */
6231 punit->ssa_controller = loading->ssa.order[unconverted];
6232 } else {
6233 log_sg("Invalid server side agent %d for unit %d",
6234 unconverted, punit->id);
6235
6237 }
6238
6240 "%s.hp", unitstr), FALSE,
6241 "%s", secfile_error());
6242
6244 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6246 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6247 punit->moved
6248 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6251 "%s.paradropped", unitstr);
6252 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6253 if (str[0] != '\0') {
6255 }
6256
6257 /* The transport status (punit->transported_by) is loaded in
6258 * sg_player_units_transport(). */
6259
6260 /* Initialize upkeep values: these are hopefully initialized
6261 * elsewhere before use (specifically, in city_support(); but
6262 * fixme: check whether always correctly initialized?).
6263 * Below is mainly for units which don't have homecity --
6264 * otherwise these don't get initialized (and AI calculations
6265 * etc may use junk values). */
6269
6271 "%s.action_decision", unitstr),
6272 FALSE, "%s", secfile_error());
6273
6274 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6275 /* Look up what action decision want the unconverted number
6276 * represents. */
6277 punit->action_decision_want = loading->act_dec.order[unconverted];
6278 } else {
6279 log_sg("Invalid action decision want for unit %d", punit->id);
6280
6282 }
6283
6285 /* Load the tile to act against. */
6286 int adwt_x, adwt_y;
6287
6288 if (secfile_lookup_int(loading->file, &adwt_x,
6289 "%s.action_decision_tile_x", unitstr)
6291 "%s.action_decision_tile_y", unitstr)) {
6293 adwt_x, adwt_y);
6294 } else {
6297 log_sg("Bad action_decision_tile for unit %d", punit->id);
6298 }
6299 } else {
6300 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6301 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6303 }
6304
6306
6307 /* Load the unit orders */
6308 {
6309 int len = secfile_lookup_int_default(loading->file, 0,
6310 "%s.orders_length", unitstr);
6311
6312 if (len > 0) {
6313 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6314 int j;
6315
6316 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6320 "%s.orders_index", unitstr);
6323 "%s.orders_repeat", unitstr);
6326 "%s.orders_vigilant", unitstr);
6327
6330 "%s.orders_list", unitstr);
6333 "%s.dir_list", unitstr);
6336 "%s.activity_list", unitstr);
6337
6339
6340 for (j = 0; j < len; j++) {
6341 struct unit_order *order = &punit->orders.list[j];
6343 int order_sub_tgt;
6344
6345 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6346 || act_unitstr[j] == '\0') {
6347 log_sg("Invalid unit orders.");
6349 break;
6350 }
6351 order->order = char2order(orders_unitstr[j]);
6352 order->dir = char2dir(dir_unitstr[j]);
6353 order->activity = char2activity(act_unitstr[j]);
6354
6356 "%s.action_vec,%d",
6357 unitstr, j);
6358
6359 if (unconverted == -1) {
6360 order->action = ACTION_NONE;
6361 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6362 /* Look up what action id the unconverted number represents. */
6363 order->action = loading->action.order[unconverted];
6364 } else {
6365 if (order->order == ORDER_PERFORM_ACTION) {
6366 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6367 }
6368
6369 order->action = ACTION_NONE;
6370 }
6371
6372 if (order->order == ORDER_LAST
6373 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6374 || (order->order == ORDER_ACTION_MOVE
6375 && !direction8_is_valid(order->dir))
6376 || (order->order == ORDER_PERFORM_ACTION
6377 && !action_id_exists(order->action))
6378 || (order->order == ORDER_ACTIVITY
6379 && order->activity == ACTIVITY_LAST)) {
6380 /* An invalid order. Just drop the orders for this unit. */
6382 punit->orders.list = NULL;
6384 break;
6385 }
6386
6388 "%s.tgt_vec,%d",
6389 unitstr, j);
6391 "%s.sub_tgt_vec,%d",
6392 unitstr, j);
6393
6394 if (order->order == ORDER_PERFORM_ACTION) {
6395 /* Validate sub target */
6396 switch (action_id_get_sub_target_kind(order->action)) {
6397 case ASTK_BUILDING:
6398 /* Sub target is a building. */
6400 /* Sub target is invalid. */
6401 log_sg("Cannot find building %d for %s to %s",
6404 order->sub_target = B_LAST;
6405 } else {
6406 order->sub_target = order_sub_tgt;
6407 }
6408 break;
6409 case ASTK_TECH:
6410 /* Sub target is a technology. */
6411 if (order_sub_tgt == A_NONE
6413 && order_sub_tgt != A_FUTURE)) {
6414 /* Target tech is invalid. */
6415 log_sg("Cannot find tech %d for %s to steal",
6417 order->sub_target = A_NONE;
6418 } else {
6419 order->sub_target = order_sub_tgt;
6420 }
6421 break;
6422 case ASTK_EXTRA:
6424 /* These take an extra. */
6426 break;
6427 case ASTK_NONE:
6428 /* None of these can take a sub target. */
6430 "Specified sub target for action %d unsupported.",
6431 order->action);
6432 order->sub_target = NO_TARGET;
6433 break;
6434 case ASTK_COUNT:
6436 "Bad action action %d.",
6437 order->action);
6438 order->sub_target = NO_TARGET;
6439 break;
6440 }
6441 }
6442
6443 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6444 enum unit_activity act;
6445
6447 if (order_sub_tgt != EXTRA_NONE) {
6448 log_sg("Cannot find extra %d for %s to build",
6450 }
6451
6452 order->sub_target = EXTRA_NONE;
6453 } else {
6454 order->sub_target = order_sub_tgt;
6455 }
6456
6457 /* An action or an activity may require an extra target. */
6458 if (action_wants_extra) {
6459 act = action_id_get_activity(order->action);
6460 } else {
6461 act = order->activity;
6462 }
6463
6464 if (unit_activity_is_valid(act)
6466 && order->sub_target == EXTRA_NONE) {
6467 /* Missing required action extra target. */
6469 punit->orders.list = NULL;
6471 break;
6472 }
6473 } else if (order->order != ORDER_PERFORM_ACTION) {
6474 if (order_sub_tgt != -1) {
6475 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6476 order_sub_tgt, -1, order->order);
6477 }
6478 order->sub_target = NO_TARGET;
6479 }
6480 }
6481
6482 for (; j < orders_max_length; j++) {
6484 "%s.action_vec,%d", unitstr, j);
6486 "%s.tgt_vec,%d", unitstr, j);
6488 "%s.sub_tgt_vec,%d", unitstr, j);
6489 }
6490 } else {
6491 int j;
6492
6494 punit->orders.list = NULL;
6495
6496 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6497 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6498 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6499 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6500 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6501 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6502 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6503 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6504 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6505
6506 for (j = 1; j < orders_max_length; j++) {
6508 "%s.action_vec,%d", unitstr, j);
6510 "%s.tgt_vec,%d", unitstr, j);
6512 "%s.sub_tgt_vec,%d", unitstr, j);
6513 }
6514 }
6515 }
6516
6517 return TRUE;
6518}
6519
6520/************************************************************************/
6525 struct player *plr)
6526{
6527 int nunits, i, plrno = player_number(plr);
6528
6529 /* Check status and return if not OK (sg_success FALSE). */
6530 sg_check_ret();
6531
6532 /* Recheck the number of units for the player. This is a copied from
6533 * sg_load_player_units(). */
6535 "player%d.nunits", plrno),
6536 "%s", secfile_error());
6537 if (!plr->is_alive && nunits > 0) {
6538 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6539 nunits = 0; /* Some old savegames may be buggy. */
6540 }
6541
6542 for (i = 0; i < nunits; i++) {
6543 int id_unit, id_trans;
6544 struct unit *punit, *ptrans;
6545
6547 "player%d.u%d.id",
6548 plrno, i);
6550 fc_assert_action(punit != NULL, continue);
6551
6553 "player%d.u%d.transported_by",
6554 plrno, i);
6555 if (id_trans == -1) {
6556 /* Not transported. */
6557 continue;
6558 }
6559
6561 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6562
6563 if (ptrans) {
6564#ifndef FREECIV_NDEBUG
6565 bool load_success =
6566#endif
6568
6569 fc_assert_action(load_success, continue);
6570 }
6571 }
6572}
6573
6574/************************************************************************/
6578 struct player *plr)
6579{
6580 int i = 0;
6581 int longest_order = 0;
6582 int plrno = player_number(plr);
6583
6584 /* Check status and return if not OK (sg_success FALSE). */
6585 sg_check_ret();
6586
6588 "player%d.nunits", plrno);
6589
6590 /* Find the longest unit order so different order length won't break
6591 * storing units in the tabular format. */
6593 if (punit->has_orders) {
6594 if (longest_order < punit->orders.length) {
6596 }
6597 }
6599
6601 "player%d.orders_max_length", plrno);
6602
6604 char buf[32];
6605 char dirbuf[2] = " ";
6606 int nat_x, nat_y;
6607 int last_order, j;
6608
6609 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6610 dirbuf[0] = dir2char(punit->facing);
6611 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6612
6614 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6615 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6616
6617 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6620 "%s.nationality", buf);
6621 }
6622 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6623 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6624 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6626 "%s.type_by_name", buf);
6627
6628 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6630 "%s.activity_count", buf);
6631 if (punit->activity_target == NULL) {
6632 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6633 } else {
6635 "%s.activity_tgt", buf);
6636 }
6637
6639 "%s.changed_from", buf);
6641 "%s.changed_from_count", buf);
6642 if (punit->changed_from_target == NULL) {
6643 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6644 } else {
6646 "%s.changed_from_tgt", buf);
6647 }
6648
6650 "%s.done_moving", buf);
6651 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6652 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6654 "%s.born", buf);
6656 "%s.current_form_turn", buf);
6658 "%s.battlegroup", buf);
6659
6660 if (punit->goto_tile) {
6662 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6663 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6664 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6665 } else {
6666 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6667 /* Set this values to allow saving it as table. */
6668 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6669 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6670 }
6671
6673 "%s.server_side_agent", buf);
6674
6675 /* Save AI data of the unit. */
6676 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6677
6679 "%s.ord_map", buf);
6681 "%s.ord_city", buf);
6682 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6684 "%s.paradropped", buf);
6686 ? unit_transport_get(punit)->id : -1,
6687 "%s.transported_by", buf);
6688 if (punit->carrying != NULL) {
6690 "%s.carrying", buf);
6691 } else {
6692 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6693 }
6694
6696 "%s.action_decision", buf);
6697
6698 /* Stored as tile rather than direction to make sure the target tile is
6699 * sane. */
6704 "%s.action_decision_tile_x", buf);
6706 "%s.action_decision_tile_y", buf);
6707 } else {
6708 /* Dummy values to get tabular format. */
6709 secfile_insert_int(saving->file, -1,
6710 "%s.action_decision_tile_x", buf);
6711 secfile_insert_int(saving->file, -1,
6712 "%s.action_decision_tile_y", buf);
6713 }
6714
6716 "%s.stay", buf);
6717
6718 if (punit->has_orders) {
6719 int len = punit->orders.length;
6720 char orders_buf[len + 1], dir_buf[len + 1];
6721 char act_buf[len + 1];
6722 int action_buf[len];
6723 int tgt_vec[len];
6724 int sub_tgt_vec[len];
6725
6726 last_order = len;
6727
6728 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6730 "%s.orders_index", buf);
6732 "%s.orders_repeat", buf);
6734 "%s.orders_vigilant", buf);
6735
6736 for (j = 0; j < len; j++) {
6738 dir_buf[j] = '?';
6739 act_buf[j] = '?';
6740 tgt_vec[j] = NO_TARGET;
6741 sub_tgt_vec[j] = -1;
6742 action_buf[j] = -1;
6743 switch (punit->orders.list[j].order) {
6744 case ORDER_MOVE:
6745 case ORDER_ACTION_MOVE:
6746 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6747 break;
6748 case ORDER_ACTIVITY:
6751 break;
6754 tgt_vec[j] = punit->orders.list[j].target;
6756 break;
6757 case ORDER_FULL_MP:
6758 case ORDER_LAST:
6759 break;
6760 }
6761
6762 if (action_buf[j] == ACTION_NONE) {
6763 action_buf[j] = -1;
6764 }
6765 }
6766 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6767
6768 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6769 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6770 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6771
6773 "%s.action_vec", buf);
6774 /* Fill in dummy values for order targets so the registry will save
6775 * the unit table in a tabular format. */
6776 for (j = last_order; j < longest_order; j++) {
6777 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6778 }
6779
6781 "%s.tgt_vec", buf);
6782 /* Fill in dummy values for order targets so the registry will save
6783 * the unit table in a tabular format. */
6784 for (j = last_order; j < longest_order; j++) {
6785 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6786 }
6787
6789 "%s.sub_tgt_vec", buf);
6790 /* Fill in dummy values for order targets so the registry will save
6791 * the unit table in a tabular format. */
6792 for (j = last_order; j < longest_order; j++) {
6793 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6794 }
6795 } else {
6796
6797 /* Put all the same fields into the savegame - otherwise the
6798 * registry code can't correctly use a tabular format and the
6799 * savegame will be bigger. */
6800 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6801 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6802 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6803 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6804 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6805 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6806 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6807
6808 /* Fill in dummy values for order targets so the registry will save
6809 * the unit table in a tabular format. */
6810
6811 /* The start of a vector has no number. */
6812 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6813 for (j = 1; j < longest_order; j++) {
6814 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6815 }
6816
6817 /* The start of a vector has no number. */
6818 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6819 for (j = 1; j < longest_order; j++) {
6820 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6821 }
6822
6823 /* The start of a vector has no number. */
6824 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6825 for (j = 1; j < longest_order; j++) {
6826 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6827 }
6828 }
6829
6830 i++;
6832}
6833
6834/************************************************************************/
6838 struct player *plr)
6839{
6840 int plrno = player_number(plr);
6841
6842 /* Check status and return if not OK (sg_success FALSE). */
6843 sg_check_ret();
6844
6845 /* Toss any existing attribute_block (should not exist) */
6846 if (plr->attribute_block.data) {
6848 plr->attribute_block.data = NULL;
6849 }
6850
6851 /* This is a big heap of opaque data for the client, check everything! */
6853 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6854
6855 if (0 > plr->attribute_block.length) {
6856 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6857 plr->attribute_block.length);
6858 plr->attribute_block.length = 0;
6859 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6860 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6862 plr->attribute_block.length = 0;
6863 } else if (0 < plr->attribute_block.length) {
6864 int part_nr, parts;
6865 int quoted_length;
6866 char *quoted;
6867#ifndef FREECIV_NDEBUG
6868 size_t actual_length;
6869#endif
6870
6873 "player%d.attribute_v2_block_length_quoted",
6874 plrno), "%s", secfile_error());
6877 "player%d.attribute_v2_block_parts", plrno),
6878 "%s", secfile_error());
6879
6881 quoted[0] = '\0';
6883 for (part_nr = 0; part_nr < parts; part_nr++) {
6884 const char *current =
6886 "player%d.attribute_v2_block_data.part%d",
6887 plrno, part_nr);
6888 if (!current) {
6889 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6890 break;
6891 }
6892 log_debug("attribute_v2_block_length_quoted=%d"
6893 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
6894 quoted_length, strlen(quoted), strlen(current));
6895 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6896 strcat(quoted, current);
6897 }
6899 "attribute_v2_block_length_quoted=%d"
6900 " actual=" SIZE_T_PRINTF,
6902
6903#ifndef FREECIV_NDEBUG
6905#endif
6907 plr->attribute_block.data,
6908 plr->attribute_block.length);
6910 free(quoted);
6911 }
6912}
6913
6914/************************************************************************/
6918 struct player *plr)
6919{
6920 int plrno = player_number(plr);
6921
6922 /* Check status and return if not OK (sg_success FALSE). */
6923 sg_check_ret();
6924
6925 /* This is a big heap of opaque data from the client. Although the binary
6926 * format is not user editable, keep the lines short enough for debugging,
6927 * and hope that data compression will keep the file a reasonable size.
6928 * Note that the "quoted" format is a multiple of 3.
6929 */
6930#define PART_SIZE (3*256)
6931#define PART_ADJUST (3)
6932 if (plr->attribute_block.data) {
6933 char part[PART_SIZE + PART_ADJUST];
6934 int parts;
6935 int current_part_nr;
6937 plr->attribute_block.length);
6938 char *quoted_at = strchr(quoted, ':');
6939 size_t bytes_left = strlen(quoted);
6940 size_t bytes_at_colon = 1 + (quoted_at - quoted);
6942
6944 "player%d.attribute_v2_block_length", plrno);
6946 "player%d.attribute_v2_block_length_quoted", plrno);
6947
6948 /* Try to wring some compression efficiencies out of the "quoted" format.
6949 * The first line has a variable length decimal, mis-aligning triples.
6950 */
6951 if ((bytes_left - bytes_adjust) > PART_SIZE) {
6952 /* first line can be longer */
6953 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
6954 } else {
6955 parts = 1;
6956 }
6957
6959 "player%d.attribute_v2_block_parts", plrno);
6960
6961 if (parts > 1) {
6963
6964 /* first line can be longer */
6966 part[size_of_current_part] = '\0';
6968 "player%d.attribute_v2_block_data.part%d",
6969 plrno, 0);
6972 current_part_nr = 1;
6973 } else {
6974 quoted_at = quoted;
6975 current_part_nr = 0;
6976 }
6977
6980
6982 part[size_of_current_part] = '\0';
6984 "player%d.attribute_v2_block_data.part%d",
6985 plrno,
6989 }
6990 fc_assert(bytes_left == 0);
6991 free(quoted);
6992 }
6993#undef PART_ADJUST
6994#undef PART_SIZE
6995}
6996
6997/************************************************************************/
7001 struct player *plr)
7002{
7003 int plrno = player_number(plr);
7004 int total_ncities =
7006 "player%d.dc_total", plrno);
7007 int i;
7008 bool someone_alive = FALSE;
7009
7010 /* Check status and return if not OK (sg_success FALSE). */
7011 sg_check_ret();
7012
7015 if (pteam_member->is_alive) {
7017 break;
7018 }
7020
7021 if (!someone_alive) {
7022 /* Reveal all for completely dead teams. */
7024 }
7025 }
7026
7027 if (-1 == total_ncities
7028 || !game.info.fogofwar
7030 "game.save_private_map")) {
7031 /* We have:
7032 * - a dead player;
7033 * - fogged cities are not saved for any reason;
7034 * - a savegame with fog of war turned off;
7035 * - or game.save_private_map is not set to FALSE in the scenario /
7036 * savegame. The players private knowledge is set to be what they could
7037 * see without fog of war. */
7038 whole_map_iterate(&(wld.map), ptile) {
7039 if (map_is_known(ptile, plr)) {
7040 struct city *pcity = tile_city(ptile);
7041
7042 update_player_tile_last_seen(plr, ptile);
7043 update_player_tile_knowledge(plr, ptile);
7044
7045 if (NULL != pcity) {
7046 update_dumb_city(plr, pcity);
7047 }
7048 }
7050
7051 /* Nothing more to do; */
7052 return;
7053 }
7054
7055 /* Load player map (terrain). */
7056 LOAD_MAP_CHAR(ch, ptile,
7057 map_get_player_tile(ptile, plr)->terrain
7058 = char2terrain(ch), loading->file,
7059 "player%d.map_t%04d", plrno);
7060
7061 /* Load player map (extras). */
7062 halfbyte_iterate_extras(j, loading->extra.size) {
7063 LOAD_MAP_CHAR(ch, ptile,
7065 ch, loading->extra.order + 4 * j),
7066 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7068
7069 whole_map_iterate(&(wld.map), ptile) {
7070 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7071
7073 if (BV_ISSET(plrtile->extras, extra_number(pres))) {
7074 plrtile->resource = pres;
7075 if (!terrain_has_resource(plrtile->terrain, pres)) {
7076 BV_CLR(plrtile->extras, extra_number(pres));
7077 }
7078 }
7081
7083 /* Load player map (border). */
7084 int x, y;
7085
7086 for (y = 0; y < wld.map.ysize; y++) {
7087 const char *buffer
7088 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7089 plrno, y);
7090 const char *buffer2
7091 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7092 plrno, y);
7093 const char *ptr = buffer;
7094 const char *ptr2 = buffer2;
7095
7096 sg_failure_ret(NULL != buffer,
7097 "Savegame corrupt - map line %d not found.", y);
7098 for (x = 0; x < wld.map.xsize; x++) {
7099 char token[TOKEN_SIZE];
7100 char token2[TOKEN_SIZE];
7101 int number;
7102 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7103
7104 scanin(&ptr, ",", token, sizeof(token));
7105 sg_failure_ret('\0' != token[0],
7106 "Savegame corrupt - map size not correct.");
7107 if (strcmp(token, "-") == 0) {
7108 map_get_player_tile(ptile, plr)->owner = NULL;
7109 } else {
7110 sg_failure_ret(str_to_int(token, &number),
7111 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7112 token, x, y);
7113 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7114 }
7115
7116 scanin(&ptr2, ",", token2, sizeof(token2));
7117 sg_failure_ret('\0' != token2[0],
7118 "Savegame corrupt - map size not correct.");
7119 if (strcmp(token2, "-") == 0) {
7120 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7121 } else {
7123 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7124 token, x, y);
7125 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7126 }
7127 }
7128 }
7129 }
7130
7131 /* Load player map (update time). */
7132 for (i = 0; i < 4; i++) {
7133 /* put 4-bit segments of 16-bit "updated" field */
7134 if (i == 0) {
7135 LOAD_MAP_CHAR(ch, ptile,
7136 map_get_player_tile(ptile, plr)->last_updated
7137 = ascii_hex2bin(ch, i),
7138 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7139 } else {
7140 LOAD_MAP_CHAR(ch, ptile,
7141 map_get_player_tile(ptile, plr)->last_updated
7142 |= ascii_hex2bin(ch, i),
7143 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7144 }
7145 }
7146
7147 /* Load player map known cities. */
7148 for (i = 0; i < total_ncities; i++) {
7149 struct vision_site *pdcity;
7150 char buf[32];
7151 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7152
7156 pdcity);
7158 } else {
7159 /* Error loading the data. */
7160 log_sg("Skipping seen city %d for player %d.", i, plrno);
7161 if (pdcity != NULL) {
7163 }
7164 }
7165 }
7166
7167 /* Repair inconsistent player maps. */
7168 whole_map_iterate(&(wld.map), ptile) {
7169 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7170 struct city *pcity = tile_city(ptile);
7171
7172 update_player_tile_knowledge(plr, ptile);
7173 reality_check_city(plr, ptile);
7174
7175 if (NULL != pcity) {
7176 update_dumb_city(plr, pcity);
7177 }
7178 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7179 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7180 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7181
7182 plrtile->owner = tile_owner(ptile);
7183 }
7185}
7186
7187/************************************************************************/
7191 struct player *plr,
7192 struct vision_site *pdcity,
7193 const char *citystr)
7194{
7195 const char *str;
7196 int i, id, size;
7197 citizens city_size;
7198 int nat_x, nat_y;
7199 const char *stylename;
7200 enum capital_type cap;
7201 const char *vname;
7202
7204 citystr),
7205 FALSE, "%s", secfile_error());
7207 citystr),
7208 FALSE, "%s", secfile_error());
7209 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7210 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7211 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7212
7213 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7214 citystr),
7215 FALSE, "%s", secfile_error());
7216 pdcity->owner = player_by_number(id);
7217 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7218 "%s has invalid owner (%d); skipping.", citystr, id);
7219
7221 "%s.id", citystr),
7222 FALSE, "%s", secfile_error());
7224 "%s has invalid id (%d); skipping.", citystr, id);
7225
7227 "%s.size", citystr),
7228 FALSE, "%s", secfile_error());
7229 city_size = (citizens)size; /* set the correct type */
7230 sg_warn_ret_val(size == (int)city_size, FALSE,
7231 "Invalid city size: %d; set to %d.", size, city_size);
7232 vision_site_size_set(pdcity, city_size);
7233
7234 /* Initialise list of improvements */
7235 BV_CLR_ALL(pdcity->improvements);
7236 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7238 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7239 "Invalid length of '%s.improvements' ("
7240 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7241 citystr, strlen(str), loading->improvement.size);
7242 for (i = 0; i < loading->improvement.size; i++) {
7243 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7244 "Undefined value '%c' within '%s.improvements'.",
7245 str[i], citystr)
7246
7247 if (str[i] == '1') {
7248 struct impr_type *pimprove =
7249 improvement_by_rule_name(loading->improvement.order[i]);
7250 if (pimprove) {
7251 BV_SET(pdcity->improvements, improvement_index(pimprove));
7252 }
7253 }
7254 }
7255
7257 "%s.name", citystr);
7258
7259 if (vname != NULL) {
7260 pdcity->name = fc_strdup(vname);
7261 }
7262
7264 "%s.occupied", citystr);
7266 "%s.walls", citystr);
7268 "%s.happy", citystr);
7270 "%s.unhappy", citystr);
7272 "%s.style", citystr);
7273 if (stylename != NULL) {
7275 } else {
7276 pdcity->style = 0;
7277 }
7278 if (pdcity->style < 0) {
7279 pdcity->style = 0;
7280 }
7281
7282 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7283 "%s.city_image", citystr);
7284
7286 "%s.capital", citystr),
7288
7290 pdcity->capital = cap;
7291 } else {
7292 pdcity->capital = CAPITAL_NOT;
7293 }
7294
7295 return TRUE;
7296}
7297
7298/************************************************************************/
7302 struct player *plr)
7303{
7304 int i, plrno = player_number(plr);
7305
7306 /* Check status and return if not OK (sg_success FALSE). */
7307 sg_check_ret();
7308
7310 /* The player can see all, there's no reason to save the private map. */
7311 return;
7312 }
7313
7314 /* Save the map (terrain). */
7315 SAVE_MAP_CHAR(ptile,
7317 saving->file, "player%d.map_t%04d", plrno);
7318
7320 /* Save the map (borders). */
7321 int x, y;
7322
7323 for (y = 0; y < wld.map.ysize; y++) {
7324 char line[wld.map.xsize * TOKEN_SIZE];
7325
7326 line[0] = '\0';
7327 for (x = 0; x < wld.map.xsize; x++) {
7328 char token[TOKEN_SIZE];
7329 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7330 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7331
7332 if (plrtile == NULL || plrtile->owner == NULL) {
7333 strcpy(token, "-");
7334 } else {
7335 fc_snprintf(token, sizeof(token), "%d",
7336 player_number(plrtile->owner));
7337 }
7338 strcat(line, token);
7339 if (x < wld.map.xsize) {
7340 strcat(line, ",");
7341 }
7342 }
7343 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7344 plrno, y);
7345 }
7346
7347 for (y = 0; y < wld.map.ysize; y++) {
7348 char line[wld.map.xsize * TOKEN_SIZE];
7349
7350 line[0] = '\0';
7351 for (x = 0; x < wld.map.xsize; x++) {
7352 char token[TOKEN_SIZE];
7353 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7354 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7355
7356 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7357 strcpy(token, "-");
7358 } else {
7359 fc_snprintf(token, sizeof(token), "%d",
7360 player_number(plrtile->extras_owner));
7361 }
7362 strcat(line, token);
7363 if (x < wld.map.xsize) {
7364 strcat(line, ",");
7365 }
7366 }
7367 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7368 plrno, y);
7369 }
7370 }
7371
7372 /* Save the map (extras). */
7374 int mod[4];
7375 int l;
7376
7377 for (l = 0; l < 4; l++) {
7378 if (4 * j + 1 > game.control.num_extra_types) {
7379 mod[l] = -1;
7380 } else {
7381 mod[l] = 4 * j + l;
7382 }
7383 }
7384
7385 SAVE_MAP_CHAR(ptile,
7387 map_get_player_tile(ptile, plr)->resource,
7388 mod),
7389 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7391
7392 /* Save the map (update time). */
7393 for (i = 0; i < 4; i++) {
7394 /* put 4-bit segments of 16-bit "updated" field */
7395 SAVE_MAP_CHAR(ptile,
7397 map_get_player_tile(ptile, plr)->last_updated, i),
7398 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7399 }
7400
7401 /* Save known cities. */
7402 i = 0;
7403 whole_map_iterate(&(wld.map), ptile) {
7404 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7405 char impr_buf[B_LAST + 1];
7406 char buf[32];
7407
7408 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7409
7410 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7411 int nat_x, nat_y;
7412
7414 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7415 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7416
7417 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7419 "%s.owner", buf);
7420
7422 "%s.size", buf);
7423 secfile_insert_bool(saving->file, pdcity->occupied,
7424 "%s.occupied", buf);
7425 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7426 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7427 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7429 "%s.style", buf);
7430 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7432 "%s.capital", buf);
7433
7434 /* Save improvement list as bitvector. Note that improvement order
7435 * is saved in savefile.improvement.order. */
7436 improvement_iterate(pimprove) {
7437 impr_buf[improvement_index(pimprove)]
7438 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7439 ? '1' : '0';
7441 impr_buf[improvement_count()] = '\0';
7443 "Invalid size of the improvement vector (%s.improvements: "
7444 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7445 buf, strlen(impr_buf), sizeof(impr_buf));
7446 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7447 if (pdcity->name != NULL) {
7448 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7449 }
7450
7451 i++;
7452 }
7454
7455 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7456}
7457
7458/* =======================================================================
7459 * Load / save the researches.
7460 * ======================================================================= */
7461
7462/************************************************************************/
7466{
7467 struct research *presearch;
7468 int count;
7469 int number;
7470 const char *str;
7471 int i, j;
7472 int *vlist_research;
7473
7475 /* Check status and return if not OK (sg_success FALSE). */
7476 sg_check_ret();
7477
7478 /* Initialize all researches. */
7482
7483 /* May be unsaved (e.g. scenario case). */
7484 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7485 for (i = 0; i < count; i++) {
7487 "research.r%d.number", i),
7488 "%s", secfile_error());
7489 presearch = research_by_number(number);
7491 "Invalid research number %d in 'research.r%d.number'",
7492 number, i);
7493
7494 presearch->tech_goal = technology_load(loading->file,
7495 "research.r%d.goal", i);
7497 &presearch->techs_researched,
7498 "research.r%d.techs", i),
7499 "%s", secfile_error());
7501 &presearch->future_tech,
7502 "research.r%d.futuretech", i),
7503 "%s", secfile_error());
7505 &presearch->bulbs_researched,
7506 "research.r%d.bulbs", i),
7507 "%s", secfile_error());
7509 &presearch->bulbs_researching_saved,
7510 "research.r%d.bulbs_before", i),
7511 "%s", secfile_error());
7512 presearch->researching_saved = technology_load(loading->file,
7513 "research.r%d.saved", i);
7514 presearch->researching = technology_load(loading->file,
7515 "research.r%d.now", i);
7517 &presearch->free_bulbs,
7518 "research.r%d.free_bulbs", i),
7519 "%s", secfile_error());
7520
7521 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7522 sg_failure_ret(str != NULL, "%s", secfile_error());
7523 sg_failure_ret(strlen(str) == loading->technology.size,
7524 "Invalid length of 'research.r%d.done' ("
7525 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7526 i, strlen(str), loading->technology.size);
7527 for (j = 0; j < loading->technology.size; j++) {
7528 sg_failure_ret(str[j] == '1' || str[j] == '0',
7529 "Undefined value '%c' within 'research.r%d.done'.",
7530 str[j], i);
7531
7532 if (str[j] == '1') {
7533 struct advance *padvance =
7534 advance_by_rule_name(loading->technology.order[j]);
7535
7536 if (padvance) {
7538 TECH_KNOWN);
7539 }
7540 }
7541 }
7542
7544 size_t count_res;
7545 int tn;
7546
7548 "research.r%d.vbs", i);
7549
7550 for (tn = 0; tn < count_res; tn++) {
7551 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7552
7553 if (padvance != NULL) {
7554 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7555 = vlist_research[tn];
7556 }
7557 }
7558 }
7559 }
7560
7561 /* In case of tech_leakage, we can update research only after all the
7562 * researches have been loaded */
7566}
7567
7568/************************************************************************/
7572{
7573 char invs[A_LAST];
7574 int i = 0;
7575 int *vlist_research;
7576
7578 /* Check status and return if not OK (sg_success FALSE). */
7579 sg_check_ret();
7580
7581 if (saving->save_players) {
7584 "research.r%d.number", i);
7585 technology_save(saving->file, "research.r%d.goal",
7586 i, presearch->tech_goal);
7587 secfile_insert_int(saving->file, presearch->techs_researched,
7588 "research.r%d.techs", i);
7589 secfile_insert_int(saving->file, presearch->future_tech,
7590 "research.r%d.futuretech", i);
7591 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7592 "research.r%d.bulbs_before", i);
7596 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7600 "research.r%d.vbs", i);
7601 if (vlist_research) {
7603 }
7604 }
7605 technology_save(saving->file, "research.r%d.saved",
7606 i, presearch->researching_saved);
7607 secfile_insert_int(saving->file, presearch->bulbs_researched,
7608 "research.r%d.bulbs", i);
7609 technology_save(saving->file, "research.r%d.now",
7610 i, presearch->researching);
7611 secfile_insert_int(saving->file, presearch->free_bulbs,
7612 "research.r%d.free_bulbs", i);
7613 /* Save technology lists as bytevector. Note that technology order is
7614 * saved in savefile.technology.order */
7615 advance_index_iterate(A_NONE, tech_id) {
7616 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7618 == TECH_KNOWN ? '1' : '0');
7621 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7622 i++;
7624 secfile_insert_int(saving->file, i, "research.count");
7625 }
7626}
7627
7628/* =======================================================================
7629 * Load / save the event cache. Should be the last thing to do.
7630 * ======================================================================= */
7631
7632/************************************************************************/
7636{
7637 /* Check status and return if not OK (sg_success FALSE). */
7638 sg_check_ret();
7639
7640 event_cache_load(loading->file, "event_cache");
7641}
7642
7643/************************************************************************/
7647{
7648 /* Check status and return if not OK (sg_success FALSE). */
7649 sg_check_ret();
7650
7651 if (saving->scenario) {
7652 /* Do _not_ save events in a scenario. */
7653 return;
7654 }
7655
7656 event_cache_save(saving->file, "event_cache");
7657}
7658
7659/* =======================================================================
7660 * Load / save the open treaties
7661 * ======================================================================= */
7662
7663/************************************************************************/
7667{
7668 int tidx;
7669 const char *plr0;
7670
7671 /* Check status and return if not OK (sg_success FALSE). */
7672 sg_check_ret();
7673
7674 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7675 "treaty%d.plr0", tidx)) != NULL ;
7676 tidx++) {
7677 const char *plr1;
7678 const char *ct;
7679 int cidx;
7680 struct player *p0, *p1;
7681
7682 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7683
7684 p0 = player_by_name(plr0);
7685 p1 = player_by_name(plr1);
7686
7687 if (p0 == NULL || p1 == NULL) {
7688 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7689 } else {
7690 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7691
7694
7695 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7696 "treaty%d.clause%d.type",
7697 tidx, cidx)) != NULL ;
7698 cidx++ ) {
7700 const char *plrx;
7701
7702 if (!clause_type_is_valid(type)) {
7703 log_error("Invalid clause type \"%s\"", ct);
7704 } else {
7705 struct player *pgiver = NULL;
7706
7707 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7708 tidx, cidx);
7709
7710 if (!fc_strcasecmp(plrx, plr0)) {
7711 pgiver = p0;
7712 } else if (!fc_strcasecmp(plrx, plr1)) {
7713 pgiver = p1;
7714 } else {
7715 log_error("Clause giver %s is not participant of the treaty"
7716 "between %s and %s", plrx, plr0, plr1);
7717 }
7718
7719 if (pgiver != NULL) {
7720 int value;
7721
7722 value = secfile_lookup_int_default(loading->file, 0,
7723 "treaty%d.clause%d.value",
7724 tidx, cidx);
7725
7726 add_clause(ptreaty, pgiver, type, value, NULL);
7727 }
7728 }
7729 }
7730
7731 /* These must be after clauses have been added so that acceptance
7732 * does not get cleared by what seems like changes to the treaty. */
7734 "treaty%d.accept0", tidx);
7736 "treaty%d.accept1", tidx);
7737 }
7738 }
7739}
7740
7741typedef struct {
7742 int tidx;
7745
7746/************************************************************************/
7749static void treaty_save(struct Treaty *ptr, void *data_in)
7750{
7751 char tpath[512];
7752 int cidx = 0;
7754
7755 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7756
7757 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7758 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7759 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7760 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7761
7763 char cpath[512];
7764
7765 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7766
7767 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7768 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7769 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7771}
7772
7773/************************************************************************/
7777{
7778 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7779
7781}
7782
7783/* =======================================================================
7784 * Load / save the history report
7785 * ======================================================================= */
7786
7787/************************************************************************/
7791{
7793 int turn;
7794
7795 /* Check status and return if not OK (sg_success FALSE). */
7796 sg_check_ret();
7797
7798 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7799
7800 if (turn != -2) {
7801 hist->turn = turn;
7802 }
7803
7804 if (turn + 1 >= game.info.turn) {
7805 const char *str;
7806
7807 str = secfile_lookup_str(loading->file, "history.title");
7808 sg_failure_ret(str != NULL, "%s", secfile_error());
7809 sz_strlcpy(hist->title, str);
7810 str = secfile_lookup_str(loading->file, "history.body");
7811 sg_failure_ret(str != NULL, "%s", secfile_error());
7812 sz_strlcpy(hist->body, str);
7813 }
7814}
7815
7816/************************************************************************/
7819static void sg_save_history(struct savedata *saving)
7820{
7822
7823 secfile_insert_int(saving->file, hist->turn, "history.turn");
7824
7825 if (hist->turn + 1 >= game.info.turn) {
7826 secfile_insert_str(saving->file, hist->title, "history.title");
7827 secfile_insert_str(saving->file, hist->body, "history.body");
7828 }
7829}
7830
7831/* =======================================================================
7832 * Load / save the mapimg definitions.
7833 * ======================================================================= */
7834
7835/************************************************************************/
7838static void sg_load_mapimg(struct loaddata *loading)
7839{
7840 int mapdef_count, i;
7841
7842 /* Check status and return if not OK (sg_success FALSE). */
7843 sg_check_ret();
7844
7845 /* Clear all defined map images. */
7846 while (mapimg_count() > 0) {
7847 mapimg_delete(0);
7848 }
7849
7851 "mapimg.count");
7852 log_verbose("Saved map image definitions: %d.", mapdef_count);
7853
7854 if (0 >= mapdef_count) {
7855 return;
7856 }
7857
7858 for (i = 0; i < mapdef_count; i++) {
7859 const char *p;
7860
7861 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7862 if (NULL == p) {
7863 log_verbose("[Mapimg %4d] Missing definition.", i);
7864 continue;
7865 }
7866
7867 if (!mapimg_define(p, FALSE)) {
7868 log_error("Invalid map image definition %4d: %s.", i, p);
7869 }
7870
7871 log_verbose("Mapimg %4d loaded.", i);
7872 }
7873}
7874
7875/************************************************************************/
7878static void sg_save_mapimg(struct savedata *saving)
7879{
7880 /* Check status and return if not OK (sg_success FALSE). */
7881 sg_check_ret();
7882
7883 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7884 if (mapimg_count() > 0) {
7885 int i;
7886
7887 for (i = 0; i < mapimg_count(); i++) {
7888 char buf[MAX_LEN_MAPDEF];
7889
7890 mapimg_id2str(i, buf, sizeof(buf));
7891 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7892 }
7893 }
7894}
7895
7896/* =======================================================================
7897 * Sanity checks for loading / saving a game.
7898 * ======================================================================= */
7899
7900/************************************************************************/
7904{
7905 int players;
7906
7907 /* Check status and return if not OK (sg_success FALSE). */
7908 sg_check_ret();
7909
7910 if (game.info.is_new_game) {
7911 /* Nothing to do for new games (or not started scenarios). */
7912 return;
7913 }
7914
7915 /* Old savegames may have maxplayers lower than current player count,
7916 * fix. */
7917 players = normal_player_count();
7918 if (game.server.max_players < players) {
7919 log_verbose("Max players lower than current players, fixing");
7920 game.server.max_players = players;
7921 }
7922
7923 /* Fix ferrying sanity */
7924 players_iterate(pplayer) {
7925 unit_list_iterate_safe(pplayer->units, punit) {
7928 log_sg("Removing %s unferried %s in %s at (%d, %d)",
7934 }
7937
7938 /* Fix stacking issues. We don't rely on the savegame preserving
7939 * alliance invariants (old savegames often did not) so if there are any
7940 * unallied units on the same tile we just bounce them. */
7941 players_iterate(pplayer) {
7943 resolve_unit_stacks(pplayer, aplayer, TRUE);
7946
7947 /* Recalculate the potential buildings for each city. Has caused some
7948 * problems with game random state.
7949 * This also changes the game state if you save the game directly after
7950 * loading it and compare the results. */
7951 players_iterate(pplayer) {
7952 /* Building advisor needs data phase open in order to work */
7953 adv_data_phase_init(pplayer, FALSE);
7954 building_advisor(pplayer);
7955 /* Close data phase again so it can be opened again when game starts. */
7956 adv_data_phase_done(pplayer);
7958
7959 /* Prevent a buggy or intentionally crafted save game from crashing
7960 * Freeciv. See hrm Bug #887748 */
7961 players_iterate(pplayer) {
7962 city_list_iterate(pplayer->cities, pcity) {
7963 worker_task_list_iterate(pcity->task_reqs, ptask) {
7964 if (!worker_task_is_sane(ptask)) {
7965 log_error("[city id: %d] Bad worker task %d.",
7966 pcity->id, ptask->act);
7967 worker_task_list_remove(pcity->task_reqs, ptask);
7968 free(ptask);
7969 ptask = NULL;
7970 }
7974
7975 /* Check worked tiles map */
7976#ifdef FREECIV_DEBUG
7977 if (loading->worked_tiles != NULL) {
7978 /* check the entire map for unused worked tiles */
7979 whole_map_iterate(&(wld.map), ptile) {
7980 if (loading->worked_tiles[ptile->index] != -1) {
7981 log_error("[city id: %d] Unused worked tile at (%d, %d).",
7982 loading->worked_tiles[ptile->index], TILE_XY(ptile));
7983 }
7985 }
7986#endif /* FREECIV_DEBUG */
7987
7988 /* Check researching technologies and goals. */
7990 int techs;
7991
7992 if (presearch->researching != A_UNSET
7993 && !is_future_tech(presearch->researching)
7994 && (valid_advance_by_number(presearch->researching) == NULL
7996 != TECH_PREREQS_KNOWN))) {
7997 log_sg(_("%s had invalid researching technology."),
7999 presearch->researching = A_UNSET;
8000 }
8001 if (presearch->tech_goal != A_UNSET
8002 && !is_future_tech(presearch->tech_goal)
8003 && (valid_advance_by_number(presearch->tech_goal) == NULL
8006 == TECH_KNOWN))) {
8007 log_sg(_("%s had invalid technology goal."),
8009 presearch->tech_goal = A_UNSET;
8010 }
8011
8013
8014 if (presearch->techs_researched != techs) {
8015 sg_regr(3000300,
8016 _("%s had finished researches count wrong."),
8018 presearch->techs_researched = techs;
8019 }
8021
8022 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8023 players_iterate(pplayer) {
8024 int unique_count[U_LAST];
8025
8026 memset(unique_count, 0, sizeof(unique_count));
8027
8028 unit_list_iterate(pplayer->units, punit) {
8031
8034 log_sg(_("%s has multiple units of type %s though it should be possible "
8035 "to have only one."),
8037 }
8040
8041 players_iterate(pplayer) {
8042 unit_list_iterate_safe(pplayer->units, punit) {
8044 punit->orders.list)) {
8045 log_sg("Invalid unit orders for unit %d.", punit->id);
8047 }
8050
8051 /* Check max rates (rules may have changed since saving) */
8052 players_iterate(pplayer) {
8055
8056 if (0 == strlen(server.game_identifier)
8057 || !is_base64url(server.game_identifier)) {
8058 /* This uses fc_rand(), so random state has to be initialized before. */
8059 randomize_base64url_string(server.game_identifier,
8060 sizeof(server.game_identifier));
8061 }
8062
8063 /* Restore game random state, just in case various initialization code
8064 * inexplicably altered the previously existing state. */
8065 if (!game.info.is_new_game) {
8066 fc_rand_set_state(loading->rstate);
8067 }
8068
8069 /* At the end do the default sanity checks. */
8070 sanity_check();
8071}
8072
8073/************************************************************************/
8077{
8078 /* Check status and return if not OK (sg_success FALSE). */
8079 sg_check_ret();
8080}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
static struct action * actions[MAX_NUM_ACTIONS]
Definition actions.c:97
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2011
struct action * action_by_rule_name(const char *name)
Definition actions.c:1840
const char * action_id_rule_name(action_id act_id)
Definition actions.c:2000
bool action_id_exists(const action_id act_id)
Definition actions.c:1829
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:656
#define NUM_ACTIONS
Definition actions.h:315
#define action_id_get_activity(act_id)
Definition actions.h:701
#define ACTION_NONE
Definition actions.h:311
void building_advisor(struct player *pplayer)
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:263
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:565
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
int ai_type_get_count(void)
Definition ai.c:327
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define ai_type_iterate_end
Definition ai.h:372
#define ai_type_iterate(NAME_ai)
Definition ai.h:365
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:179
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool has_capabilities(const char *us, const char *them)
Definition capability.c:86
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
void citizens_init(struct city *pcity)
Definition citizens.c:32
void citizens_update(struct city *pcity, struct player *plr)
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:148
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c:1145
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
const char * city_style_rule_name(const int style)
Definition city.c:1765
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3430
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2870
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1180
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3357
void destroy_city_virtual(struct city *pcity)
Definition city.c:3516
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:517
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define cities_iterate(pcity)
Definition city.h:512
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:86
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define output_type_iterate(output)
Definition city.h:845
#define FREE_WORKED_TILES
Definition city.h:882
#define MAX_CITY_SIZE
Definition city.h:106
#define city_list_iterate_end
Definition city.h:510
#define I_NEVER
Definition city.h:247
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
#define output_type_iterate_end
Definition city.h:851
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2769
bool send_city_suppression(bool now)
Definition citytools.c:2166
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:137
void city_thaw_workers(struct city *pcity)
Definition citytools.c:147
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2840
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3442
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:367
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:852
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
char * techs
Definition comments.c:31
char * incite_cost
Definition comments.c:75
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
int counter_index(const struct counter *pcount)
Definition counters.c:174
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
int counters_get_city_counters_count(void)
Definition counters.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:111
struct Treaty * ptreaty
Definition diplodlg_g.h:28
void init_treaty(struct Treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:380
bool add_clause(struct Treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaty_add(struct Treaty *ptreaty)
Definition diptreaty.c:361
#define clause_list_iterate_end
Definition diptreaty.h:70
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:68
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1114
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h:354
int Tech_type_id
Definition fc_types.h:377
unsigned char citizens
Definition fc_types.h:388
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:126
#define MAX_LEN_NAME
Definition fc_types.h:66
@ O_LAST
Definition fc_types.h:101
int Multiplier_type_id
Definition fc_types.h:386
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
void initialize_globals(void)
Definition game.c:683
struct city * game_city_by_number(int id)
Definition game.c:107
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:598
#define GAME_DEFAULT_SCORETURN
Definition game.h:582
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:597
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:600
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:599
#define GAME_DEFAULT_RULESETDIR
Definition game.h:676
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:602
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:617
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c:501
void adv_city_alloc(struct city *pcity)
Definition infracache.c:488
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_fatal(message,...)
Definition log.h:100
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1660
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:641
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:1866
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1676
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1696
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1765
void map_init_topology(struct civ_map *nmap)
Definition map.c:303
void main_map_allocate(void)
Definition map.c:519
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
int map_startpos_count(void)
Definition map.c:1853
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:443
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1753
bool map_is_empty(void)
Definition map.c:149
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1643
#define map_startpos_iterate(NAME_psp)
Definition map.h:130
#define MAP_INDEX_SIZE
Definition map.h:137
#define map_startpos_iterate_end
Definition map.h:133
#define whole_map_iterate(_map, _tile)
Definition map.h:545
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:157
#define whole_map_iterate_end
Definition map.h:554
map_generator
Definition map_types.h:46
@ MAPGEN_SCENARIO
Definition map_types.h:47
void assign_continent_numbers(void)
void player_map_init(struct player *pplayer)
Definition maphand.c:1221
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1467
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2207
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:894
bool send_tile_suppression(bool now)
Definition maphand.c:475
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:345
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1196
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1398
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1367
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2220
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1178
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1159
void map_calculate_borders(void)
Definition maphand.c:2373
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1632
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1382
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1311
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1204
int mapimg_count(void)
Definition mapimg.c:573
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
void set_meta_patches_string(const char *string)
Definition meta.c:172
char * meta_addr_port(void)
Definition meta.c:203
const char * default_meta_patches_string(void)
Definition meta.c:83
const char * get_meta_patches_string(void)
Definition meta.c:107
#define DEFAULT_META_SERVER_ADDR
Definition meta.h:21
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
static struct nation_type * nations
Definition nation.c:46
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nation_hash_iterate_end
Definition nation.h:95
#define NO_NATION_SELECTED
Definition nation.h:30
void event_cache_load(struct section_file *file, const char *section)
Definition notify.c:783
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:903
int parts
Definition packhand.c:132
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
int player_count(void)
Definition player.c:817
int player_slot_count(void)
Definition player.c:418
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:463
int player_number(const struct player *pplayer)
Definition player.c:837
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:159
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_max_used_number(void)
Definition player.c:476
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
struct player * player_by_name(const char *name)
Definition player.c:881
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:240
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
int player_index(const struct player *pplayer)
Definition player.c:829
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:861
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1493
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1485
#define players_iterate_end
Definition player.h:537
dipl_reason
Definition player.h:190
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:192
#define players_iterate(_pplayer)
Definition player.h:532
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:221
#define player_list_iterate(playerlist, pplayer)
Definition player.h:555
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define player_slots_iterate(_pslot)
Definition player.h:523
#define is_ai(plr)
Definition player.h:230
#define player_list_iterate_end
Definition player.h:557
#define players_iterate_alive_end
Definition player.h:547
#define player_slots_iterate_end
Definition player.h:527
#define players_iterate_alive(_pplayer)
Definition player.h:542
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2267
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1893
int normal_player_count(void)
Definition plrhand.c:3204
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2056
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2452
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2402
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3250
void shuffle_players(void)
Definition plrhand.c:2377
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1942
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1618
void assign_player_colors(void)
Definition plrhand.c:1733
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3237
void fit_nationset_to_players(void)
Definition plrhand.c:2658
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
bool fc_rand_is_init(void)
Definition rand.c:200
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:50
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
bool entry_str_set_gt_marking(struct entry *pentry, bool gt_marking)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
#define secfile_insert_int_vec(secfile, values, dim, path,...)
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
struct history_report * history_report_get(void)
Definition report.c:1824
const char * universal_rule_name(const struct universal *psource)
const char * universal_type_rule_name(const struct universal *psource)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:668
const char * research_name_translation(const struct research *presearch)
Definition research.c:156
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:637
struct research * research_by_number(int number)
Definition research.c:118
int research_number(const struct research *presearch)
Definition research.c:109
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1345
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
void research_update(struct research *presearch)
Definition research.c:501
#define researches_iterate(_presearch)
Definition research.h:155
#define researches_iterate_end
Definition research.h:158
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Definition rgbcolor.c:74
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, char *path,...)
Definition rgbcolor.c:121
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleset.c:9358
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:205
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:215
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:138
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:227
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:183
#define sg_check_ret(...)
Definition savecompat.h:150
#define sg_warn(condition, message,...)
Definition savecompat.h:160
#define hex_chars
Definition savecompat.h:205
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
#define sg_regr(fixversion, message,...)
Definition savecompat.h:193
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:146
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:171
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:429
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:7819
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1196
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2750
static void unit_ordering_apply(void)
Definition savegame3.c:1077
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3617
static struct loaddata * loaddata_new(struct section_file *file)
Definition savegame3.c:582
static void worklist_save(struct section_file *file, const struct worklist *pwl, int max_length, const char *path,...)
Definition savegame3.c:1010
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3498
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3168
bool sg_success
Definition savecompat.c:34
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:152
static char * quote_block(const void *const data, int length)
Definition savegame3.c:895
#define halfbyte_iterate_extras_end
Definition savegame3.c:260
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:255
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2809
static enum unit_orders char2order(char order)
Definition savegame3.c:708
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:916
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:3000
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3459
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4072
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:219
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5565
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5517
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4949
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2900
static bool sg_load_player_unit(struct loaddata *loading, struct player *plr, struct unit *punit, int orders_max_length, const char *unitstr)
Definition savegame3.c:6038
static char activity2char(int activity)
Definition savegame3.c:821
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:677
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1334
static enum unit_activity char2activity(char activity)
Definition savegame3.c:872
static void unit_ordering_calc(void)
Definition savegame3.c:1048
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2659
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5969
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1248
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2430
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3113
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7465
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3415
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:172
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2039
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2389
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1773
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6524
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7790
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7776
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3289
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7571
static void savegame3_save_real(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:525
#define TOKEN_SIZE
Definition savegame3.c:276
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2468
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2494
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2086
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:696
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4133
static char order2char(enum unit_orders order)
Definition savegame3.c:735
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7666
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2582
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1131
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6577
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2239
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1163
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1261
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7301
static enum direction8 char2dir(char dir)
Definition savegame3.c:759
#define ACTIVITY_LAST_SAVEGAME3
Definition savegame3.c:153
static bool sg_load_player_city(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr, int wlist_max_length, int routes_max)
Definition savegame3.c:5068
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1225
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8076
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7838
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6837
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:6917
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2062
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2860
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7000
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2940
static void worklist_load(struct section_file *file, int wlist_max_length, struct worklist *pwl, const char *path,...)
Definition savegame3.c:964
static void sg_save_mapimg(struct savedata *saving)
Definition savegame3.c:7878
static const char savefile_options_default[]
Definition savegame3.c:278
static char dir2char(enum direction8 dir)
Definition savegame3.c:788
static bool sg_load_player_vision_city(struct loaddata *loading, struct player *plr, struct vision_site *pdcity, const char *citystr)
Definition savegame3.c:7190
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2697
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3026
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:621
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3877
#define PART_ADJUST
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1297
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7646
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:2968
static void treaty_save(struct Treaty *ptr, void *data_in)
Definition savegame3.c:7749
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:7903
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7635
void savegame3_load(struct section_file *file)
Definition savegame3.c:456
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1098
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2259
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4623
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2479
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2675
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3554
void script_server_state_save(struct section_file *file)
void script_server_state_load(struct section_file *file)
void settings_game_load(struct section_file *file, const char *section)
Definition settings.c:4946
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4858
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
sex_t sex_by_name(const char *name)
Definition sex.c:27
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1101
bool str_to_int(const char *str, int *pint)
Definition shared.c:517
const struct strvec * get_scenario_dirs(void)
Definition shared.c:978
bool is_base64url(const char *s)
Definition shared.c:318
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1922
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:339
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX_LEN_PATH
Definition shared.h:32
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
@ SSHIP_LAUNCHED
Definition spaceship.h:85
@ SSHIP_NONE
Definition spaceship.h:84
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
void server_game_init(bool keep_ruleset_value)
Definition srv_main.c:3463
const char * aifill(int amount)
Definition srv_main.c:2465
bool game_was_started(void)
Definition srv_main.c:349
void identity_number_reserve(int id)
Definition srv_main.c:1994
struct server_arguments srvarg
Definition srv_main.c:176
void init_game_seed(void)
Definition srv_main.c:203
void update_nations_with_startpos(void)
Definition srv_main.c:2270
enum server_states server_state(void)
Definition srv_main.c:333
void server_game_free(void)
Definition srv_main.c:3487
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * plr0
Definition diptreaty.h:79
bool accept0
Definition diptreaty.h:80
bool accept1
Definition diptreaty.h:80
struct clause_list * clauses
Definition diptreaty.h:81
struct player * plr1
Definition diptreaty.h:79
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
int turn
Definition city.h:246
Definition city.h:320
struct worker_task_list * task_reqs
Definition city.h:412
int turn_last_built
Definition city.h:387
enum city_wl_cancel_behavior wlcb
Definition city.h:404
int food_stock
Definition city.h:367
struct built_status built[B_LAST]
Definition city.h:394
struct player * original
Definition city.h:324
int history
Definition city.h:410
int * counter_values
Definition city.h:408
bool did_sell
Definition city.h:380
int id
Definition city.h:326
int last_turns_shield_surplus
Definition city.h:392
int disbanded_shields
Definition city.h:391
int turn_plague
Definition city.h:374
bv_city_options city_options
Definition city.h:403
bool was_happy
Definition city.h:381
enum city_acquire_type acquire_t
Definition city.h:329
int turn_founded
Definition city.h:386
int airlift
Definition city.h:378
int caravan_shields
Definition city.h:390
bool did_buy
Definition city.h:379
struct trade_route_list * routes
Definition city.h:344
int anarchy
Definition city.h:384
struct worklist worklist
Definition city.h:401
struct universal production
Definition city.h:396
struct unit_order * orders
Definition city.h:422
struct city::@16 rally_point
struct adv_city * adv
Definition city.h:452
bool vigilant
Definition city.h:421
int steal
Definition city.h:414
int before_change_shields
Definition city.h:389
int style
Definition city.h:327
bool had_famine
Definition city.h:382
size_t length
Definition city.h:417
bool synced
Definition city.h:448
citizens specialists[SP_MAX]
Definition city.h:336
struct tile * tile
Definition city.h:322
int shield_stock
Definition city.h:368
struct vision * vision
Definition city.h:455
struct city::@17::@19 server
struct cm_parameter * cm_parameter
Definition city.h:425
struct universal changed_from
Definition city.h:399
struct unit_list * units_supported
Definition city.h:406
bool persistent
Definition city.h:419
int rapture
Definition city.h:385
bool multiresearch
Definition game.h:167
bool last_updated_year
Definition game.h:240
float turn_change_time
Definition game.h:222
bool vision_reveal_tiles
Definition game.h:204
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:265
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:238
struct civ_game::@31::@35::@37 save_options
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:211
char rulesetdir[MAX_LEN_NAME]
Definition game.h:242
int additional_phase_seconds
Definition game.h:216
struct section_file * luadata
Definition game.h:250
int scoreturn
Definition game.h:229
randseed seed
Definition game.h:231
int dbid
Definition game.h:251
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:207
struct timer * phase_timer
Definition game.h:215
unsigned revealmap
Definition game.h:181
char orig_game_version[MAX_LEN_NAME]
Definition game.h:225
bool save_known
Definition game.h:262
bool foggedborders
Definition game.h:151
struct civ_game::@31::@35 server
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:209
int timeoutinc
Definition game.h:208
int phase_mode_stored
Definition game.h:220
int max_players
Definition game.h:160
bool save_starts
Definition game.h:264
int timeoutintinc
Definition game.h:210
int xsize
Definition map_types.h:78
randseed seed
Definition map_types.h:92
int ysize
Definition map_types.h:78
bool have_resources
Definition map_types.h:108
struct civ_map::@42::@44 server
bool have_huts
Definition map_types.h:107
enum map_generator generator
Definition map_types.h:98
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
int changed_to_times
Definition government.h:64
struct section_file * file
Definition savecompat.h:48
int great_wonder_owners[B_LAST]
bool global_advances[A_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char version[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char datafile[MAX_LEN_NAME]
char authors[MAX_LEN_PACKET/3]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:114
struct ai_trait * traits
Definition player.h:124
enum barbarian_type barbarian_type
Definition player.h:120
int science_cost
Definition player.h:117
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:122
int expand
Definition player.h:116
int fuzzy
Definition player.h:115
enum diplstate_type type
Definition player.h:197
int infra_points
Definition player.h:65
int units_killed
Definition player.h:103
int landarea
Definition player.h:92
int population
Definition player.h:94
int pollution
Definition player.h:97
int wonders
Definition player.h:89
int settledarea
Definition player.h:93
int units_used
Definition player.h:106
int specialists[SP_MAX]
Definition player.h:88
int units_lost
Definition player.h:104
int angry
Definition player.h:87
int techout
Definition player.h:91
int units
Definition player.h:96
int units_built
Definition player.h:102
int content
Definition player.h:85
int happy
Definition player.h:84
int spaceship
Definition player.h:101
int culture
Definition player.h:107
int unhappy
Definition player.h:86
int cities
Definition player.h:95
int literacy
Definition player.h:98
int techs
Definition player.h:90
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:279
int bulbs_last_turn
Definition player.h:349
struct player_ai ai_common
Definition player.h:286
bv_plr_flags flags
Definition player.h:290
bool is_male
Definition player.h:255
int wonders[B_LAST]
Definition player.h:303
bool unassigned_ranked
Definition player.h:253
struct government * target_government
Definition player.h:257
int autoselect_weight
Definition player.h:297
char username[MAX_LEN_NAME]
Definition player.h:250
int revolution_finishes
Definition player.h:271
int nturns_idle
Definition player.h:263
struct government * government
Definition player.h:256
struct team * team
Definition player.h:259
int turns_alive
Definition player.h:264
const struct ai_type * ai
Definition player.h:287
struct unit_list * units
Definition player.h:280
char ranked_username[MAX_LEN_NAME]
Definition player.h:252
int huts
Definition player.h:347
bool is_alive
Definition player.h:266
bv_player real_embassy
Definition player.h:275
struct player_economic economic
Definition player.h:282
struct player_spaceship spaceship
Definition player.h:284
struct attribute_block_s attribute_block
Definition player.h:305
struct player_score score
Definition player.h:281
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:312
struct nation_type * nation
Definition player.h:258
struct nation_style * style
Definition player.h:277
bool border_vision
Definition player.h:325
bool phase_done
Definition player.h:261
struct adv_data * adv
Definition player.h:332
struct player::@70::@72 server
int history
Definition player.h:314
char orig_username[MAX_LEN_NAME]
Definition player.h:345
int last_war_action
Definition player.h:268
struct rgbcolor * rgb
Definition player.h:310
bool unassigned_user
Definition player.h:251
const char * save_reason
Definition savegame3.c:269
struct section_file * file
Definition savegame3.c:265
bool scenario
Definition savegame3.c:270
bool save_players
Definition savegame3.c:273
char secfile_options[512]
Definition savegame3.c:266
char metaserver_addr[256]
Definition srv_main.h:29
char serverid[256]
Definition srv_main.h:49
Definition map.c:41
Definition team.c:40
char identifier
Definition terrain.h:191
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int infra_turns
Definition tile.h:62
struct extra_type * placing
Definition tile.h:61
struct tile * claimer
Definition tile.h:64
Definition timing.c:81
enum route_direction dir
Definition traderoutes.h:86
struct section_file * file
Definition savegame3.c:7743
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:138
int length
Definition unit.h:195
int upkeep[O_LAST]
Definition unit.h:148
bool has_orders
Definition unit.h:193
struct unit::@80 orders
enum action_decision action_decision_want
Definition unit.h:202
int battlegroup
Definition unit.h:191
enum unit_activity activity
Definition unit.h:157
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
int ord_city
Definition unit.h:242
bool moved
Definition unit.h:173
int ord_map
Definition unit.h:241
int index
Definition unit.h:195
struct vision * vision
Definition unit.h:244
bool vigilant
Definition unit.h:197
int hp
Definition unit.h:151
int fuel
Definition unit.h:153
struct extra_type * changed_from_target
Definition unit.h:170
int current_form_turn
Definition unit.h:208
bool stay
Definition unit.h:205
enum direction8 facing
Definition unit.h:142
struct unit::@81::@84 server
struct extra_type * activity_target
Definition unit.h:164
int activity_count
Definition unit.h:162
struct unit_order * list
Definition unit.h:198
enum unit_activity changed_from
Definition unit.h:168
struct player * nationality
Definition unit.h:144
bool repeat
Definition unit.h:196
int homecity
Definition unit.h:146
bool paradropped
Definition unit.h:174
bool done_moving
Definition unit.h:181
int birth_turn
Definition unit.h:207
struct goods_type * carrying
Definition unit.h:186
struct tile * goto_tile
Definition unit.h:155
struct tile * action_decision_tile
Definition unit.h:203
int veteran
Definition unit.h:152
int changed_from_count
Definition unit.h:169
enum server_side_agent ssa_controller
Definition unit.h:172
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct civ_map map
int city_style(struct city *pcity)
Definition style.c:241
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
int team_index(const struct team *pteam)
Definition team.c:383
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
bool team_add_player(struct player *pplayer, struct team *pteam)
Definition team.c:467
struct team * team_new(struct team_slot *tslot)
Definition team.c:317
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:248
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:275
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:276
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:244
void init_tech(struct research *research, bool update)
Definition techtools.c:1094
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:255
#define terrain_type_iterate(_p)
Definition terrain.h:373
#define T_UNKNOWN
Definition terrain.h:57
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:195
#define terrain_type_iterate_end
Definition terrain.h:379
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1095
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
void tile_set_worked(struct tile *ptile, struct city *pcity)
Definition tile.c:106
#define tile_index(_pt_)
Definition tile.h:88
#define tile_worked(_tile)
Definition tile.h:114
#define tile_terrain(_tile)
Definition tile.h:110
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
#define tile_owner(_tile)
Definition tile.h:96
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:264
void timer_stop(struct timer *t)
Definition timing.c:308
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:384
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
const struct impr_type * building
Definition fc_types.h:714
void free_unit_orders(struct unit *punit)
Definition unit.c:1769
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2370
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1088
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1245
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2441
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:841
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target)
Definition unit.c:1105
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1624
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2649
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1729
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1255
#define unit_tile(_pu)
Definition unit.h:397
#define BATTLEGROUP_NONE
Definition unit.h:190
unit_orders
Definition unit.h:37
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_owner(_pu)
Definition unit.h:396
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1394
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4840
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1221
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1058
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2625
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
#define unit_type_iterate(_p)
Definition unittype.h:855
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:862
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:129
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24