Freeciv-3.4
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 "ruleload.h"
121#include "sanitycheck.h"
122#include "score.h"
123#include "settings.h"
124#include "spacerace.h"
125#include "srv_main.h"
126#include "stdinhand.h"
127#include "techtools.h"
128#include "unittools.h"
129
130/* server/advisors */
131#include "advdata.h"
132#include "advbuilding.h"
133#include "infracache.h"
134
135/* server/generator */
136#include "mapgen.h"
137#include "mapgen_utils.h"
138
139/* server/scripting */
140#include "script_server.h"
141
142/* server/savegame */
143#include "savecompat.h"
144#include "savemain.h"
145
146/* ai */
147#include "aitraits.h"
148#include "difficulty.h"
149
150#include "savegame3.h"
151
152extern bool sg_success;
153
154#define ACTIVITY_OLD_POLLUTION_SG3 (ACTIVITY_LAST + 1)
155#define ACTIVITY_OLD_FALLOUT_SG3 (ACTIVITY_OLD_POLLUTION_SG3 + 1)
156#define ACTIVITY_LAST_SAVEGAME3 (ACTIVITY_OLD_FALLOUT_SG3 + 1)
157
158#ifdef FREECIV_TESTMATIC
159#define SAVE_DUMMY_TURN_CHANGE_TIME 1
160#endif
161
162/*
163 * This loops over the entire map to save data. It collects all the data of
164 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
165 *
166 * Parameters:
167 * ptile: current tile within the line (used by GET_XY_CHAR)
168 * GET_XY_CHAR: macro returning the map character for each position
169 * secfile: a secfile struct
170 * secpath, ...: path as used for sprintf() with arguments; the last item
171 * will be the y coordinate
172 * Example:
173 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
174 */
175#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
176{ \
177 char _line[MAP_NATIVE_WIDTH + 1]; \
178 int _nat_x, _nat_y; \
179 \
180 for (_nat_y = 0; _nat_y < MAP_NATIVE_HEIGHT; _nat_y++) { \
181 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _nat_x++) { \
182 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
183 \
184 fc_assert_action(ptile != nullptr, continue); \
185 \
186 _line[_nat_x] = (GET_XY_CHAR); \
187 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
188 "Trying to write invalid map data at position " \
189 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
190 secpath, _line[_nat_x], _line[_nat_x]); \
191 } \
192 _line[MAP_NATIVE_WIDTH] = '\0'; \
193 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
194 } \
195}
196
197/*
198 * This loops over the entire map to load data. It inputs a line of data
199 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
200 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
201 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
202 * macro but definable by the caller.
203 *
204 * Parameters:
205 * ch: a variable to hold a char (data for a single position,
206 * used by SET_XY_CHAR)
207 * ptile: current tile within the line (used by SET_XY_CHAR)
208 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
209 * secfile: a secfile struct
210 * secpath, ...: path as used for sprintf() with arguments; the last item
211 * will be the y coordinate
212 * Example:
213 * LOAD_MAP_CHAR(ch, ptile,
214 * map_get_player_tile(ptile, plr)->terrain
215 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
216 *
217 * Note: some (but not all) of the code this is replacing used to skip over
218 * lines that did not exist. This allowed for backward-compatibility.
219 * We could add another parameter that specified whether it was OK to
220 * skip the data, but there's not really much advantage to exiting
221 * early in this case. Instead, we let any map data type to be empty,
222 * and just print an informative warning message about it.
223 */
224#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
225{ \
226 int _nat_x, _nat_y; \
227 bool _printed_warning = FALSE; \
228 for (_nat_y = 0; _nat_y < MAP_NATIVE_HEIGHT; _nat_y++) { \
229 const char *_line = secfile_lookup_str(secfile, secpath, \
230 ## __VA_ARGS__, _nat_y); \
231 if (_line == nullptr) { \
232 char buf[64]; \
233 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
234 log_verbose("Line not found='%s'", buf); \
235 _printed_warning = TRUE; \
236 continue; \
237 } else if (strlen(_line) != MAP_NATIVE_WIDTH) { \
238 char buf[64]; \
239 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
240 log_verbose("Line too short (expected %d got " SIZE_T_PRINTF \
241 ")='%s'", MAP_NATIVE_WIDTH, strlen(_line), buf); \
242 _printed_warning = TRUE; \
243 continue; \
244 } \
245 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _nat_x++) { \
246 const char ch = _line[_nat_x]; \
247 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
248 (SET_XY_CHAR); \
249 } \
250 } \
251 if (_printed_warning) { \
252 /* TRANS: Minor error message. */ \
253 log_sg(_("Saved game contains incomplete map data. This can" \
254 " happen with old saved games, or it may indicate an" \
255 " invalid saved game file. Proceed at your own risk.")); \
256 } \
257}
258
259/* Iterate on the extras half-bytes */
260#define halfbyte_iterate_extras(e, num_extras_types) \
261{ \
262 int e; \
263 for (e = 0; 4 * e < (num_extras_types); e++) {
264
265#define halfbyte_iterate_extras_end \
266 } \
267}
268
269struct savedata {
272
273 /* set by the caller */
274 const char *save_reason;
276
277 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
279};
280
281#define TOKEN_SIZE 10
282
283static const char savefile_options_default[] =
284 " +version3";
285/* The following savefile option are added if needed:
286 * - nothing at current version
287 * See also calls to sg_save_savefile_options(). */
288
289static void savegame3_save_real(struct section_file *file,
290 const char *save_reason,
291 bool scenario);
292static struct loaddata *loaddata_new(struct section_file *file);
293static void loaddata_destroy(struct loaddata *loading);
294
295static struct savedata *savedata_new(struct section_file *file,
296 const char *save_reason,
297 bool scenario);
298static void savedata_destroy(struct savedata *saving);
299
300static enum unit_orders char2order(char order);
301static char order2char(enum unit_orders order);
302static enum direction8 char2dir(char dir);
303static char dir2char(enum direction8 dir);
304static char activity2char(int activity);
305static enum unit_activity char2activity(char activity);
306static char *quote_block(const void *const data, int length);
307static int unquote_block(const char *const quoted_, void *dest,
308 int dest_length);
309static void worklist_load(struct section_file *file, int wlist_max_length,
310 struct worklist *pwl, const char *path, ...);
311static void worklist_save(struct section_file *file,
312 const struct worklist *pwl,
313 int max_length, const char *path, ...);
314static void unit_ordering_calc(void);
315static void unit_ordering_apply(void);
316static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx);
317static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx);
318static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
319 const int *idx);
320static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
321 const int *idx);
322static struct terrain *char2terrain(char ch);
323static char terrain2char(const struct terrain *pterrain);
324static Tech_type_id technology_load(struct section_file *file,
325 const char *path, int plrno);
326static void technology_save(struct section_file *file,
327 const char *path, int plrno, Tech_type_id tech);
328
329static void sg_load_savefile(struct loaddata *loading);
330static void sg_save_savefile(struct savedata *saving);
331static void sg_save_savefile_options(struct savedata *saving,
332 const char *option);
333
334static void sg_load_game(struct loaddata *loading);
335static void sg_save_game(struct savedata *saving);
336
337static void sg_load_ruledata(struct loaddata *loading);
338static void sg_save_ruledata(struct savedata *saving);
339
340static void sg_load_random(struct loaddata *loading);
341static void sg_save_random(struct savedata *saving);
342
343static void sg_load_script(struct loaddata *loading);
344static void sg_save_script(struct savedata *saving);
345
346static void sg_load_scenario(struct loaddata *loading);
347static void sg_save_scenario(struct savedata *saving);
348
349static void sg_load_settings(struct loaddata *loading);
350static void sg_save_settings(struct savedata *saving);
351
352static void sg_load_counters (struct loaddata * loading);
353static void sg_save_counters (struct savedata * saving);
354
355static void sg_load_map(struct loaddata *loading);
356static void sg_save_map(struct savedata *saving);
357static void sg_load_map_tiles(struct loaddata *loading);
358static void sg_load_map_altitude(struct loaddata *loading);
359static void sg_save_map_tiles(struct savedata *saving);
360static void sg_save_map_altitude(struct savedata *saving);
361static void sg_load_map_tiles_extras(struct loaddata *loading);
362static void sg_save_map_tiles_extras(struct savedata *saving);
363
364static void sg_load_map_startpos(struct loaddata *loading);
365static void sg_save_map_startpos(struct savedata *saving);
366static void sg_load_map_owner(struct loaddata *loading);
367static void sg_save_map_owner(struct savedata *saving);
368static void sg_load_map_worked(struct loaddata *loading);
369static void sg_save_map_worked(struct savedata *saving);
370static void sg_load_map_known(struct loaddata *loading);
371static void sg_save_map_known(struct savedata *saving);
372
373static void sg_load_players_basic(struct loaddata *loading);
374static void sg_load_players(struct loaddata *loading);
375static void sg_load_player_main(struct loaddata *loading,
376 struct player *plr);
377static void sg_load_player_cities(struct loaddata *loading,
378 struct player *plr);
379static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
380 struct city *pcity, const char *citystr,
383 struct player *plr,
384 struct city *pcity,
385 const char *citystr);
386static void sg_load_player_units(struct loaddata *loading,
387 struct player *plr);
388static bool sg_load_player_unit(struct loaddata *loading,
389 struct player *plr, struct unit *punit,
391 const char *unitstr);
393 struct player *plr);
394static void sg_load_player_attributes(struct loaddata *loading,
395 struct player *plr);
396static void sg_load_player_vision(struct loaddata *loading,
397 struct player *plr);
399 struct player *plr,
400 struct vision_site *pdcity,
401 const char *citystr);
402static void sg_save_players(struct savedata *saving);
403static void sg_save_player_main(struct savedata *saving,
404 struct player *plr);
405static void sg_save_player_cities(struct savedata *saving,
406 struct player *plr);
407static void sg_save_player_units(struct savedata *saving,
408 struct player *plr);
409static void sg_save_player_attributes(struct savedata *saving,
410 struct player *plr);
411static void sg_save_player_vision(struct savedata *saving,
412 struct player *plr);
413
414static void sg_load_researches(struct loaddata *loading);
415static void sg_save_researches(struct savedata *saving);
416
417static void sg_load_event_cache(struct loaddata *loading);
418static void sg_save_event_cache(struct savedata *saving);
419
420static void sg_load_treaties(struct loaddata *loading);
421static void sg_save_treaties(struct savedata *saving);
422
423static void sg_load_history(struct loaddata *loading);
424static void sg_save_history(struct savedata *saving);
425
426static void sg_load_mapimg(struct loaddata *loading);
427static void sg_save_mapimg(struct savedata *saving);
428
429static void sg_load_sanitycheck(struct loaddata *loading);
430static void sg_save_sanitycheck(struct savedata *saving);
431
432
433/************************************************************************/
436void savegame3_save(struct section_file *sfile, const char *save_reason,
437 bool scenario)
438{
439 fc_assert_ret(sfile != nullptr);
440
441#ifdef DEBUG_TIMERS
442 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
444#endif
445
446 log_verbose("saving game in new format ...");
447 savegame3_save_real(sfile, save_reason, scenario);
448
449#ifdef DEBUG_TIMERS
451 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
453#endif /* DEBUG_TIMERS */
454}
455
456/* =======================================================================
457 * Basic load / save functions.
458 * ======================================================================= */
459
460/************************************************************************/
463void savegame3_load(struct section_file *file)
464{
465 struct loaddata *loading;
467
468 /* initialise loading */
473
474 /* Load the savegame data. */
475 /* [compat] */
477 /* [scenario] */
479 /* [savefile] */
481 /* [game] */
483 /* [random] */
485 /* [settings] */
487 /* [ruledata] */
489 /* [players] (basic data) */
491 /* [map]; needs width and height loaded by [settings] */
493 /* [research] */
495 /* [player<i>] */
497 /* [counters] */
499 /* [event_cache] */
501 /* [treaties] */
503 /* [history] */
505 /* [mapimg] */
507 /* [script] -- must come last as may reference game objects */
509 /* [post_load_compat]; needs the game loaded by [savefile] */
511
512 /* Sanity checks for the loaded game. */
514
515 /* deinitialise loading */
519
520 if (!sg_success) {
521 log_error("Failure loading savegame!");
523 }
524}
525
526/************************************************************************/
530 const char *save_reason,
531 bool scenario)
532{
533 struct savedata *saving;
534
535 /* initialise loading */
538
539 /* [scenario] */
540 /* This should be first section so scanning through all scenarios just for
541 * names and descriptions would go faster. */
543 /* [savefile] */
545 /* [counters] */
547 /* [game] */
549 /* [random] */
551 /* [script] */
553 /* [settings] */
555 /* [ruledata] */
557 /* [map] */
559 /* [player<i>] */
561 /* [research] */
563 /* [event_cache] */
565 /* [treaty<i>] */
567 /* [history] */
569 /* [mapimg] */
571
572 /* Sanity checks for the saved game. */
574
575 /* deinitialise saving */
577
578 if (!sg_success) {
579 log_error("Failure saving savegame!");
580 }
581}
582
583/************************************************************************/
586static struct loaddata *loaddata_new(struct section_file *file)
587{
588 struct loaddata *loading = calloc(1, sizeof(*loading));
589 loading->file = file;
590 loading->secfile_options = nullptr;
591
592 loading->improvement.order = nullptr;
593 loading->improvement.size = -1;
594 loading->technology.order = nullptr;
595 loading->technology.size = -1;
596 loading->activities.order = nullptr;
597 loading->activities.size = -1;
598 loading->trait.order = nullptr;
599 loading->trait.size = -1;
600 loading->extra.order = nullptr;
601 loading->extra.size = -1;
602 loading->multiplier.order = nullptr;
603 loading->multiplier.size = -1;
604 loading->specialist.order = nullptr;
605 loading->specialist.size = -1;
606 loading->action.order = nullptr;
607 loading->action.size = -1;
608 loading->act_dec.order = nullptr;
609 loading->act_dec.size = -1;
610 loading->ssa.order = nullptr;
611 loading->ssa.size = -1;
612 loading->coptions.order = nullptr;
613 loading->coptions.size = -1;
614
615 loading->server_state = S_S_INITIAL;
616 loading->rstate = fc_rand_state();
617 loading->worked_tiles = nullptr;
618
619 return loading;
620}
621
622/************************************************************************/
626{
627 if (loading->improvement.order != nullptr) {
628 free(loading->improvement.order);
629 }
630
631 if (loading->technology.order != nullptr) {
632 free(loading->technology.order);
633 }
634
635 if (loading->activities.order != nullptr) {
636 free(loading->activities.order);
637 }
638
639 if (loading->trait.order != nullptr) {
640 free(loading->trait.order);
641 }
642
643 if (loading->extra.order != nullptr) {
644 free(loading->extra.order);
645 }
646
647 if (loading->multiplier.order != nullptr) {
648 free(loading->multiplier.order);
649 }
650
651 if (loading->specialist.order != nullptr) {
652 free(loading->specialist.order);
653 }
654
655 if (loading->action.order != nullptr) {
656 free(loading->action.order);
657 }
658
659 if (loading->act_dec.order != nullptr) {
660 free(loading->act_dec.order);
661 }
662
663 if (loading->ssa.order != nullptr) {
664 free(loading->ssa.order);
665 }
666
667 if (loading->coptions.order != nullptr) {
668 free(loading->coptions.order);
669 }
670
671 if (loading->worked_tiles != nullptr) {
672 free(loading->worked_tiles);
673 }
674
675 free(loading);
676}
677
678/************************************************************************/
681static struct savedata *savedata_new(struct section_file *file,
682 const char *save_reason,
683 bool scenario)
684{
685 struct savedata *saving = calloc(1, sizeof(*saving));
686 saving->file = file;
687 saving->secfile_options[0] = '\0';
688
689 saving->save_reason = save_reason;
690 saving->scenario = scenario;
691
692 saving->save_players = FALSE;
693
694 return saving;
695}
696
697/************************************************************************/
700static void savedata_destroy(struct savedata *saving)
701{
702 free(saving);
703}
704
705/* =======================================================================
706 * Helper functions.
707 * ======================================================================= */
708
709/************************************************************************/
712static enum unit_orders char2order(char order)
713{
714 switch (order) {
715 case 'm':
716 case 'M':
717 return ORDER_MOVE;
718 case 'w':
719 case 'W':
720 return ORDER_FULL_MP;
721 case 'a':
722 case 'A':
723 return ORDER_ACTIVITY;
724 case 'x':
725 case 'X':
726 return ORDER_ACTION_MOVE;
727 case 'p':
728 case 'P':
730 }
731
732 /* This can happen if the savegame is invalid. */
733 return ORDER_LAST;
734}
735
736/************************************************************************/
739static char order2char(enum unit_orders order)
740{
741 switch (order) {
742 case ORDER_MOVE:
743 return 'm';
744 case ORDER_FULL_MP:
745 return 'w';
746 case ORDER_ACTIVITY:
747 return 'a';
749 return 'x';
751 return 'p';
752 case ORDER_LAST:
753 break;
754 }
755
757 return '?';
758}
759
760/************************************************************************/
763static enum direction8 char2dir(char dir)
764{
765 /* Numberpad values for the directions. */
766 switch (dir) {
767 case '1':
768 return DIR8_SOUTHWEST;
769 case '2':
770 return DIR8_SOUTH;
771 case '3':
772 return DIR8_SOUTHEAST;
773 case '4':
774 return DIR8_WEST;
775 case '6':
776 return DIR8_EAST;
777 case '7':
778 return DIR8_NORTHWEST;
779 case '8':
780 return DIR8_NORTH;
781 case '9':
782 return DIR8_NORTHEAST;
783 }
784
785 /* This can happen if the savegame is invalid. */
786 return direction8_invalid();
787}
788
789/************************************************************************/
792static char dir2char(enum direction8 dir)
793{
794 /* Numberpad values for the directions. */
795 switch (dir) {
796 case DIR8_NORTH:
797 return '8';
798 case DIR8_SOUTH:
799 return '2';
800 case DIR8_EAST:
801 return '6';
802 case DIR8_WEST:
803 return '4';
804 case DIR8_NORTHEAST:
805 return '9';
806 case DIR8_NORTHWEST:
807 return '7';
808 case DIR8_SOUTHEAST:
809 return '3';
810 case DIR8_SOUTHWEST:
811 return '1';
812 }
813
815
816 return '?';
817}
818
819/************************************************************************/
825static char activity2char(int activity)
826{
827 switch (activity) {
828 case ACTIVITY_IDLE:
829 return 'w';
830 case ACTIVITY_CLEAN:
831 return 'C';
833 return 'p';
834 case ACTIVITY_MINE:
835 return 'm';
836 case ACTIVITY_PLANT:
837 return 'M';
839 return 'i';
841 return 'I';
843 return 'f';
844 case ACTIVITY_SENTRY:
845 return 's';
846 case ACTIVITY_PILLAGE:
847 return 'e';
848 case ACTIVITY_GOTO:
849 return 'g';
850 case ACTIVITY_EXPLORE:
851 return 'x';
853 return 'o';
855 return 'y';
857 return 'u';
858 case ACTIVITY_BASE:
859 return 'b';
861 return 'R';
862 case ACTIVITY_CONVERT:
863 return 'c';
864 case ACTIVITY_LAST:
865 break;
866 }
867
869
870 return '?';
871}
872
873/************************************************************************/
876static enum unit_activity char2activity(char activity)
877{
878 enum unit_activity a;
879
880 for (a = 0; a < ACTIVITY_LAST_SAVEGAME3; a++) {
881 /* Skip ACTIVITY_LAST. The SAVEGAME3 specific values are after it. */
882 if (a != ACTIVITY_LAST) {
883 char achar = activity2char(a);
884
885 if (activity == achar) {
886 return a;
887 }
888 }
889 }
890
891 /* This can happen if the savegame is invalid. */
892 return ACTIVITY_LAST;
893}
894
895/************************************************************************/
899static char *quote_block(const void *const data, int length)
900{
901 char *buffer = fc_malloc(length * 3 + 10);
902 size_t offset;
903 int i;
904
905 sprintf(buffer, "%d:", length);
906 offset = strlen(buffer);
907
908 for (i = 0; i < length; i++) {
909 sprintf(buffer + offset, "%02x ", ((unsigned char *) data)[i]);
910 offset += 3;
911 }
912 return buffer;
913}
914
915/************************************************************************/
920static int unquote_block(const char *const quoted_, void *dest,
921 int dest_length)
922{
923 int i, length, parsed, tmp;
924 char *endptr;
925 const char *quoted = quoted_;
926
927 parsed = sscanf(quoted, "%d", &length);
928
929 if (parsed != 1) {
930 log_error(_("Syntax error in attribute block."));
931 return 0;
932 }
933
934 if (length > dest_length) {
935 return 0;
936 }
937
938 quoted = strchr(quoted, ':');
939
940 if (quoted == nullptr) {
941 log_error(_("Syntax error in attribute block."));
942 return 0;
943 }
944
945 quoted++;
946
947 for (i = 0; i < length; i++) {
948 tmp = strtol(quoted, &endptr, 16);
949
950 if ((endptr - quoted) != 2
951 || *endptr != ' '
952 || (tmp & 0xff) != tmp) {
953 log_error(_("Syntax error in attribute block."));
954 return 0;
955 }
956
957 ((unsigned char *) dest)[i] = tmp;
958 quoted += 3;
959 }
960
961 return length;
962}
963
964/************************************************************************/
969 struct worklist *pwl, const char *path, ...)
970{
971 int i;
972 const char *kind;
973 const char *name;
974 char path_str[1024];
975 va_list ap;
976
977 /* The first part of the registry path is taken from the varargs to the
978 * function. */
979 va_start(ap, path);
980 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
981 va_end(ap);
982
985 "%s.wl_length", path_str);
986 if (pwl->length > MAX_LEN_WORKLIST) {
987 log_sg("worklist length %d, while MAX_LEN_WORKLIST %d.",
988 pwl->length, MAX_LEN_WORKLIST);
989 pwl->length = MAX_LEN_WORKLIST;
990 } else if (pwl->length > wlist_max_length) {
991 log_sg("worklist length %d, while player's max worklist length %d.",
992 pwl->length, wlist_max_length);
993 }
994
995 for (i = 0; i < pwl->length; i++) {
996 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
997
998 /* We lookup the production value by name. An invalid entry isn't a
999 * fatal error; we just truncate the worklist. */
1000 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
1001 path_str, i);
1002 pwl->entries[i] = universal_by_rule_name(kind, name);
1003 if (pwl->entries[i].kind == universals_n_invalid()) {
1004 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
1005 name);
1006 pwl->length = i;
1007 break;
1008 }
1009 }
1010
1011 /* Padding entries */
1012 for (; i < wlist_max_length; i++) {
1013 secfile_entry_ignore(file, "%s.wl_kind%d", path_str, i);
1014 secfile_entry_ignore(file, "%s.wl_value%d", path_str, i);
1015 }
1016}
1017
1018/************************************************************************/
1022static void worklist_save(struct section_file *file,
1023 const struct worklist *pwl,
1024 int max_length, const char *path, ...)
1025{
1026 char path_str[1024];
1027 int i;
1028 va_list ap;
1029
1030 /* The first part of the registry path is taken from the varargs to the
1031 * function. */
1032 va_start(ap, path);
1033 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1034 va_end(ap);
1035
1036 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1037
1038 for (i = 0; i < pwl->length; i++) {
1039 const struct universal *entry = pwl->entries + i;
1041 "%s.wl_kind%d", path_str, i);
1043 "%s.wl_value%d", path_str, i);
1044 }
1045
1047
1048 /* We want to keep savegame in tabular format, so each line has to be
1049 * of equal length. Fill table up to maximum worklist size. */
1050 for (i = pwl->length ; i < max_length; i++) {
1051 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1052 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1053 }
1054}
1055
1056/************************************************************************/
1060static void unit_ordering_calc(void)
1061{
1062 int j;
1063
1064 players_iterate(pplayer) {
1065 /* to avoid junk values for unsupported units: */
1066 unit_list_iterate(pplayer->units, punit) {
1067 punit->server.ord_city = 0;
1069 city_list_iterate(pplayer->cities, pcity) {
1070 j = 0;
1071 unit_list_iterate(pcity->units_supported, punit) {
1072 punit->server.ord_city = j++;
1076
1077 whole_map_iterate(&(wld.map), ptile) {
1078 j = 0;
1079 unit_list_iterate(ptile->units, punit) {
1080 punit->server.ord_map = j++;
1083}
1084
1085/************************************************************************/
1089static void unit_ordering_apply(void)
1090{
1091 players_iterate(pplayer) {
1092 city_list_iterate(pplayer->cities, pcity) {
1093 unit_list_sort_ord_city(pcity->units_supported);
1094 }
1097
1098 whole_map_iterate(&(wld.map), ptile) {
1099 unit_list_sort_ord_map(ptile->units);
1101}
1102
1103/************************************************************************/
1110static void sg_extras_set_dbv(struct dbv *extras, char ch,
1111 struct extra_type **idx)
1112{
1113 int i, bin;
1114 const char *pch = strchr(hex_chars, ch);
1115
1116 if (!pch || ch == '\0') {
1117 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1118 bin = 0;
1119 } else {
1120 bin = pch - hex_chars;
1121 }
1122
1123 for (i = 0; i < 4; i++) {
1124 struct extra_type *pextra = idx[i];
1125
1126 if (pextra == nullptr) {
1127 continue;
1128 }
1129 if ((bin & (1 << i))
1130 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1131 dbv_set(extras, extra_index(pextra));
1132 }
1133 }
1134}
1135
1136/************************************************************************/
1144 struct extra_type **idx)
1145{
1146 int i, bin;
1147 const char *pch = strchr(hex_chars, ch);
1148
1149 if (!pch || ch == '\0') {
1150 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1151 bin = 0;
1152 } else {
1153 bin = pch - hex_chars;
1154 }
1155
1156 for (i = 0; i < 4; i++) {
1157 struct extra_type *pextra = idx[i];
1158
1159 if (pextra == nullptr) {
1160 continue;
1161 }
1162 if ((bin & (1 << i))
1163 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1164 BV_SET(*extras, extra_index(pextra));
1165 }
1166 }
1167}
1168
1169/************************************************************************/
1175static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1176 const int *idx)
1177{
1178 int i, bin = 0;
1179 int max = dbv_bits(extras);
1180
1181 for (i = 0; i < 4; i++) {
1182 int extra = idx[i];
1183
1184 if (extra < 0) {
1185 break;
1186 }
1187
1188 if (extra < max
1189 && (dbv_isset(extras, extra)
1190 /* An invalid resource, a resource that can't exist at the tile's
1191 * current terrain, isn't in the bit extra vector. Save it so it
1192 * can return if the tile's terrain changes to something it can
1193 * exist on. */
1194 || extra_by_number(extra) == presource)) {
1195 bin |= (1 << i);
1196 }
1197 }
1198
1199 return hex_chars[bin];
1200}
1201
1202/************************************************************************/
1208static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1209 const int *idx)
1210{
1211 int i, bin = 0;
1212
1213 for (i = 0; i < 4; i++) {
1214 int extra = idx[i];
1215
1216 if (extra < 0) {
1217 break;
1218 }
1219
1220 if (BV_ISSET(extras, extra)
1221 /* An invalid resource, a resource that can't exist at the tile's
1222 * current terrain, isn't in the bit extra vector. Save it so it
1223 * can return if the tile's terrain changes to something it can
1224 * exist on. */
1225 || extra_by_number(extra) == presource) {
1226 bin |= (1 << i);
1227 }
1228 }
1229
1230 return hex_chars[bin];
1231}
1232
1233/************************************************************************/
1237static struct terrain *char2terrain(char ch)
1238{
1239 /* terrain_by_identifier plus fatal error */
1241 return T_UNKNOWN;
1242 }
1243 terrain_type_iterate(pterrain) {
1244 if (pterrain->identifier_load == ch) {
1245 return pterrain;
1246 }
1248
1249 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1250
1252
1253 RETURN_VALUE_AFTER_EXIT(nullptr);
1254}
1255
1256/************************************************************************/
1260static char terrain2char(const struct terrain *pterrain)
1261{
1262 if (pterrain == T_UNKNOWN) {
1264 } else {
1265 return pterrain->identifier;
1266 }
1267}
1268
1269/************************************************************************/
1273 const char *path, int plrno)
1274{
1275 char path_with_name[128];
1276 const char *name;
1277 struct advance *padvance;
1278
1280 "%s_name", path);
1281
1283
1284 if (!name || name[0] == '\0') {
1285 /* Used by researching_saved */
1286 return A_UNKNOWN;
1287 }
1288 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1289 return A_FUTURE;
1290 }
1291 if (fc_strcasecmp(name, "A_NONE") == 0) {
1292 return A_NONE;
1293 }
1294 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1295 return A_UNSET;
1296 }
1297
1300 "%s: unknown technology \"%s\".", path_with_name, name);
1301
1302 return advance_number(padvance);
1303}
1304
1305/************************************************************************/
1308static void technology_save(struct section_file *file,
1309 const char *path, int plrno, Tech_type_id tech)
1310{
1311 char path_with_name[128];
1312 const char *name;
1313
1315 "%s_name", path);
1316
1317 switch (tech) {
1318 case A_UNKNOWN: /* Used by researching_saved */
1319 name = "";
1320 break;
1321 case A_NONE:
1322 name = "A_NONE";
1323 break;
1324 case A_UNSET:
1325 name = "A_UNSET";
1326 break;
1327 case A_FUTURE:
1328 name = "A_FUTURE";
1329 break;
1330 default:
1332 break;
1333 }
1334
1336}
1337
1338/* =======================================================================
1339 * Load / save savefile data.
1340 * ======================================================================= */
1341
1342/************************************************************************/
1346{
1347 int i;
1348 const char *terr_name;
1349 bool ruleset_datafile;
1351 const char *str;
1352
1353 /* Check status and return if not OK (sg_success FALSE). */
1354 sg_check_ret();
1355
1356 /* Load savefile options. */
1357 loading->secfile_options
1358 = secfile_lookup_str(loading->file, "savefile.options");
1359
1360 /* We don't need these entries, but read them anyway to avoid
1361 * warnings about unread secfile entries. */
1362 secfile_entry_ignore_by_path(loading->file, "savefile.reason");
1363 secfile_entry_ignore_by_path(loading->file, "savefile.revision");
1364
1365 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1367
1368 if (game.scenario.datafile[0] != '\0') {
1370 } else {
1372 }
1373
1376 const char *req_caps;
1377
1378 if (!load_rulesets(nullptr, nullptr, FALSE, nullptr, TRUE, FALSE,
1380 /* Failed to load correct ruleset */
1381 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1383 }
1384
1385 req_caps = secfile_lookup_str_default(loading->file, "",
1386 "scenario.ruleset_caps");
1387 strncpy(game.scenario.req_caps, req_caps,
1388 sizeof(game.scenario.req_caps) - 1);
1389 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1390
1391 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1392 /* Current ruleset lacks required capabilities. */
1393 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1394 log_normal(_("Ruleset has capabilities: %s"),
1396 /* TRANS: ... ruleset dir ... scenario name ... */
1397 log_error(_("Current ruleset %s not compatible with the scenario %s."
1398 " Trying to switch to the ruleset specified by the"
1399 " scenario."),
1401
1403 }
1404 }
1405
1408 const char *ruleset, *alt_dir;
1409
1412 "savefile.rulesetdir");
1413
1414 /* Load ruleset. */
1416 if (!strcmp("default", game.server.rulesetdir)) {
1417 /* Here 'default' really means current default.
1418 * Saving happens with real ruleset name, so savegames containing this
1419 * are special scenarios. */
1421 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1423 }
1424
1425 alt_dir = secfile_lookup_str_default(loading->file, nullptr,
1426 "savefile.ruleset_alt_dir");
1427
1428 if (!load_rulesets(nullptr, alt_dir, FALSE, nullptr,
1430 if (alt_dir) {
1432 _("Failed to load either of rulesets '%s' or '%s' "
1433 "needed for savegame."),
1434 ruleset, alt_dir);
1435 } else {
1437 _("Failed to load ruleset '%s' needed for savegame."),
1438 ruleset);
1439 }
1440 }
1441
1443 /* TRANS: ruleset dir */
1444 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1445 }
1446 }
1447
1448 /* Remove all aifill players. Correct number of them get created later
1449 * with correct skill level etc. */
1450 (void) aifill(0);
1451
1452 /* Time to load scenario specific luadata */
1453 if (game.scenario.datafile[0] != '\0') {
1454 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1455 game.server.luadata = nullptr;
1456 } else {
1457 const struct strvec *paths[] = { get_scenario_dirs(), nullptr };
1458 const struct strvec **path;
1459 const char *found = nullptr;
1460 char testfile[MAX_LEN_PATH];
1461 struct section_file *secfile;
1462
1463 for (path = paths; found == nullptr && *path != nullptr; path++) {
1464 fc_snprintf(testfile, sizeof(testfile), "%s.luadata",
1466
1467 found = fileinfoname(*path, testfile);
1468 }
1469
1470 if (found == nullptr) {
1471 log_error(_("Can't find scenario luadata file %s.luadata."),
1473 sg_success = FALSE;
1474 return;
1475 }
1476
1477 secfile = secfile_load(found, FALSE);
1478 if (secfile == nullptr) {
1479 log_error(_("Failed to load scenario luadata file %s.luadata"),
1481 sg_success = FALSE;
1482 return;
1483 }
1484
1485 game.server.luadata = secfile;
1486 }
1487 }
1488
1490 "savefile.dbid");
1491
1492 /* This is in the savegame only if the game has been started before savegame3.c time,
1493 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1495 "savefile.last_updated_as_year");
1496
1497 /* Load improvements. */
1498 loading->improvement.size
1500 "savefile.improvement_size");
1501 if (loading->improvement.size) {
1502 loading->improvement.order
1503 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1504 "savefile.improvement_vector");
1505 sg_failure_ret(loading->improvement.size != 0,
1506 "Failed to load improvement order: %s",
1507 secfile_error());
1508 }
1509
1510 /* Load technologies. */
1511 loading->technology.size
1513 "savefile.technology_size");
1514 if (loading->technology.size) {
1515 loading->technology.order
1516 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1517 "savefile.technology_vector");
1518 sg_failure_ret(loading->technology.size != 0,
1519 "Failed to load technology order: %s",
1520 secfile_error());
1521 }
1522
1523 /* Load Activities. */
1524 loading->activities.size
1526 "savefile.activities_size");
1527 if (loading->activities.size) {
1528 loading->activities.order
1529 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1530 "savefile.activities_vector");
1531 sg_failure_ret(loading->activities.size != 0,
1532 "Failed to load activity order: %s",
1533 secfile_error());
1534 }
1535
1536 /* Load traits. */
1537 loading->trait.size
1539 "savefile.trait_size");
1540 if (loading->trait.size) {
1541 loading->trait.order
1542 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1543 "savefile.trait_vector");
1544 sg_failure_ret(loading->trait.size != 0,
1545 "Failed to load trait order: %s",
1546 secfile_error());
1547 }
1548
1549 /* Load extras. */
1550 loading->extra.size
1552 "savefile.extras_size");
1553 if (loading->extra.size) {
1554 const char **modname;
1555 size_t nmod;
1556 int j;
1557
1558 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1559 "savefile.extras_vector");
1560 sg_failure_ret(loading->extra.size != 0,
1561 "Failed to load extras order: %s",
1562 secfile_error());
1564 "Number of extras defined by the ruleset (= %d) are "
1565 "lower than the number in the savefile (= %d).",
1566 game.control.num_extra_types, (int)loading->extra.size);
1567 /* Make sure that the size of the array is divisible by 4 */
1568 nmod = 4 * ((loading->extra.size + 3) / 4);
1569 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1570 for (j = 0; j < loading->extra.size; j++) {
1571 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1572 }
1573 free(modname);
1574 for (; j < nmod; j++) {
1575 loading->extra.order[j] = nullptr;
1576 }
1577 }
1578
1579 /* Load multipliers. */
1580 loading->multiplier.size
1582 "savefile.multipliers_size");
1583 if (loading->multiplier.size) {
1584 const char **modname;
1585 int j;
1586
1587 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1588 "savefile.multipliers_vector");
1589 sg_failure_ret(loading->multiplier.size != 0,
1590 "Failed to load multipliers order: %s",
1591 secfile_error());
1592 /* It's OK for the set of multipliers in the savefile to differ
1593 * from those in the ruleset. */
1594 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1595 sizeof(*loading->multiplier.order));
1596 for (j = 0; j < loading->multiplier.size; j++) {
1597 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1598 if (!loading->multiplier.order[j]) {
1599 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1600 "discarding", modname[j]);
1601 }
1602 }
1603 free(modname);
1604 }
1605
1606 /* Load specialists. */
1607 loading->specialist.size
1609 "savefile.specialists_size");
1610 if (loading->specialist.size) {
1611 const char **modname;
1612 size_t nmod;
1613 int j;
1614
1615 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1616 "savefile.specialists_vector");
1617 sg_failure_ret(loading->specialist.size != 0,
1618 "Failed to load specialists order: %s",
1619 secfile_error());
1621 "Number of specialists defined by the ruleset (= %d) are "
1622 "lower than the number in the savefile (= %d).",
1623 game.control.num_specialist_types, (int)loading->specialist.size);
1624 /* Make sure that the size of the array is divisible by 4 */
1625 /* That's not really needed with specialists at the moment, but done this way
1626 * for consistency with other types, and to be prepared for the time it needs
1627 * to be this way. */
1628 nmod = 4 * ((loading->specialist.size + 3) / 4);
1629 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1630 for (j = 0; j < loading->specialist.size; j++) {
1631 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1632 }
1633 free(modname);
1634 for (; j < nmod; j++) {
1635 loading->specialist.order[j] = nullptr;
1636 }
1637 }
1638
1639 /* Load action order. */
1640 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1641 "savefile.action_size");
1642
1643 sg_failure_ret(loading->action.size > 0,
1644 "Failed to load action order: %s",
1645 secfile_error());
1646
1647 if (loading->action.size) {
1648 const char **modname;
1649 int j;
1650
1651 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1652 "savefile.action_vector");
1653
1654 loading->action.order = fc_calloc(loading->action.size,
1655 sizeof(*loading->action.order));
1656
1657 for (j = 0; j < loading->action.size; j++) {
1659
1660 if (real_action) {
1661 loading->action.order[j] = real_action->id;
1662 } else {
1663 log_sg("Unknown action \'%s\'", modname[j]);
1664 loading->action.order[j] = ACTION_NONE;
1665 }
1666 }
1667
1668 free(modname);
1669 }
1670
1671 /* Load action decision order. */
1672 loading->act_dec.size
1674 "savefile.action_decision_size");
1675
1676 sg_failure_ret(loading->act_dec.size > 0,
1677 "Failed to load action decision order: %s",
1678 secfile_error());
1679
1680 if (loading->act_dec.size) {
1681 const char **modname;
1682 int j;
1683
1684 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1685 "savefile.action_decision_vector");
1686
1687 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1688 sizeof(*loading->act_dec.order));
1689
1690 for (j = 0; j < loading->act_dec.size; j++) {
1691 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1693 }
1694
1695 free(modname);
1696 }
1697
1698 /* Load server side agent order. */
1699 loading->ssa.size
1701 "savefile.server_side_agent_size");
1702
1703 sg_failure_ret(loading->ssa.size > 0,
1704 "Failed to load server side agent order: %s",
1705 secfile_error());
1706
1707 if (loading->ssa.size) {
1708 const char **modname;
1709 int j;
1710
1711 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1712 "savefile.server_side_agent_list");
1713
1714 loading->ssa.order = fc_calloc(loading->ssa.size,
1715 sizeof(*loading->ssa.order));
1716
1717 for (j = 0; j < loading->ssa.size; j++) {
1718 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1720 }
1721
1722 free(modname);
1723 }
1724
1725 /* Load city options order. */
1726 loading->coptions.size
1728 "savefile.city_options_size");
1729
1730 sg_failure_ret(loading->coptions.size > 0,
1731 "Failed to load city options order: %s",
1732 secfile_error());
1733
1734 if (loading->coptions.size) {
1735 const char **modname;
1736 int j;
1737
1738 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1739 "savefile.city_options_vector");
1740
1741 loading->coptions.order = fc_calloc(loading->coptions.size,
1742 sizeof(*loading->coptions.order));
1743
1744 for (j = 0; j < loading->coptions.size; j++) {
1745 loading->coptions.order[j] = city_options_by_name(modname[j],
1747 }
1748
1749 free(modname);
1750 }
1751
1752 /* Terrain identifiers */
1754 pterr->identifier_load = '\0';
1756
1757 i = 0;
1758 while ((terr_name = secfile_lookup_str_default(loading->file, nullptr,
1759 "savefile.terrident%d.name", i))
1760 != nullptr) {
1762
1763 if (pterr != nullptr) {
1764 const char *iptr
1765 = secfile_lookup_str_default(loading->file, nullptr,
1766 "savefile.terrident%d.identifier", i);
1767
1768 pterr->identifier_load = *iptr;
1769 } else {
1770 log_error("Identifier for unknown terrain type %s.", terr_name);
1771 }
1772 i++;
1773 }
1774
1777 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1778 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1779 "%s and %s share a saved identifier",
1781 }
1784}
1785
1786/************************************************************************/
1790{
1791 int i;
1792
1793 /* Check status and return if not OK (sg_success FALSE). */
1794 sg_check_ret();
1795
1796 /* Save savefile options. */
1798
1799 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1800
1801 /* Save reason of the savefile generation. */
1802 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1803
1804 /* Save as accurate freeciv revision information as possible */
1805 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1806
1807 /* Freeciv version used in the very first launch of this game -
1808 * or even saving in pregame. */
1810 "savefile.orig_version");
1811
1812 /* Save rulesetdir at this point as this ruleset is required by this
1813 * savefile. */
1814 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1815
1816 if (game.control.version[0] != '\0') {
1817 /* Current ruleset has version information, save it.
1818 * This is never loaded, but exist in savegame file only for debugging purposes. */
1819 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1820 }
1821
1822 if (game.control.alt_dir[0] != '\0') {
1823 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1824 }
1825
1827 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1828 }
1829
1830 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1831
1832 /* Save improvement order in savegame, so we are not dependent on ruleset
1833 * order. If the game isn't started improvements aren't loaded so we can
1834 * not save the order. */
1836 "savefile.improvement_size");
1837 if (improvement_count() > 0) {
1838 const char *buf[improvement_count()];
1839
1840 improvement_iterate(pimprove) {
1841 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1843
1845 "savefile.improvement_vector");
1846 }
1847
1848 /* Save technology order in savegame, so we are not dependent on ruleset
1849 * order. If the game isn't started advances aren't loaded so we can not
1850 * save the order. */
1852 "savefile.technology_size");
1853 if (game.control.num_tech_types > 0) {
1854 const char *buf[game.control.num_tech_types];
1855
1856 buf[A_NONE] = "A_NONE";
1857 advance_iterate(a) {
1861 "savefile.technology_vector");
1862 }
1863
1864 /* Save activities order in the savegame. */
1866 "savefile.activities_size");
1867 if (ACTIVITY_LAST > 0) {
1868 const char **modname;
1869 int j;
1870
1871 i = 0;
1872
1874
1875 for (j = 0; j < ACTIVITY_LAST; j++) {
1877 }
1878
1881 "savefile.activities_vector");
1882 free(modname);
1883 }
1884
1885 /* Save specialists order in the savegame. */
1887 "savefile.specialists_size");
1888 {
1889 const char **modname;
1890
1891 i = 0;
1893
1897
1899 "savefile.specialists_vector");
1900
1901 free(modname);
1902 }
1903
1904 /* Save trait order in savegame. */
1906 "savefile.trait_size");
1907 {
1908 const char **modname;
1909 enum trait tr;
1910 int j;
1911
1912 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1913
1914 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1915 modname[j] = trait_name(tr);
1916 }
1917
1919 "savefile.trait_vector");
1920 free(modname);
1921 }
1922
1923 /* Save extras order in the savegame. */
1925 "savefile.extras_size");
1926 if (game.control.num_extra_types > 0) {
1927 const char **modname;
1928
1929 i = 0;
1931
1932 extra_type_iterate(pextra) {
1933 modname[i++] = extra_rule_name(pextra);
1935
1938 "savefile.extras_vector");
1939 free(modname);
1940 }
1941
1942 /* Save multipliers order in the savegame. */
1944 "savefile.multipliers_size");
1945 if (multiplier_count() > 0) {
1946 const char **modname;
1947
1949
1950 multipliers_iterate(pmul) {
1953
1956 "savefile.multipliers_vector");
1957 free(modname);
1958 }
1959
1960 /* Save city_option order in the savegame. */
1962 "savefile.city_options_size");
1963 if (CITYO_LAST > 0) {
1964 const char **modname;
1965 int j;
1966
1967 i = 0;
1968 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1969
1970 for (j = 0; j < CITYO_LAST; j++) {
1971 modname[i++] = city_options_name(j);
1972 }
1973
1975 CITYO_LAST,
1976 "savefile.city_options_vector");
1977 free(modname);
1978 }
1979
1980 /* Save action order in the savegame. */
1982 "savefile.action_size");
1983 if (NUM_ACTIONS > 0) {
1984 const char **modname;
1985 int j;
1986
1987 i = 0;
1988 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1989
1990 for (j = 0; j < NUM_ACTIONS; j++) {
1992 }
1993
1996 "savefile.action_vector");
1997 free(modname);
1998 }
1999
2000 /* Save action decision order in the savegame. */
2002 "savefile.action_decision_size");
2003 if (ACT_DEC_COUNT > 0) {
2004 const char **modname;
2005 int j;
2006
2007 i = 0;
2009
2010 for (j = 0; j < ACT_DEC_COUNT; j++) {
2012 }
2013
2016 "savefile.action_decision_vector");
2017 free(modname);
2018 }
2019
2020 /* Save server side agent order in the savegame. */
2022 "savefile.server_side_agent_size");
2023 if (SSA_COUNT > 0) {
2024 const char **modname;
2025 int j;
2026
2027 i = 0;
2028 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2029
2030 for (j = 0; j < SSA_COUNT; j++) {
2032 }
2033
2035 SSA_COUNT,
2036 "savefile.server_side_agent_list");
2037 free(modname);
2038 }
2039
2040 /* Save terrain character mapping in the savegame. */
2041 i = 0;
2043 char buf[2];
2044
2045 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2047 buf[1] = '\0';
2048 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2050}
2051
2052/************************************************************************/
2056 const char *option)
2057{
2058 /* Check status and return if not OK (sg_success FALSE). */
2059 sg_check_ret();
2060
2061 if (option == nullptr) {
2062 /* No additional option */
2063 return;
2064 }
2065
2066 sz_strlcat(saving->secfile_options, option);
2067 secfile_replace_str(saving->file, saving->secfile_options,
2068 "savefile.options");
2069}
2070
2071/* =======================================================================
2072 * Load / save game status.
2073 * ======================================================================= */
2074
2075/************************************************************************/
2079{
2080 int i;
2081 const char *name;
2082
2083 /* Check status and return if not OK (sg_success FALSE). */
2084 sg_check_ret();
2085
2086 for (i = 0;
2087 (name = secfile_lookup_str_default(loading->file, nullptr,
2088 "ruledata.government%d.name", i));
2089 i++) {
2091
2092 if (gov != nullptr) {
2093 gov->changed_to_times
2095 "ruledata.government%d.changes", i);
2096 }
2097 }
2098}
2099
2100/************************************************************************/
2103static void sg_load_game(struct loaddata *loading)
2104{
2105 const char *str;
2106 int i;
2107
2108 /* Check status and return if not OK (sg_success FALSE). */
2109 sg_check_ret();
2110
2111 /* Load server state. */
2112 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2113 "game.server_state");
2114 loading->server_state = server_states_by_name(str, strcmp);
2115 if (!server_states_is_valid(loading->server_state)) {
2116 /* Don't take any risk! */
2117 loading->server_state = S_S_INITIAL;
2118 }
2119
2121 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2122
2125 "game.meta_patches");
2127
2129 /* Do not overwrite this if the user requested a specific metaserver
2130 * from the command line (option --Metaserver). */
2134 "game.meta_server"));
2135 }
2136
2137 if ('\0' == srvarg.serverid[0]) {
2138 /* Do not overwrite this if the user requested a specific metaserver
2139 * from the command line (option --serverid). */
2142 "game.serverid"));
2143 }
2144 sz_strlcpy(server.game_identifier,
2145 secfile_lookup_str_default(loading->file, "", "game.id"));
2146 /* We are not checking game_identifier legality just yet.
2147 * That's done when we are sure that rand seed has been initialized,
2148 * so that we can generate new game_identifier, if needed.
2149 * See sq_load_sanitycheck(). */
2150
2151 str = secfile_lookup_str_default(loading->file, nullptr,
2152 "game.phase_mode");
2153 if (str != nullptr) {
2156 log_error("Illegal phase mode \"%s\"", str);
2158 }
2159 } else {
2160 log_error("Phase mode missing");
2161 }
2162
2163 str = secfile_lookup_str_default(loading->file, nullptr,
2164 "game.phase_mode_stored");
2165 if (str != nullptr) {
2168 log_error("Illegal stored phase mode \"%s\"", str);
2170 }
2171 } else {
2172 log_error("Stored phase mode missing");
2173 }
2176 "game.phase");
2180 "game.scoreturn");
2181
2184 "game.timeoutint");
2187 "game.timeoutintinc");
2190 "game.timeoutinc");
2193 "game.timeoutincmult");
2196 "game.timeoutcounter");
2197
2198 game.info.turn
2199 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2201 "game.year"), "%s", secfile_error());
2203 "game.world_peace_start"), "%s", secfile_error());
2205 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2206
2208 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2210 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2212 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2213
2215 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2217 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2219 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2220
2221 /* Savegame may have stored random_seed for documentation purposes only,
2222 * but we want to keep it for resaving. */
2223 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2224
2225 /* Global advances. */
2226 str = secfile_lookup_str_default(loading->file, nullptr,
2227 "game.global_advances");
2228 if (str != nullptr) {
2229 sg_failure_ret(strlen(str) == loading->technology.size,
2230 "Invalid length of 'game.global_advances' ("
2231 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2232 strlen(str), loading->technology.size);
2233 for (i = 0; i < loading->technology.size; i++) {
2234 sg_failure_ret(str[i] == '1' || str[i] == '0',
2235 "Undefined value '%c' within 'game.global_advances'.",
2236 str[i]);
2237 if (str[i] == '1') {
2238 struct advance *padvance
2239 = advance_by_rule_name(loading->technology.order[i]);
2240
2241 if (padvance != nullptr) {
2243 }
2244 }
2245 }
2246 }
2247
2249 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2250
2252 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2253}
2254
2255/************************************************************************/
2259{
2260 int set_count = 0;
2261
2263 char path[256];
2264
2265 fc_snprintf(path, sizeof(path),
2266 "ruledata.government%d", set_count++);
2267
2269 "%s.name", path);
2270 secfile_insert_int(saving->file, pgov->changed_to_times,
2271 "%s.changes", path);
2273}
2274
2275/************************************************************************/
2278static void sg_save_game(struct savedata *saving)
2279{
2281 char global_advances[game.control.num_tech_types + 1];
2282 int i;
2283
2284 /* Check status and return if not OK (sg_success FALSE). */
2285 sg_check_ret();
2286
2287 /* Game state: once the game is no longer a new game (ie, has been
2288 * started the first time), it should always be considered a running
2289 * game for savegame purposes. */
2290 if (saving->scenario && !game.scenario.players) {
2292 } else {
2294 }
2296 "game.server_state");
2297
2298 if (game.server.phase_timer != nullptr) {
2302 "game.phase_seconds");
2303 }
2304
2306 "game.meta_patches");
2307 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2308
2309 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2310 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2311
2314 "game.phase_mode");
2317 "game.phase_mode_stored");
2319 "game.phase");
2321 "game.scoreturn");
2322
2324 "game.timeoutint");
2326 "game.timeoutintinc");
2328 "game.timeoutinc");
2330 "game.timeoutincmult");
2332 "game.timeoutcounter");
2333
2334 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2335 secfile_insert_int(saving->file, game.info.year, "game.year");
2336 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2338 "game.year_0_hack");
2339
2341 "game.globalwarming");
2343 "game.heating");
2345 "game.warminglevel");
2346
2348 "game.nuclearwinter");
2350 "game.cooling");
2352 "game.coolinglevel");
2353 /* For debugging purposes only.
2354 * Do not save it if it's 0 (not known);
2355 * this confuses people reading this 'document' less than
2356 * saving 0. */
2357 if (game.server.seed != 0) {
2359 "game.random_seed");
2360 }
2361
2362 /* Global advances. */
2363 for (i = 0; i < game.control.num_tech_types; i++) {
2364 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2365 }
2366 global_advances[i] = '\0';
2367 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2368
2369 if (!game_was_started()) {
2370 saving->save_players = FALSE;
2371 } else {
2372 if (saving->scenario) {
2373 saving->save_players = game.scenario.players;
2374 } else {
2375 saving->save_players = TRUE;
2376 }
2377#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2379 "game.last_turn_change_time");
2380#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2382 "game.last_turn_change_time");
2383#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2384 }
2385 secfile_insert_bool(saving->file, saving->save_players,
2386 "game.save_players");
2387
2388 if (srv_state != S_S_INITIAL) {
2389 const char *ainames[ai_type_get_count()];
2390
2391 i = 0;
2392 ai_type_iterate(ait) {
2393 ainames[i] = ait->name;
2394 i++;
2396
2398 "game.ai_types");
2399 }
2400}
2401
2402/* =======================================================================
2403 * Load / save random status.
2404 * ======================================================================= */
2405
2406/************************************************************************/
2409static void sg_load_random(struct loaddata *loading)
2410{
2411 /* Check status and return if not OK (sg_success FALSE). */
2412 sg_check_ret();
2413
2414 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2415 const char *str;
2416 int i;
2417
2419 "random.index_J"), "%s", secfile_error());
2421 "random.index_K"), "%s", secfile_error());
2423 "random.index_X"), "%s", secfile_error());
2424
2425 for (i = 0; i < 8; i++) {
2426 str = secfile_lookup_str(loading->file, "random.table%d",i);
2427 sg_failure_ret(str != nullptr, "%s", secfile_error());
2428 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2429 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2430 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2431 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2432 }
2433 loading->rstate.is_init = TRUE;
2434 fc_rand_set_state(loading->rstate);
2435 } else {
2436 /* No random values - mark the setting. */
2437 secfile_entry_ignore_by_path(loading->file, "random.saved");
2438
2439 /* We're loading a game without a seed (which is okay, if it's a scenario).
2440 * We need to generate the game seed now because it will be needed later
2441 * during the load. */
2443 loading->rstate = fc_rand_state();
2444 }
2445}
2446
2447/************************************************************************/
2450static void sg_save_random(struct savedata *saving)
2451{
2452 /* Check status and return if not OK (sg_success FALSE). */
2453 sg_check_ret();
2454
2455 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2456 int i;
2457 RANDOM_STATE rstate = fc_rand_state();
2458
2459 secfile_insert_bool(saving->file, TRUE, "random.saved");
2460 fc_assert(rstate.is_init);
2461
2462 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2463 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2464 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2465
2466 for (i = 0; i < 8; i++) {
2467 char vec[100];
2468
2469 fc_snprintf(vec, sizeof(vec),
2470 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2471 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2472 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2473 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2474 secfile_insert_str(saving->file, vec, "random.table%d", i);
2475 }
2476 } else {
2477 secfile_insert_bool(saving->file, FALSE, "random.saved");
2478 }
2479}
2480
2481/* =======================================================================
2482 * Load / save lua script data.
2483 * ======================================================================= */
2484
2485/************************************************************************/
2488static void sg_load_script(struct loaddata *loading)
2489{
2490 /* Check status and return if not OK (sg_success FALSE). */
2491 sg_check_ret();
2492
2494}
2495
2496/************************************************************************/
2499static void sg_save_script(struct savedata *saving)
2500{
2501 /* Check status and return if not OK (sg_success FALSE). */
2502 sg_check_ret();
2503
2505}
2506
2507/* =======================================================================
2508 * Load / save scenario data.
2509 * ======================================================================= */
2510
2511/************************************************************************/
2515{
2516 const char *buf;
2517 int game_version;
2518
2519 /* Check status and return if not OK (sg_success FALSE). */
2520 sg_check_ret();
2521
2522 /* Load version. */
2524 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2525 /* We require at least version 2.90.99 - and at that time we saved version
2526 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2527 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2528 "version 2.90.99 required.");
2529
2530 loading->full_version = game_version;
2531
2532 game.scenario.datafile[0] = '\0';
2533
2535 "scenario.is_scenario"), "%s", secfile_error());
2536 if (!game.scenario.is_scenario) {
2537 return;
2538 }
2539
2540 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2541 if (buf[0] != '\0') {
2543 }
2544
2546 "scenario.authors");
2547 if (buf[0] != '\0') {
2549 } else {
2550 game.scenario.authors[0] = '\0';
2551 }
2552
2554 "scenario.description");
2555 if (buf[0] != '\0') {
2557 } else {
2558 game.scenario_desc.description[0] = '\0';
2559 }
2561 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2563 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2566 "scenario.startpos_nations");
2569 "scenario.prevent_new_cities");
2572 "scenario.lake_flooding");
2575 "scenario.handmade");
2578 "scenario.allow_ai_type_fallback");
2579
2582 "scenario.ruleset_locked");
2583
2585 "scenario.datafile");
2586 if (buf[0] != '\0') {
2588 }
2589
2590 sg_failure_ret(loading->server_state == S_S_INITIAL
2591 || (loading->server_state == S_S_RUNNING
2592 && game.scenario.players),
2593 "Invalid scenario definition (server state '%s' and "
2594 "players are %s).",
2595 server_states_name(loading->server_state),
2596 game.scenario.players ? "saved" : "not saved");
2597}
2598
2599/************************************************************************/
2603{
2604 struct entry *mod_entry;
2605 int game_version;
2606
2607 /* Check status and return if not OK (sg_success FALSE). */
2608 sg_check_ret();
2609
2610 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2611#ifdef EMERGENCY_VERSION
2613#endif /* EMERGENCY_VERSION */
2614 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2615
2616 if (!saving->scenario || !game.scenario.is_scenario) {
2617 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2618 return;
2619 }
2620
2621 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2622
2623 /* Name is mandatory to the level that is saved even if empty. */
2624 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2626
2627 /* Authors list is saved only if it exist */
2628 if (game.scenario.authors[0] != '\0') {
2630 "scenario.authors");
2632 }
2633
2634 /* Description is saved only if it exist */
2635 if (game.scenario_desc.description[0] != '\0') {
2637 "scenario.description");
2639 }
2640
2641 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2642 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2644 "scenario.startpos_nations");
2647 "scenario.prevent_new_cities");
2648 }
2650 "scenario.lake_flooding");
2651 if (game.scenario.handmade) {
2653 "scenario.handmade");
2654 }
2657 "scenario.allow_ai_type_fallback");
2658 }
2659
2660 if (game.scenario.datafile[0] != '\0') {
2662 "scenario.datafile");
2663 }
2665 "scenario.ruleset_locked");
2666 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2668 "scenario.ruleset_caps");
2669 }
2670}
2671
2672/* =======================================================================
2673 * Load / save game settings.
2674 * ======================================================================= */
2675
2676/************************************************************************/
2680{
2681 /* Check status and return if not OK (sg_success FALSE). */
2682 sg_check_ret();
2683
2684 settings_game_load(loading->file, "settings");
2685
2686 /* Save current status of fogofwar. */
2688
2689 /* Add all compatibility settings here. */
2690}
2691
2692/************************************************************************/
2696{
2698
2699 /* Check status and return if not OK (sg_success FALSE). */
2700 sg_check_ret();
2701
2702 if (saving->scenario) {
2703 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2704 }
2705
2706 settings_game_save(saving->file, "settings");
2707 /* Restore real map generator. */
2709
2710 /* Add all compatibility settings here. */
2711}
2712
2713
2714/************************************************************************/
2718{
2719 struct city *pcity;
2720 int i, j;
2721 size_t length, length2;
2722 int *city_count;
2724 "savefile.city_counters_order_size");
2725
2726 if (0==length) {
2727
2728 return;
2729 }
2730
2731 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2732
2733 sg_failure_ret(loading->counter.order != 0,
2734 "Failed to load counter's ruleset order: %s",
2735 secfile_error());
2736 sg_failure_ret(loading->counter.size = length,
2737 "Counter vector in savegame have bad size: %s",
2738 secfile_error());
2739
2740 int corder[length];
2741
2742 for (i = 0; i < length; i++) {
2743
2744 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2746 }
2747
2748 i = 0;
2749 while ((city_count =
2751 "counters.c%d", i)) != nullptr) {
2752
2753 sg_failure_ret((length2 - 1 == (size_t) length),
2754 ( "Bad city counters vector size. Should be " SIZE_T_PRINTF ". Is " SIZE_T_PRINTF "." ),
2755 length, length2 - 1);
2756
2758
2759 sg_failure_ret(pcity != nullptr,
2760 "City with id %d not found. Is savegame malformed? Abort loading.",
2761 city_count[0]);
2762
2763 for (j = 0; j < length; j++) {
2764
2765 pcity->counter_values[corder[j]] = city_count[j+1];
2766 }
2767 i++;
2768 }
2769}
2770
2771/************************************************************************/
2775{
2776 /* Check status and return if not OK (sg_success FALSE). */
2777 sg_check_ret();
2778
2779 const char **countnames;
2780 int *countvalues;
2781 int i, j, count;
2782
2784
2785 secfile_insert_int(saving->file, count,
2786 "savefile.city_counters_order_size");
2787
2788 if (0 == count) {
2789
2790 return;
2791 }
2792
2793 countnames = fc_calloc(count, sizeof(*countnames));
2794 for (j = 0; j < count; j++) {
2796 }
2797
2799 "savefile.city_counters_order_vector");
2800
2802
2803 // Saving city's counters
2804
2805 j = 0;
2806 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2807
2809
2810 city_list_iterate(_pplayer->cities, pcity) {
2811
2812 countvalues[0] = pcity->id;
2813 for (i = 0; i < count; ++i) {
2814
2815 countvalues[i+1] = pcity->counter_values[i];
2816 }
2817
2818 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2819 ++j;
2822
2824}
2825
2826/* =======================================================================
2827 * Load / save the main map.
2828 * ======================================================================= */
2829
2830/************************************************************************/
2833static void sg_load_map(struct loaddata *loading)
2834{
2835 /* Check status and return if not OK (sg_success FALSE). */
2836 sg_check_ret();
2837
2838 /* This defaults to TRUE even if map has not been generated.
2839 * We rely on that
2840 * 1) scenario maps have it explicitly right.
2841 * 2) when map is actually generated, it re-initialize this to FALSE. */
2843 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2844
2846 = secfile_lookup_bool_default(loading->file, TRUE, "map.altitude");
2847
2849 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2850
2852
2853 /* Savegame may have stored random_seed for documentation purposes only,
2854 * but we want to keep it for resaving. */
2856 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2857
2858 if (S_S_INITIAL == loading->server_state
2860 /* Generator MAPGEN_SCENARIO is used;
2861 * this map was done with the map editor. */
2862
2863 /* Load tiles. */
2867
2868 /* Nothing more needed for a scenario. */
2869 secfile_entry_ignore(loading->file, "game.save_known");
2870
2871 return;
2872 }
2873
2874 if (S_S_INITIAL == loading->server_state) {
2875 /* Nothing more to do if it is not a scenario but in initial state. */
2876 return;
2877 }
2878
2880 if (wld.map.altitude_info) {
2882 }
2888}
2889
2890/************************************************************************/
2893static void sg_save_map(struct savedata *saving)
2894{
2895 /* Check status and return if not OK (sg_success FALSE). */
2896 sg_check_ret();
2897
2898 if (map_is_empty()) {
2899 /* No map. */
2900 return;
2901 }
2902
2903 if (saving->scenario) {
2905 "map.have_huts");
2907 "map.have_resources");
2908 } else {
2909 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2910 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2911 }
2912
2913 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2914
2915 /* For debugging purposes only.
2916 * Do not save it if it's 0 (not known);
2917 * this confuses people reading this 'document' less than
2918 * saving 0. */
2919 if (wld.map.server.seed != 0) {
2921 "map.random_seed");
2922 }
2923
2925 if (wld.map.altitude_info) {
2927 }
2933}
2934
2935/************************************************************************/
2939{
2940 /* Check status and return if not OK (sg_success FALSE). */
2941 sg_check_ret();
2942
2943 /* Initialize the map for the current topology. 'map.xsize' and
2944 * 'map.ysize' must be set. */
2946
2947 /* Allocate map. */
2949
2950 /* get the terrain type */
2951 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2952 "map.t%04d");
2954
2955 /* Check for special tile sprites. */
2956 whole_map_iterate(&(wld.map), ptile) {
2957 const char *spec_sprite;
2958 const char *label;
2959 int nat_x, nat_y;
2960
2962 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2963 nat_x, nat_y);
2964 label = secfile_lookup_str_default(loading->file, nullptr,
2965 "map.label_%d_%d",
2966 nat_x, nat_y);
2967 if (ptile->spec_sprite != nullptr) {
2968 ptile->spec_sprite = fc_strdup(spec_sprite);
2969 }
2970 if (label != nullptr) {
2971 tile_set_label(ptile, label);
2972 }
2974}
2975
2976/************************************************************************/
2980{
2981 /* Check status and return if not OK (sg_success FALSE). */
2982 sg_check_ret();
2983
2984 /* Save the terrain type. */
2985 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2986 "map.t%04d");
2987
2988 /* Save special tile sprites. */
2989 whole_map_iterate(&(wld.map), ptile) {
2990 int nat_x, nat_y;
2991
2993 if (ptile->spec_sprite) {
2994 secfile_insert_str(saving->file, ptile->spec_sprite,
2995 "map.spec_sprite_%d_%d", nat_x, nat_y);
2996 }
2997 if (ptile->label != nullptr) {
2998 secfile_insert_str(saving->file, ptile->label,
2999 "map.label_%d_%d", nat_x, nat_y);
3000 }
3002}
3003
3004/************************************************************************/
3008{
3009 int y;
3010
3011 /* Check status and return if not OK (sg_success FALSE). */
3012 sg_check_ret();
3013
3014 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3015 const char *buffer = secfile_lookup_str(loading->file,
3016 "map.alt%04d", y);
3017 const char *ptr = buffer;
3018 int x;
3019
3020 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3021
3022 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3023 char token[TOKEN_SIZE];
3024 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3025 int number;
3026
3027 scanin(&ptr, ",", token, sizeof(token));
3028 sg_failure_ret(token[0] != '\0',
3029 "Map size not correct (map.alt%d).", y);
3030 sg_failure_ret(str_to_int(token, &number),
3031 "Got map alt %s in (%d, %d).", token, x, y);
3032 ptile->altitude = number;
3033 }
3034 }
3035}
3036
3037/************************************************************************/
3041{
3042 int y;
3043
3044 /* Check status and return if not OK (sg_success FALSE). */
3045 sg_check_ret();
3046
3047 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3049 int x;
3050
3051 line[0] = '\0';
3052 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3053 char token[TOKEN_SIZE];
3054 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3055
3056 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3057
3058 strcat(line, token);
3059 if (x + 1 < MAP_NATIVE_WIDTH) {
3060 strcat(line, ",");
3061 }
3062 }
3063
3064 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3065 }
3066}
3067
3068/************************************************************************/
3072{
3073 /* Check status and return if not OK (sg_success FALSE). */
3074 sg_check_ret();
3075
3076 /* Load extras. */
3077 halfbyte_iterate_extras(j, loading->extra.size) {
3078 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3079 loading->extra.order + 4 * j),
3080 loading->file, "map.e%02d_%04d", j);
3082
3083 if (S_S_INITIAL != loading->server_state
3086 whole_map_iterate(&(wld.map), ptile) {
3088 if (tile_has_extra(ptile, pres)) {
3089 tile_set_resource(ptile, pres);
3090
3091 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3092 BV_CLR(ptile->extras, extra_index(pres));
3093 }
3094 }
3097 }
3098}
3099
3100/************************************************************************/
3104{
3105 /* Check status and return if not OK (sg_success FALSE). */
3106 sg_check_ret();
3107
3108 /* Save extras. */
3110 int mod[4];
3111 int l;
3112
3113 for (l = 0; l < 4; l++) {
3114 if (4 * j + 1 > game.control.num_extra_types) {
3115 mod[l] = -1;
3116 } else {
3117 mod[l] = 4 * j + l;
3118 }
3119 }
3120 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3121 saving->file, "map.e%02d_%04d", j);
3123}
3124
3125/************************************************************************/
3130{
3131 struct nation_type *pnation;
3132 struct startpos *psp;
3133 struct tile *ptile;
3134 const char SEPARATOR = '#';
3135 const char *nation_names;
3136 int nat_x, nat_y;
3137 bool exclude;
3138 int i, startpos_count;
3139
3140 /* Check status and return if not OK (sg_success FALSE). */
3141 sg_check_ret();
3142
3144 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3145
3146 if (0 == startpos_count) {
3147 /* Nothing to do. */
3148 return;
3149 }
3150
3151 for (i = 0; i < startpos_count; i++) {
3152 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3153 || !secfile_lookup_int(loading->file, &nat_y,
3154 "map.startpos%d.y", i)) {
3155 log_sg("Warning: Undefined coordinates for startpos %d", i);
3156 continue;
3157 }
3158
3159 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3160 if (ptile == nullptr) {
3161 log_error("Start position native coordinates (%d, %d) do not exist "
3162 "in this map. Skipping...", nat_x, nat_y);
3163 continue;
3164 }
3165
3166 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3167 "map.startpos%d.exclude", i);
3168
3169 psp = map_startpos_new(ptile);
3170
3172 "map.startpos%d.nations", i);
3173 if (nation_names != nullptr && '\0' != nation_names[0]) {
3174 const size_t size = strlen(nation_names) + 1;
3175 char buf[size], *start, *end;
3176
3178 for (start = buf - 1; start != nullptr; start = end) {
3179 start++;
3180 if ((end = strchr(start, SEPARATOR))) {
3181 *end = '\0';
3182 }
3183
3184 pnation = nation_by_rule_name(start);
3185 if (NO_NATION_SELECTED != pnation) {
3186 if (exclude) {
3187 startpos_disallow(psp, pnation);
3188 } else {
3189 startpos_allow(psp, pnation);
3190 }
3191 } else {
3192 log_verbose("Missing nation \"%s\".", start);
3193 }
3194 }
3195 }
3196 }
3197
3198 if (0 < map_startpos_count()
3199 && loading->server_state == S_S_INITIAL
3201 log_verbose("Number of starts (%d) are lower than rules.max_players "
3202 "(%d), lowering rules.max_players.",
3205 }
3206
3207 /* Re-initialize nation availability in light of start positions.
3208 * This has to be after loading [scenario] and [map].startpos and
3209 * before we seek nations for players. */
3211}
3212
3213/************************************************************************/
3217{
3218 struct tile *ptile;
3219 const char SEPARATOR = '#';
3220 int i = 0;
3221
3222 /* Check status and return if not OK (sg_success FALSE). */
3223 sg_check_ret();
3224
3226 return;
3227 }
3228
3230 "map.startpos_count");
3231
3233 int nat_x, nat_y;
3234
3235 ptile = startpos_tile(psp);
3236
3238 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3239 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3240
3242 "map.startpos%d.exclude", i);
3243 if (startpos_allows_all(psp)) {
3244 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3245 } else {
3246 const struct nation_hash *nations = startpos_raw_nations(psp);
3248
3249 nation_names[0] = '\0';
3250 nation_hash_iterate(nations, pnation) {
3251 if ('\0' == nation_names[0]) {
3253 sizeof(nation_names));
3254 } else {
3256 "%c%s", SEPARATOR, nation_rule_name(pnation));
3257 }
3260 "map.startpos%d.nations", i);
3261 }
3262 i++;
3264
3266}
3267
3268/************************************************************************/
3272{
3273 int y;
3274 struct tile *claimer = nullptr;
3275 struct extra_type *placing = nullptr;
3276
3277 /* Check status and return if not OK (sg_success FALSE). */
3278 sg_check_ret();
3279
3280 if (game.info.is_new_game) {
3281 /* No owner/source information for a new game / scenario. */
3282 return;
3283 }
3284
3285 /* Owner, ownership source, and infra turns are stored as plain numbers */
3286 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3287 const char *buffer1 = secfile_lookup_str(loading->file,
3288 "map.owner%04d", y);
3289 const char *buffer2 = secfile_lookup_str(loading->file,
3290 "map.source%04d", y);
3291 const char *buffer3 = secfile_lookup_str(loading->file,
3292 "map.eowner%04d", y);
3293 const char *buffer_placing
3294 = secfile_lookup_str_default(loading->file, nullptr,
3295 "map.placing%04d", y);
3296 const char *buffer_turns
3297 = secfile_lookup_str_default(loading->file, nullptr,
3298 "map.infra_turns%04d", y);
3299 const char *ptr1 = buffer1;
3300 const char *ptr2 = buffer2;
3301 const char *ptr3 = buffer3;
3302 const char *ptr_placing = buffer_placing;
3303 const char *ptr_turns = buffer_turns;
3304 int x;
3305
3306 sg_failure_ret(buffer1 != nullptr, "%s", secfile_error());
3307 sg_failure_ret(buffer2 != nullptr, "%s", secfile_error());
3308 sg_failure_ret(buffer3 != nullptr, "%s", secfile_error());
3309
3310 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3311 char token1[TOKEN_SIZE];
3312 char token2[TOKEN_SIZE];
3313 char token3[TOKEN_SIZE];
3315 char token_turns[TOKEN_SIZE];
3316 struct player *owner = nullptr;
3317 struct player *eowner = nullptr;
3318 int turns;
3319 int number;
3320 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3321
3322 scanin(&ptr1, ",", token1, sizeof(token1));
3323 sg_failure_ret(token1[0] != '\0',
3324 "Map size not correct (map.owner%d).", y);
3325 if (strcmp(token1, "-") == 0) {
3326 owner = nullptr;
3327 } else {
3329 "Got map owner %s in (%d, %d).", token1, x, y);
3330 owner = player_by_number(number);
3331 }
3332
3333 scanin(&ptr2, ",", token2, sizeof(token2));
3334 sg_failure_ret(token2[0] != '\0',
3335 "Map size not correct (map.source%d).", y);
3336 if (strcmp(token2, "-") == 0) {
3337 claimer = nullptr;
3338 } else {
3340 "Got map source %s in (%d, %d).", token2, x, y);
3341 claimer = index_to_tile(&(wld.map), number);
3342 }
3343
3344 scanin(&ptr3, ",", token3, sizeof(token3));
3345 sg_failure_ret(token3[0] != '\0',
3346 "Map size not correct (map.eowner%d).", y);
3347 if (strcmp(token3, "-") == 0) {
3348 eowner = nullptr;
3349 } else {
3351 "Got base owner %s in (%d, %d).", token3, x, y);
3352 eowner = player_by_number(number);
3353 }
3354
3355 if (ptr_placing != nullptr) {
3357 sg_failure_ret(token_placing[0] != '\0',
3358 "Map size not correct (map.placing%d).", y);
3359 if (strcmp(token_placing, "-") == 0) {
3360 placing = nullptr;
3361 } else {
3363 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3364 placing = extra_by_number(number);
3365 }
3366 } else {
3367 placing = nullptr;
3368 }
3369
3370 if (ptr_turns != nullptr) {
3371 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3372 sg_failure_ret(token_turns[0] != '\0',
3373 "Map size not correct (map.infra_turns%d).", y);
3375 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3376 turns = number;
3377 } else {
3378 turns = 1;
3379 }
3380
3382 tile_claim_bases(ptile, eowner);
3383 ptile->placing = placing;
3384 ptile->infra_turns = turns;
3385 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3386 }
3387 }
3388}
3389
3390/************************************************************************/
3394{
3395 int y;
3396
3397 /* Check status and return if not OK (sg_success FALSE). */
3398 sg_check_ret();
3399
3400 if (saving->scenario && !saving->save_players) {
3401 /* Nothing to do for a scenario without saved players. */
3402 return;
3403 }
3404
3405 /* Store owner and ownership source as plain numbers. */
3406 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3408 int x;
3409
3410 line[0] = '\0';
3411 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3412 char token[TOKEN_SIZE];
3413 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3414
3415 if (!saving->save_players || tile_owner(ptile) == nullptr) {
3416 strcpy(token, "-");
3417 } else {
3418 fc_snprintf(token, sizeof(token), "%d",
3419 player_number(tile_owner(ptile)));
3420 }
3421 strcat(line, token);
3422 if (x + 1 < MAP_NATIVE_WIDTH) {
3423 strcat(line, ",");
3424 }
3425 }
3426
3427 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3428 }
3429
3430 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3432 int x;
3433
3434 line[0] = '\0';
3435 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3436 char token[TOKEN_SIZE];
3437 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3438
3439 if (ptile->claimer == nullptr) {
3440 strcpy(token, "-");
3441 } else {
3442 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3443 }
3444 strcat(line, token);
3445 if (x + 1 < MAP_NATIVE_WIDTH) {
3446 strcat(line, ",");
3447 }
3448 }
3449
3450 secfile_insert_str(saving->file, line, "map.source%04d", y);
3451 }
3452
3453 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3455 int x;
3456
3457 line[0] = '\0';
3458 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3459 char token[TOKEN_SIZE];
3460 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3461
3462 if (!saving->save_players || extra_owner(ptile) == nullptr) {
3463 strcpy(token, "-");
3464 } else {
3465 fc_snprintf(token, sizeof(token), "%d",
3466 player_number(extra_owner(ptile)));
3467 }
3468 strcat(line, token);
3469 if (x + 1 < MAP_NATIVE_WIDTH) {
3470 strcat(line, ",");
3471 }
3472 }
3473
3474 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3475 }
3476
3477 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3479 int x;
3480
3481 line[0] = '\0';
3482 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3483 char token[TOKEN_SIZE];
3484 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3485
3486 if (ptile->placing == nullptr) {
3487 strcpy(token, "-");
3488 } else {
3489 fc_snprintf(token, sizeof(token), "%d",
3490 extra_number(ptile->placing));
3491 }
3492 strcat(line, token);
3493 if (x + 1 < MAP_NATIVE_WIDTH) {
3494 strcat(line, ",");
3495 }
3496 }
3497
3498 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3499 }
3500
3501 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3503 int x;
3504
3505 line[0] = '\0';
3506 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3507 char token[TOKEN_SIZE];
3508 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3509
3510 if (ptile->placing != nullptr) {
3511 fc_snprintf(token, sizeof(token), "%d",
3512 ptile->infra_turns);
3513 } else {
3514 fc_snprintf(token, sizeof(token), "0");
3515 }
3516 strcat(line, token);
3517 if (x + 1 < MAP_NATIVE_WIDTH) {
3518 strcat(line, ",");
3519 }
3520 }
3521
3522 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3523 }
3524}
3525
3526/************************************************************************/
3530{
3531 int x, y;
3532
3533 /* Check status and return if not OK (sg_success FALSE). */
3534 sg_check_ret();
3535
3536 sg_failure_ret(loading->worked_tiles == nullptr,
3537 "City worked map not loaded!");
3538
3539 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3540 sizeof(*loading->worked_tiles));
3541
3542 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3543 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3544 y);
3545 const char *ptr = buffer;
3546
3547 sg_failure_ret(buffer != nullptr,
3548 "Savegame corrupt - map line %d not found.", y);
3549 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3550 char token[TOKEN_SIZE];
3551 int number;
3552 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3553
3554 scanin(&ptr, ",", token, sizeof(token));
3555 sg_failure_ret('\0' != token[0],
3556 "Savegame corrupt - map size not correct.");
3557 if (strcmp(token, "-") == 0) {
3558 number = -1;
3559 } else {
3560 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3561 "Savegame corrupt - got tile worked by city "
3562 "id=%s in (%d, %d).", token, x, y);
3563 }
3564
3565 loading->worked_tiles[ptile->index] = number;
3566 }
3567 }
3568}
3569
3570/************************************************************************/
3574{
3575 int x, y;
3576
3577 /* Check status and return if not OK (sg_success FALSE). */
3578 sg_check_ret();
3579
3580 if (saving->scenario && !saving->save_players) {
3581 /* Nothing to do for a scenario without saved players. */
3582 return;
3583 }
3584
3585 /* Additionally save the tiles worked by the cities */
3586 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3588
3589 line[0] = '\0';
3590 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3591 char token[TOKEN_SIZE];
3592 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3593 struct city *pcity = tile_worked(ptile);
3594
3595 if (pcity == nullptr) {
3596 strcpy(token, "-");
3597 } else {
3598 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3599 }
3600 strcat(line, token);
3601 if (x < MAP_NATIVE_WIDTH) {
3602 strcat(line, ",");
3603 }
3604 }
3605 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3606 }
3607}
3608
3609/************************************************************************/
3613{
3614 /* Check status and return if not OK (sg_success FALSE). */
3615 sg_check_ret();
3616
3617 players_iterate(pplayer) {
3618 /* Allocate player private map here; it is needed in different modules
3619 * besides this one ((i.e. sg_load_player_*()). */
3620 player_map_init(pplayer);
3622
3624 "game.save_known")) {
3625 int lines = player_slot_max_used_number() / 32 + 1;
3626 int j, p, l, i;
3627 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3628
3629 for (l = 0; l < lines; l++) {
3630 for (j = 0; j < 8; j++) {
3631 for (i = 0; i < 4; i++) {
3632 /* Only bother trying to load the map for this halfbyte if at least
3633 * one of the corresponding player slots is in use. */
3634 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3635 LOAD_MAP_CHAR(ch, ptile,
3636 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3637 |= ascii_hex2bin(ch, j),
3638 loading->file, "map.k%02d_%04d", l * 8 + j);
3639 break;
3640 }
3641 }
3642 }
3643 }
3644
3645 players_iterate(pplayer) {
3646 dbv_clr_all(&pplayer->tile_known);
3648
3649 /* HACK: we read the known data from hex into 32-bit integers, and
3650 * now we convert it to the known tile data of each player. */
3651 whole_map_iterate(&(wld.map), ptile) {
3652 players_iterate(pplayer) {
3653 p = player_index(pplayer);
3654 l = player_index(pplayer) / 32;
3655
3656 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3657 map_set_known(ptile, pplayer);
3658 }
3661
3662 FC_FREE(known);
3663 }
3664}
3665
3666/************************************************************************/
3670{
3671 /* Check status and return if not OK (sg_success FALSE). */
3672 sg_check_ret();
3673
3674 if (!saving->save_players) {
3675 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3676 return;
3677 } else {
3678 int lines = player_slot_max_used_number() / 32 + 1;
3679
3681 "game.save_known");
3683 int j, p, l, i;
3684 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3685
3686 /* HACK: we convert the data into a 32-bit integer, and then save it as
3687 * hex. */
3688
3689 whole_map_iterate(&(wld.map), ptile) {
3690 players_iterate(pplayer) {
3691 if (map_is_known(ptile, pplayer)) {
3692 p = player_index(pplayer);
3693 l = p / 32;
3694 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3695 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3696 }
3699
3700 for (l = 0; l < lines; l++) {
3701 for (j = 0; j < 8; j++) {
3702 for (i = 0; i < 4; i++) {
3703 /* Only bother saving the map for this halfbyte if at least one
3704 * of the corresponding player slots is in use */
3705 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3706 /* put 4-bit segments of the 32-bit "known" field */
3708 + tile_index(ptile)], j),
3709 saving->file, "map.k%02d_%04d", l * 8 + j);
3710 break;
3711 }
3712 }
3713 }
3714 }
3715
3716 FC_FREE(known);
3717 }
3718 }
3719}
3720
3721/* =======================================================================
3722 * Load / save player data.
3723 *
3724 * This is split into two parts as some data can only be loaded if the
3725 * number of players is known and the corresponding player slots are
3726 * defined.
3727 * ======================================================================= */
3728
3729/************************************************************************/
3733{
3734 int i, k, nplayers;
3735 const char *str;
3736 bool shuffle_loaded = TRUE;
3737
3738 /* Check status and return if not OK (sg_success FALSE). */
3739 sg_check_ret();
3740
3741 if (S_S_INITIAL == loading->server_state
3742 || game.info.is_new_game) {
3743 /* Nothing more to do. */
3744 return;
3745 }
3746
3747 /* Load destroyed wonders: */
3749 "players.destroyed_wonders");
3750 sg_failure_ret(str != nullptr, "%s", secfile_error());
3751 sg_failure_ret(strlen(str) == loading->improvement.size,
3752 "Invalid length for 'players.destroyed_wonders' ("
3753 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3754 strlen(str), loading->improvement.size);
3755 for (k = 0; k < loading->improvement.size; k++) {
3756 sg_failure_ret(str[k] == '1' || str[k] == '0',
3757 "Undefined value '%c' within "
3758 "'players.destroyed_wonders'.", str[k]);
3759
3760 if (str[k] == '1') {
3761 struct impr_type *pimprove
3762 = improvement_by_rule_name(loading->improvement.order[k]);
3763
3764 if (pimprove != nullptr) {
3767 }
3768 }
3769 }
3770
3771 server.identity_number
3772 = secfile_lookup_int_default(loading->file, server.identity_number,
3773 "players.identity_number_used");
3774
3775 /* First remove all defined players. */
3776 players_iterate(pplayer) {
3777 server_remove_player(pplayer);
3779
3780 /* Now, load the players from the savefile. */
3781 player_slots_iterate(pslot) {
3782 struct player *pplayer;
3783 struct rgbcolor *prgbcolor = nullptr;
3784 int pslot_id = player_slot_index(pslot);
3785
3786 if (secfile_section_lookup(loading->file, "player%d",
3787 pslot_id) == nullptr) {
3788 continue;
3789 }
3790
3791 /* Get player AI type. */
3792 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3793 player_slot_index(pslot));
3794 sg_failure_ret(str != nullptr, "%s", secfile_error());
3795
3796 /* Get player color */
3797 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3798 pslot_id)) {
3799 if (game_was_started()) {
3800 log_sg("Game has started, yet player %d has no color defined.",
3801 pslot_id);
3802 /* This will be fixed up later */
3803 } else {
3804 log_verbose("No color defined for player %d.", pslot_id);
3805 /* Colors will be assigned on game start, or at end of savefile
3806 * loading if game has already started */
3807 }
3808 }
3809
3810 /* Create player. */
3811 pplayer = server_create_player(player_slot_index(pslot), str,
3812 prgbcolor,
3815 sg_failure_ret(pplayer != nullptr, "Invalid AI type: '%s'!", str);
3816
3817 server_player_init(pplayer, FALSE, FALSE);
3818
3819 /* Free the color definition. */
3821
3822 /* Multipliers (policies) */
3823
3824 /* First initialise player values with ruleset defaults; this will
3825 * cover any in the ruleset not known when the savefile was created. */
3826 multipliers_iterate(pmul) {
3827 pplayer->multipliers[multiplier_index(pmul)].value
3828 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3830
3831 /* Now override with any values from the savefile. */
3832 for (k = 0; k < loading->multiplier.size; k++) {
3833 const struct multiplier *pmul = loading->multiplier.order[k];
3834
3835 if (pmul) {
3837 int val =
3839 "player%d.multiplier%d.val",
3840 player_slot_index(pslot), k);
3841 int rval = (((CLIP(pmul->start, val, pmul->stop)
3842 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3843
3844 if (rval != val) {
3845 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3846 "was %d, clamped to %d", pslot_id,
3847 multiplier_rule_name(pmul), val, rval);
3848 }
3849 pplayer->multipliers[idx].value = rval;
3850
3851 val =
3853 pplayer->multipliers[idx].value,
3854 "player%d.multiplier%d.target",
3855 player_slot_index(pslot), k);
3856 rval = (((CLIP(pmul->start, val, pmul->stop)
3857 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3858
3859 if (rval != val) {
3860 log_verbose("Player %d had illegal value for multiplier_target "
3861 " \"%s\": was %d, clamped to %d", pslot_id,
3862 multiplier_rule_name(pmul), val, rval);
3863 }
3864 pplayer->multipliers[idx].target = rval;
3865
3866 pplayer->multipliers[idx].changed
3868 "player%d.multiplier%d.changed",
3869 player_slot_index(pslot), k);
3870 } /* else silently discard multiplier not in current ruleset */
3871 }
3872
3873 /* Must be loaded before tile owner is set. */
3874 pplayer->server.border_vision =
3876 "player%d.border_vision",
3877 player_slot_index(pslot));
3878
3880 "player%d.autoselect_weight",
3881 pslot_id);
3883
3884 /* check number of players */
3885 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3886 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3887 "(%d) from the loaded game does not match the number of "
3888 "players present (%d).", nplayers, player_count());
3889
3890 /* Load team information. */
3891 players_iterate(pplayer) {
3892 int team;
3893 struct team_slot *tslot = nullptr;
3894
3896 "player%d.team_no",
3897 player_number(pplayer))
3899 "Invalid team definition for player %s (nb %d).",
3900 player_name(pplayer), player_number(pplayer));
3901 /* Should never fail when slot given is not nullptr */
3902 team_add_player(pplayer, team_new(tslot));
3904
3905 /* Loading the shuffle list is quite complex. At the time of saving the
3906 * shuffle data is saved as
3907 * shuffled_player_<number> = player_slot_id
3908 * where number is an increasing number and player_slot_id is a number
3909 * between 0 and the maximum number of player slots. Now we have to create
3910 * a list
3911 * shuffler_players[number] = player_slot_id
3912 * where all player slot IDs are used exactly one time. The code below
3913 * handles this ... */
3914 if (secfile_lookup_int_default(loading->file, -1,
3915 "players.shuffled_player_%d", 0) >= 0) {
3916 int slots = player_slot_count();
3917 int plrcount = player_count();
3920
3921 for (i = 0; i < slots; i++) {
3922 /* Array to save used numbers. */
3924 /* List of all player IDs (needed for set_shuffled_players()). It is
3925 * initialised with the value -1 to indicate that no value is set. */
3926 shuffled_players[i] = -1;
3927 }
3928
3929 /* Load shuffled player list. */
3930 for (i = 0; i < plrcount; i++) {
3931 int shuffle
3933 "players.shuffled_player_%d", i);
3934
3935 if (shuffle == -1) {
3936 log_sg("Missing player shuffle information (index %d) "
3937 "- reshuffle player list!", i);
3939 break;
3940 } else if (shuffled_player_set[shuffle]) {
3941 log_sg("Player shuffle %d used two times "
3942 "- reshuffle player list!", shuffle);
3944 break;
3945 }
3946 /* Set this ID as used. */
3948
3949 /* Save the player ID in the shuffle list. */
3951 }
3952
3953 if (shuffle_loaded) {
3954 /* Insert missing numbers. */
3955 int shuffle_index = plrcount;
3956
3957 for (i = 0; i < slots; i++) {
3958 if (!shuffled_player_set[i]) {
3960 }
3961
3962 /* shuffle_index must not grow higher than size of shuffled_players. */
3964 "Invalid player shuffle data!");
3965 }
3966
3967#ifdef FREECIV_DEBUG
3968 log_debug("[load shuffle] player_count() = %d", player_count());
3969 player_slots_iterate(pslot) {
3970 int plrid = player_slot_index(pslot);
3971
3972 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3974 shuffled_player_set[plrid] ? "is used" : "-");
3976#endif /* FREECIV_DEBUG */
3977
3978 /* Set shuffle list from savegame. */
3980 }
3981 }
3982
3983 if (!shuffle_loaded) {
3984 /* No shuffled players included or error loading them, so shuffle them
3985 * (this may include scenarios). */
3987 }
3988}
3989
3990/************************************************************************/
3994{
3995 /* Check status and return if not OK (sg_success FALSE). */
3996 sg_check_ret();
3997
3998 if (game.info.is_new_game) {
3999 /* Nothing to do. */
4000 return;
4001 }
4002
4003 players_iterate(pplayer) {
4004 sg_load_player_main(loading, pplayer);
4006 sg_load_player_units(loading, pplayer);
4008
4009 /* Check the success of the functions above. */
4010 sg_check_ret();
4011
4012 /* Print out some information */
4013 if (is_ai(pplayer)) {
4014 log_normal(_("%s has been added as %s level AI-controlled player "
4015 "(%s)."), player_name(pplayer),
4016 ai_level_translated_name(pplayer->ai_common.skill_level),
4017 ai_name(pplayer->ai));
4018 } else {
4019 log_normal(_("%s has been added as human player."),
4020 player_name(pplayer));
4021 }
4023
4024 /* Also load the transport status of the units here. It must be a special
4025 * case as all units must be known (unit on an allied transporter). */
4026 players_iterate(pplayer) {
4027 /* Load unit transport status. */
4030
4031 /* Savegame may contain nation assignments that are incompatible with the
4032 * current nationset. Ensure they are compatible, one way or another. */
4034
4035 /* Some players may have invalid nations in the ruleset. Once all players
4036 * are loaded, pick one of the remaining nations for them. */
4037 players_iterate(pplayer) {
4038 if (pplayer->nation == NO_NATION_SELECTED) {
4039 player_set_nation(pplayer, pick_a_nation(nullptr, FALSE, TRUE,
4041 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4042 log_sg(_("%s had invalid nation; changing to %s."),
4043 player_name(pplayer), nation_plural_for_player(pplayer));
4044
4045 ai_traits_init(pplayer);
4046 }
4048
4049 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4052 if (pplayers_allied(plr, aplayer)) {
4054 DS_ALLIANCE);
4055
4058 log_sg("Illegal alliance structure detected: "
4059 "%s alliance to %s reduced to peace treaty.",
4064 }
4065 }
4068
4069 /* Update cached city illness. This can depend on trade routes,
4070 * so can't be calculated until all players have been loaded. */
4071 if (game.info.illness_on) {
4073 pcity->server.illness
4074 = city_illness_calc(pcity, nullptr, nullptr,
4075 &(pcity->illness_trade), nullptr);
4077 }
4078
4079 /* Update all city information. This must come after all cities are
4080 * loaded (in player_load) but before player (dumb) cities are loaded
4081 * in player_load_vision(). */
4082 players_iterate(plr) {
4083 city_list_iterate(plr->cities, pcity) {
4086 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4089
4090 /* Since the cities must be placed on the map to put them on the
4091 player map we do this afterwards */
4092 players_iterate(pplayer) {
4094 /* Check the success of the function above. */
4095 sg_check_ret();
4097
4098 /* Check shared vision and tiles. */
4099 players_iterate(pplayer) {
4100 BV_CLR_ALL(pplayer->gives_shared_vision);
4101 BV_CLR_ALL(pplayer->gives_shared_tiles);
4102 BV_CLR_ALL(pplayer->server.really_gives_vision);
4104
4105 /* Set up shared vision... */
4106 players_iterate(pplayer) {
4107 int plr1 = player_index(pplayer);
4108
4110 int plr2 = player_index(pplayer2);
4111
4113 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4114 give_shared_vision(pplayer, pplayer2);
4115 }
4117 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4118 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4119 }
4122
4123 /* ...and check it */
4126 /* TODO: Is there a good reason player is not marked as
4127 * giving shared vision to themselves -> really_gives_vision()
4128 * returning FALSE when pplayer1 == pplayer2 */
4129 if (pplayer1 != pplayer2
4132 sg_regr(3000900,
4133 _("%s did not give shared vision to team member %s."),
4136 }
4138 sg_regr(3000900,
4139 _("%s did not give shared vision to team member %s."),
4142 }
4143 }
4146
4149
4150 /* All vision is ready; this calls city_thaw_workers_queue(). */
4152
4153 /* Make sure everything is consistent. */
4154 players_iterate(pplayer) {
4155 unit_list_iterate(pplayer->units, punit) {
4157 struct tile *ptile = unit_tile(punit);
4158
4159 log_sg("%s doing illegal activity in savegame!",
4161 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4165 : "missing",
4166 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4168 }
4171
4174 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4176
4177 /* Player colors are always needed once game has started. Pre-2.4 savegames
4178 * lack them. This cannot be in compatibility conversion layer as we need
4179 * all the player data available to be able to assign best colors. */
4180 if (game_was_started()) {
4182 }
4183}
4184
4185/************************************************************************/
4188static void sg_save_players(struct savedata *saving)
4189{
4190 /* Check status and return if not OK (sg_success FALSE). */
4191 sg_check_ret();
4192
4193 if ((saving->scenario && !saving->save_players)
4194 || !game_was_started()) {
4195 /* Nothing to do for a scenario without saved players or a game in
4196 * INITIAL state. */
4197 return;
4198 }
4199
4200 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4201
4202 /* Save destroyed wonders as bitvector. Note that improvement order
4203 * is saved in 'savefile.improvement.order'. */
4204 {
4205 char destroyed[B_LAST+1];
4206
4207 improvement_iterate(pimprove) {
4208 if (is_great_wonder(pimprove)
4209 && great_wonder_is_destroyed(pimprove)) {
4210 destroyed[improvement_index(pimprove)] = '1';
4211 } else {
4212 destroyed[improvement_index(pimprove)] = '0';
4213 }
4215 destroyed[improvement_count()] = '\0';
4217 "players.destroyed_wonders");
4218 }
4219
4220 secfile_insert_int(saving->file, server.identity_number,
4221 "players.identity_number_used");
4222
4223 /* Save player order. */
4224 {
4225 int i = 0;
4226 shuffled_players_iterate(pplayer) {
4227 secfile_insert_int(saving->file, player_number(pplayer),
4228 "players.shuffled_player_%d", i);
4229 i++;
4231 }
4232
4233 /* Sort units. */
4235
4236 /* Save players. */
4237 players_iterate(pplayer) {
4238 sg_save_player_main(saving, pplayer);
4239 sg_save_player_cities(saving, pplayer);
4240 sg_save_player_units(saving, pplayer);
4242 sg_save_player_vision(saving, pplayer);
4244}
4245
4246/************************************************************************/
4250 struct player *plr)
4251{
4252 const char **slist;
4253 int i, plrno = player_number(plr);
4254 const char *str;
4255 struct government *gov;
4256 const char *level;
4257 const char *barb_str;
4258 size_t nval;
4259 const char *kind;
4260
4261 /* Check status and return if not OK (sg_success FALSE). */
4262 sg_check_ret();
4263
4264 /* Basic player data. */
4265 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4266 sg_failure_ret(str != nullptr, "%s", secfile_error());
4268 sz_strlcpy(plr->username,
4270 "player%d.username", plrno));
4272 "player%d.unassigned_user", plrno),
4273 "%s", secfile_error());
4276 "player%d.orig_username", plrno));
4279 "player%d.ranked_username",
4280 plrno));
4282 "player%d.unassigned_ranked", plrno),
4283 "%s", secfile_error());
4285 "player%d.delegation_username",
4286 plrno);
4287 /* Defaults to no delegation. */
4288 if (strlen(str)) {
4290 }
4291
4292 /* Player flags */
4293 BV_CLR_ALL(plr->flags);
4294 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4295 for (i = 0; i < nval; i++) {
4296 const char *sval = slist[i];
4298
4299 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4300
4301 BV_SET(plr->flags, fid);
4302 }
4303 free(slist);
4304
4305 /* Nation */
4306 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4308 if (plr->nation != nullptr) {
4309 ai_traits_init(plr);
4310 }
4311
4312 /* Government */
4313 str = secfile_lookup_str(loading->file, "player%d.government_name",
4314 plrno);
4316 sg_failure_ret(gov != nullptr, "Player%d: unsupported government \"%s\".",
4317 plrno, str);
4318 plr->government = gov;
4319
4320 /* Target government */
4322 "player%d.target_government_name", plrno);
4323 if (str != nullptr) {
4325 } else {
4326 plr->target_government = nullptr;
4327 }
4330 "player%d.revolution_finishes", plrno);
4331
4332 /* Load diplomatic data (diplstate + embassy + vision).
4333 * Shared vision is loaded in sg_load_players(). */
4335 players_iterate(pplayer) {
4336 char buf[32];
4337 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4338 i = player_index(pplayer);
4339
4340 /* Load diplomatic status */
4341 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4342
4343 ds->type =
4345 diplstate_type, "%s.current", buf);
4346 ds->max_state =
4348 diplstate_type, "%s.closest", buf);
4349
4350 /* FIXME: If either party is barbarian, we cannot enforce below check */
4351#if 0
4352 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4353 sg_regr(3020000,
4354 "Player%d: War with player %d who has never been met. "
4355 "Reverted to No Contact state.", plrno, i);
4356 ds->type = DS_NO_CONTACT;
4357 }
4358#endif
4359
4360 if (valid_dst_closest(ds) != ds->max_state) {
4361 sg_regr(3020000,
4362 "Player%d: closest diplstate to player %d less than current. "
4363 "Updated.", plrno, i);
4364 ds->max_state = ds->type;
4365 }
4366
4367 ds->first_contact_turn =
4369 "%s.first_contact_turn", buf);
4370 ds->turns_left =
4371 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4372 ds->has_reason_to_cancel =
4374 "%s.has_reason_to_cancel", buf);
4375 ds->contact_turns_left =
4377 "%s.contact_turns_left", buf);
4378
4379 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4380 buf)) {
4381 BV_SET(plr->real_embassy, i);
4382 }
4383 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4384 * must be known. */
4386
4387 /* load ai data */
4389 char buf[32];
4390
4391 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4393
4395 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4396 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4398
4400 "player%d.adv.wonder_city",
4401 plrno);
4402
4403 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4404
4405 /* Some sane defaults */
4406 plr->ai_common.fuzzy = 0;
4407 plr->ai_common.expand = 100;
4408 plr->ai_common.science_cost = 100;
4409
4410
4411 level = secfile_lookup_str_default(loading->file, nullptr,
4412 "player%d.ai.level", plrno);
4413 if (level != nullptr && !fc_strcasecmp("Handicapped", level)) {
4414 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4416 } else {
4418 }
4419
4421 log_sg("Player%d: Invalid AI level \"%s\". "
4422 "Changed to \"%s\".", plrno, level,
4425 }
4426
4428 "player%d.ai.barb_type", plrno);
4430
4432 log_sg("Player%d: Invalid barbarian type \"%s\". "
4433 "Changed to \"None\".", plrno, barb_str);
4435 }
4436
4437 if (is_barbarian(plr)) {
4438 server.nbarbarians++;
4439 }
4440
4441 if (is_ai(plr)) {
4443 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4444 }
4445
4446 /* Load nation style. */
4447 {
4448 struct nation_style *style;
4449
4450 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4451
4452 sg_failure_ret(str != nullptr, "%s", secfile_error());
4453 style = style_by_rule_name(str);
4454 if (style == nullptr) {
4455 style = style_by_number(0);
4456 log_sg("Player%d: unsupported city_style_name \"%s\". "
4457 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4458 }
4459 plr->style = style;
4460 }
4461
4463 "player%d.idle_turns", plrno),
4464 "%s", secfile_error());
4465 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4466 if (sex_by_name(kind) == SEX_MALE) {
4467 plr->is_male = TRUE;
4468 } else {
4469 plr->is_male = FALSE;
4470 }
4472 "player%d.is_alive", plrno),
4473 "%s", secfile_error());
4475 "player%d.turns_alive", plrno),
4476 "%s", secfile_error());
4478 "player%d.last_war", plrno),
4479 "%s", secfile_error());
4481 "player%d.phase_done", plrno);
4483 "player%d.gold", plrno),
4484 "%s", secfile_error());
4486 "player%d.rates.tax", plrno),
4487 "%s", secfile_error());
4489 "player%d.rates.science", plrno),
4490 "%s", secfile_error());
4492 "player%d.rates.luxury", plrno),
4493 "%s", secfile_error());
4495 "player%d.infrapts",
4496 plrno);
4497 plr->server.bulbs_last_turn =
4499 "player%d.research.bulbs_last_turn", plrno);
4500
4501 /* Traits */
4502 if (plr->nation) {
4503 for (i = 0; i < loading->trait.size; i++) {
4504 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4505
4506 if (trait_is_valid(tr)) {
4507 int val;
4508
4509 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4510 plrno, i),
4511 "%s", secfile_error());
4512 plr->ai_common.traits[tr].val = val;
4513
4515 "player%d.trait%d.mod", plrno, i),
4516 "%s", secfile_error());
4517 plr->ai_common.traits[tr].mod = val;
4518 }
4519 }
4520 }
4521
4522 /* Achievements */
4523 {
4524 int count;
4525
4526 count = secfile_lookup_int_default(loading->file, -1,
4527 "player%d.achievement_count", plrno);
4528
4529 if (count > 0) {
4530 for (i = 0; i < count; i++) {
4531 const char *name;
4532 struct achievement *pach;
4533 bool first;
4534
4536 "player%d.achievement%d.name", plrno, i);
4538
4539 sg_failure_ret(pach != nullptr,
4540 "Unknown achievement \"%s\".", name);
4541
4543 "player%d.achievement%d.first",
4544 plrno, i),
4545 "achievement error: %s", secfile_error());
4546
4547 sg_failure_ret(pach->first == nullptr || !first,
4548 "Multiple players listed as first to get achievement \"%s\".",
4549 name);
4550
4551 BV_SET(pach->achievers, player_index(plr));
4552
4553 if (first) {
4554 pach->first = plr;
4555 }
4556 }
4557 }
4558 }
4559
4560 /* Player score. */
4561 plr->score.happy =
4563 "score%d.happy", plrno);
4564 plr->score.content =
4566 "score%d.content", plrno);
4567 plr->score.unhappy =
4569 "score%d.unhappy", plrno);
4570 plr->score.angry =
4572 "score%d.angry", plrno);
4573
4574 /* Make sure that the score about specialists in current ruleset that
4575 * were not present at saving time are set to zero. */
4577 plr->score.specialists[sp] = 0;
4579
4580 for (i = 0; i < loading->specialist.size; i++) {
4581 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4583 "score%d.specialists%d", plrno, i);
4584 }
4585
4586 plr->score.wonders =
4588 "score%d.wonders", plrno);
4589 plr->score.techs =
4591 "score%d.techs", plrno);
4592 plr->score.techout =
4594 "score%d.techout", plrno);
4595 plr->score.landarea =
4597 "score%d.landarea", plrno);
4598 plr->score.settledarea =
4600 "score%d.settledarea", plrno);
4601 plr->score.population =
4603 "score%d.population", plrno);
4604 plr->score.cities =
4606 "score%d.cities", plrno);
4607 plr->score.units =
4609 "score%d.units", plrno);
4610 plr->score.pollution =
4612 "score%d.pollution", plrno);
4613 plr->score.literacy =
4615 "score%d.literacy", plrno);
4616 plr->score.bnp =
4618 "score%d.bnp", plrno);
4619 plr->score.mfg =
4621 "score%d.mfg", plrno);
4622 plr->score.spaceship =
4624 "score%d.spaceship", plrno);
4625 plr->score.units_built =
4627 "score%d.units_built", plrno);
4628 plr->score.units_killed =
4630 "score%d.units_killed", plrno);
4631 plr->score.units_lost =
4633 "score%d.units_lost", plrno);
4634 plr->score.units_used =
4636 "score%d.units_used", plrno);
4637 plr->score.culture =
4639 "score%d.culture", plrno);
4640 plr->score.game =
4642 "score%d.total", plrno);
4643
4644 /* Load space ship data. */
4645 {
4646 struct player_spaceship *ship = &plr->spaceship;
4647 char prefix[32];
4648 const char *st;
4649 int ei;
4650
4651 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4654 &ei,
4655 "%s.state", prefix),
4656 "%s", secfile_error());
4657 ship->state = ei;
4658
4659 if (ship->state != SSHIP_NONE) {
4660 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4661 "%s.structurals", prefix),
4662 "%s", secfile_error());
4663 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4664 "%s.components", prefix),
4665 "%s", secfile_error());
4667 "%s.modules", prefix),
4668 "%s", secfile_error());
4670 "%s.fuel", prefix),
4671 "%s", secfile_error());
4672 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4673 "%s.propulsion", prefix),
4674 "%s", secfile_error());
4675 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4676 "%s.habitation", prefix),
4677 "%s", secfile_error());
4678 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4679 "%s.life_support", prefix),
4680 "%s", secfile_error());
4681 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4682 "%s.solar_panels", prefix),
4683 "%s", secfile_error());
4684
4685 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4686 sg_failure_ret(st != nullptr, "%s", secfile_error())
4687 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4688 sg_failure_ret(st[i] == '1' || st[i] == '0',
4689 "Undefined value '%c' within '%s.structure'.", st[i],
4690 prefix)
4691
4692 if (!(st[i] == '0')) {
4693 BV_SET(ship->structure, i);
4694 }
4695 }
4696 if (ship->state >= SSHIP_LAUNCHED) {
4697 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4698 "%s.launch_year", prefix),
4699 "%s", secfile_error());
4700 }
4702 }
4703 }
4704
4705 /* Load lost wonder data. */
4706 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4707 /* If not present, probably an old savegame; nothing to be done */
4708 if (str != nullptr) {
4709 int k;
4710
4711 sg_failure_ret(strlen(str) == loading->improvement.size,
4712 "Invalid length for 'player%d.lost_wonders' ("
4713 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4714 plrno, strlen(str), loading->improvement.size);
4715 for (k = 0; k < loading->improvement.size; k++) {
4716 sg_failure_ret(str[k] == '1' || str[k] == '0',
4717 "Undefined value '%c' within "
4718 "'player%d.lost_wonders'.", plrno, str[k]);
4719
4720 if (str[k] == '1') {
4721 struct impr_type *pimprove
4722 = improvement_by_rule_name(loading->improvement.order[k]);
4723
4724 if (pimprove) {
4725 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4726 }
4727 }
4728 }
4729 }
4730
4731 plr->history
4732 = secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4733 plr->server.huts
4734 = secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4735}
4736
4737/************************************************************************/
4741 struct player *plr)
4742{
4743 int i, k, plrno = player_number(plr);
4744 struct player_spaceship *ship = &plr->spaceship;
4745 const char *flag_names[PLRF_COUNT];
4746 int set_count;
4747
4748 /* Check status and return if not OK (sg_success FALSE). */
4749 sg_check_ret();
4750
4751 set_count = 0;
4752 for (i = 0; i < PLRF_COUNT; i++) {
4753 if (player_has_flag(plr, i)) {
4755 }
4756 }
4757
4759 "player%d.flags", plrno);
4760
4761 secfile_insert_str(saving->file, ai_name(plr->ai),
4762 "player%d.ai_type", plrno);
4764 "player%d.name", plrno);
4766 "player%d.username", plrno);
4768 "player%d.unassigned_user", plrno);
4769 if (plr->rgb != nullptr) {
4770 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4771 } else {
4772 /* Colorless players are ok in pregame */
4773 if (game_was_started()) {
4774 log_sg("Game has started, yet player %d has no color defined.", plrno);
4775 }
4776 }
4778 "player%d.ranked_username", plrno);
4780 "player%d.unassigned_ranked", plrno);
4782 "player%d.orig_username", plrno);
4785 : "",
4786 "player%d.delegation_username", plrno);
4788 "player%d.nation", plrno);
4789 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4790 "player%d.team_no", plrno);
4791
4794 "player%d.government_name", plrno);
4795
4796 if (plr->target_government) {
4799 "player%d.target_government_name", plrno);
4800 }
4801
4803 "player%d.style_by_name", plrno);
4804
4806 "player%d.idle_turns", plrno);
4807 if (plr->is_male) {
4809 "player%d.kind", plrno);
4810 } else {
4812 "player%d.kind", plrno);
4813 }
4815 "player%d.is_alive", plrno);
4817 "player%d.turns_alive", plrno);
4819 "player%d.last_war", plrno);
4821 "player%d.phase_done", plrno);
4822
4823 players_iterate(pplayer) {
4824 char buf[32];
4825 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4826
4827 i = player_index(pplayer);
4828
4829 /* save diplomatic state */
4830 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4831
4832 secfile_insert_enum(saving->file, ds->type,
4833 diplstate_type, "%s.current", buf);
4834 secfile_insert_enum(saving->file, ds->max_state,
4835 diplstate_type, "%s.closest", buf);
4836 secfile_insert_int(saving->file, ds->first_contact_turn,
4837 "%s.first_contact_turn", buf);
4838 secfile_insert_int(saving->file, ds->turns_left,
4839 "%s.turns_left", buf);
4840 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4841 "%s.has_reason_to_cancel", buf);
4842 secfile_insert_int(saving->file, ds->contact_turns_left,
4843 "%s.contact_turns_left", buf);
4845 "%s.embassy", buf);
4846 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4847 "%s.gives_shared_vision", buf);
4848 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4849 "%s.gives_shared_tiles", buf);
4851
4854 /* save ai data */
4856 "player%d.ai%d.love", plrno, i);
4857 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4859
4861 "player%d.adv.wonder_city", plrno);
4862
4863 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4864
4865 /* Multipliers (policies) */
4866 i = multiplier_count();
4867
4868 for (k = 0; k < i; k++) {
4870 "player%d.multiplier%d.val", plrno, k);
4872 "player%d.multiplier%d.target", plrno, k);
4874 "player%d.multiplier%d.changed", plrno, k);
4875 }
4876
4878 "player%d.ai.level", plrno);
4880 "player%d.ai.barb_type", plrno);
4882 "player%d.gold", plrno);
4884 "player%d.rates.tax", plrno);
4886 "player%d.rates.science", plrno);
4888 "player%d.rates.luxury", plrno);
4890 "player%d.infrapts", plrno);
4892 "player%d.research.bulbs_last_turn", plrno);
4893
4894 /* Save traits */
4895 {
4896 enum trait tr;
4897 int j;
4898
4899 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4901 "player%d.trait%d.val", plrno, j);
4903 "player%d.trait%d.mod", plrno, j);
4904 }
4905 }
4906
4907 /* Save achievements */
4908 {
4909 int j = 0;
4910
4912 if (achievement_player_has(pach, plr)) {
4914 "player%d.achievement%d.name", plrno, j);
4915 if (pach->first == plr) {
4917 "player%d.achievement%d.first", plrno, j);
4918 } else {
4920 "player%d.achievement%d.first", plrno, j);
4921 }
4922
4923 j++;
4924 }
4926
4927 secfile_insert_int(saving->file, j,
4928 "player%d.achievement_count", plrno);
4929 }
4930
4932 "player%d.revolution_finishes", plrno);
4933
4934 /* Player score */
4936 "score%d.happy", plrno);
4938 "score%d.content", plrno);
4940 "score%d.unhappy", plrno);
4942 "score%d.angry", plrno);
4945 "score%d.specialists%d", plrno, sp);
4948 "score%d.wonders", plrno);
4950 "score%d.techs", plrno);
4952 "score%d.techout", plrno);
4954 "score%d.landarea", plrno);
4956 "score%d.settledarea", plrno);
4958 "score%d.population", plrno);
4960 "score%d.cities", plrno);
4962 "score%d.units", plrno);
4964 "score%d.pollution", plrno);
4966 "score%d.literacy", plrno);
4967 secfile_insert_int(saving->file, plr->score.bnp,
4968 "score%d.bnp", plrno);
4969 secfile_insert_int(saving->file, plr->score.mfg,
4970 "score%d.mfg", plrno);
4972 "score%d.spaceship", plrno);
4974 "score%d.units_built", plrno);
4976 "score%d.units_killed", plrno);
4978 "score%d.units_lost", plrno);
4980 "score%d.units_used", plrno);
4982 "score%d.culture", plrno);
4983 secfile_insert_int(saving->file, plr->score.game,
4984 "score%d.total", plrno);
4985
4986 /* Save space ship status. */
4987 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4988 plrno);
4989 if (ship->state != SSHIP_NONE) {
4990 char buf[32];
4991 char st[NUM_SS_STRUCTURALS+1];
4992 int ssi;
4993
4994 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4995
4996 secfile_insert_int(saving->file, ship->structurals,
4997 "%s.structurals", buf);
4998 secfile_insert_int(saving->file, ship->components,
4999 "%s.components", buf);
5000 secfile_insert_int(saving->file, ship->modules,
5001 "%s.modules", buf);
5002 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
5003 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
5004 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
5005 secfile_insert_int(saving->file, ship->life_support,
5006 "%s.life_support", buf);
5007 secfile_insert_int(saving->file, ship->solar_panels,
5008 "%s.solar_panels", buf);
5009
5010 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
5011 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
5012 }
5013 st[ssi] = '\0';
5014 secfile_insert_str(saving->file, st, "%s.structure", buf);
5015 if (ship->state >= SSHIP_LAUNCHED) {
5016 secfile_insert_int(saving->file, ship->launch_year,
5017 "%s.launch_year", buf);
5018 }
5019 }
5020
5021 /* Save lost wonders info. */
5022 {
5023 char lost[B_LAST+1];
5024
5025 improvement_iterate(pimprove) {
5026 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5027 lost[improvement_index(pimprove)] = '1';
5028 } else {
5029 lost[improvement_index(pimprove)] = '0';
5030 }
5032 lost[improvement_count()] = '\0';
5034 "player%d.lost_wonders", plrno);
5035 }
5036
5037 secfile_insert_int(saving->file, plr->history,
5038 "player%d.history", plrno);
5040 "player%d.hut_count", plrno);
5041
5043 "player%d.border_vision", plrno);
5044
5045 if (saving->scenario) {
5046 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5047 int def = 1; /* We want users to get a player in a scenario */
5048
5050 /* This isn't usable player */
5051 def = 0;
5052 }
5053
5054 secfile_insert_int(saving->file, def,
5055 "player%d.autoselect_weight", plrno);
5056 } else {
5058 "player%d.autoselect_weight", plrno);
5059 }
5060 }
5061}
5062
5063/************************************************************************/
5067 struct player *plr)
5068{
5069 int ncities, i, plrno = player_number(plr);
5070 bool tasks_handled;
5072
5073 /* Check status and return if not OK (sg_success FALSE). */
5074 sg_check_ret();
5075
5077 "player%d.ncities", plrno),
5078 "%s", secfile_error());
5079
5080 if (!plr->is_alive && ncities > 0) {
5081 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5082 ncities = 0;
5083 }
5084
5086 "player%d.wl_max_length",
5087 plrno);
5089 log_sg("wlist_max_length %d over MAX_LEN_WORKLIST (%d)",
5091 }
5092
5094 "player%d.routes_max_length", plrno);
5095
5096 /* Load all cities of the player. */
5097 for (i = 0; i < ncities; i++) {
5098 char buf[32];
5099 struct city *pcity;
5100
5101 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5102
5103 /* Create a dummy city. */
5104 pcity = create_city_virtual(plr, nullptr, buf);
5110 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5111 }
5112
5115
5116 /* Load the information about the nationality of citizens. This is done
5117 * here because the city sanity check called by citizens_update() requires
5118 * that the city is registered. */
5120
5121 /* After everything is loaded, but before vision. */
5123
5124 /* adding the city contribution to fog-of-war */
5128
5130 }
5131
5133 for (i = 0; !tasks_handled; i++) {
5134 int city_id;
5135 struct city *pcity = nullptr;
5136
5137 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5138 plrno, i);
5139
5140 if (city_id != -1) {
5141 pcity = player_city_by_number(plr, city_id);
5142 }
5143
5144 if (pcity != nullptr) {
5145 const char *str;
5146 int nat_x, nat_y;
5147 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5148
5149 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5150 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5151
5152 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5153
5154 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5156
5158 "Unknown workertask activity %s", str);
5159
5160 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5161
5162 if (strcmp("-", str)) {
5164
5165 sg_failure_ret(ptask->tgt != nullptr,
5166 "Unknown workertask target %s", str);
5167 } else {
5168 ptask->tgt = nullptr;
5169
5170 if (ptask->act == ACTIVITY_IRRIGATE) {
5172 } else if (ptask->act == ACTIVITY_MINE) {
5173 ptask->act = ACTIVITY_MINE;
5174 }
5175 }
5176
5177 ptask->want = secfile_lookup_int_default(loading->file, 1,
5178 "player%d.task%d.want", plrno, i);
5179
5180 worker_task_list_append(pcity->task_reqs, ptask);
5181 } else {
5183 }
5184 }
5185}
5186
5187/************************************************************************/
5190static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5191 struct city *pcity, const char *citystr,
5193{
5194 struct player *past;
5195 const char *kind, *name, *str;
5196 int id, i, repair, sp_count = 0, workers = 0, value;
5197 int nat_x, nat_y;
5198 citizens size;
5199 const char *stylename;
5200 int partner;
5201 int want;
5202 int tmp_int;
5203 const struct civ_map *nmap = &(wld.map);
5204 enum capital_type cap;
5205
5207 FALSE, "%s", secfile_error());
5209 FALSE, "%s", secfile_error());
5211 sg_warn_ret_val(pcity->tile != nullptr, FALSE,
5212 "%s has invalid center tile (%d, %d)",
5213 citystr, nat_x, nat_y);
5215 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5216
5217 /* Instead of dying, use 'citystr' string for damaged name. */
5219 "%s.name", citystr));
5220
5222 citystr), FALSE, "%s", secfile_error());
5223
5225 "%s.original", citystr);
5226 past = player_by_number(id);
5227 if (past != nullptr) {
5228 pcity->original = past;
5229 }
5230
5231 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5232 citystr), FALSE, "%s", secfile_error());
5233 size = (citizens)value; /* Set the correct type */
5234 sg_warn_ret_val(value == (int)size, FALSE,
5235 "Invalid city size: %d, set to %d", value, size);
5237
5239 "%s.capital", citystr),
5241
5243 pcity->capital = cap;
5244 if (cap == CAPITAL_PRIMARY) {
5245 plr->primary_capital_id = pcity->id;
5246 }
5247 } else {
5248 pcity->capital = CAPITAL_NOT;
5249 }
5250
5251 for (i = 0; i < loading->specialist.size; i++) {
5252 Specialist_type_id si = specialist_index(loading->specialist.order[i]);
5253
5254 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5255 citystr, i),
5256 FALSE, "%s", secfile_error());
5257 pcity->specialists[si] = (citizens)value;
5259 sp_count += value;
5260 }
5261 }
5262
5263 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5264 for (i = 0; partner != 0; i++) {
5265 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5266 const char *dir;
5267 const char *good_str;
5268
5269 /* Append to routes list immediately, so the pointer can be found for freeing
5270 * even if we abort */
5272
5273 proute->partner = partner;
5274 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5275 sg_warn_ret_val(dir != nullptr, FALSE,
5276 "No traderoute direction found for %s", citystr);
5279 "Illegal route direction %s", dir);
5280 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5281 sg_warn_ret_val(dir != nullptr, FALSE,
5282 "No good found for %s", citystr);
5284 sg_warn_ret_val(proute->goods != nullptr, FALSE,
5285 "Illegal good %s", good_str);
5286
5287 /* Next one */
5289 "%s.traderoute%d", citystr, i + 1);
5290 }
5291
5292 for (; i < routes_max; i++) {
5293 secfile_entry_ignore(loading->file, "%s.traderoute%d", citystr, i);
5294 secfile_entry_ignore(loading->file, "%s.route_direction%d", citystr, i);
5295 secfile_entry_ignore(loading->file, "%s.route_good%d", citystr, i);
5296 }
5297
5298 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5299 "%s.food_stock", citystr),
5300 FALSE, "%s", secfile_error());
5301 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5302 "%s.shield_stock", citystr),
5303 FALSE, "%s", secfile_error());
5304 pcity->history =
5305 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5306
5307 pcity->airlift =
5308 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5309 pcity->was_happy =
5310 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5311 citystr);
5312 pcity->had_famine =
5313 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5314 citystr);
5315
5316 pcity->turn_plague =
5317 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5318
5320 "%s.anarchy", citystr),
5321 FALSE, "%s", secfile_error());
5322 pcity->rapture =
5323 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5324 pcity->steal =
5325 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5326
5327 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5328 "%s.turn_founded", citystr),
5329 FALSE, "%s", secfile_error());
5331 "%s.acquire_t", citystr),
5332 FALSE, "%s", secfile_error());
5333 pcity->acquire_t = tmp_int;
5334 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5335 citystr), FALSE, "%s", secfile_error());
5336 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5337 citystr), FALSE, "%s", secfile_error());
5338
5339 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5340 "%s.turn_last_built", citystr),
5341 FALSE, "%s", secfile_error());
5342
5343 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5344 citystr);
5345 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5346 citystr);
5347 pcity->production = universal_by_rule_name(kind, name);
5348 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5349 "%s.currently_building: unknown \"%s\" \"%s\".",
5350 citystr, kind, name);
5351
5352 want = secfile_lookup_int_default(loading->file, 0,
5353 "%s.current_want", citystr);
5354 if (pcity->production.kind == VUT_IMPROVEMENT) {
5355 pcity->server.adv->
5356 building_want[improvement_index(pcity->production.value.building)]
5357 = want;
5358 }
5359
5360 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5361 citystr);
5362 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5363 citystr);
5366 "%s.changed_from: unknown \"%s\" \"%s\".",
5367 citystr, kind, name);
5368
5369 pcity->before_change_shields =
5370 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5371 "%s.before_change_shields", citystr);
5372 pcity->caravan_shields =
5374 "%s.caravan_shields", citystr);
5375 pcity->disbanded_shields =
5377 "%s.disbanded_shields", citystr);
5378 pcity->last_turns_shield_surplus =
5380 "%s.last_turns_shield_surplus",
5381 citystr);
5382
5384 "%s.style", citystr);
5385 if (stylename != nullptr) {
5387 } else {
5388 pcity->style = 0;
5389 }
5390 if (pcity->style < 0) {
5391 pcity->style = city_style(pcity);
5392 }
5393
5394 pcity->server.synced = FALSE; /* Must re-sync with clients */
5395
5396 /* Initialise list of city improvements. */
5397 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5398 pcity->built[i].turn = I_NEVER;
5399 }
5400
5401 /* Load city improvements. */
5402 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5403 sg_warn_ret_val(str != nullptr, FALSE, "%s", secfile_error());
5404 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5405 "Invalid length of '%s.improvements' ("
5406 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5407 citystr, strlen(str), loading->improvement.size);
5408 for (i = 0; i < loading->improvement.size; i++) {
5409 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5410 "Undefined value '%c' within '%s.improvements'.",
5411 str[i], citystr)
5412
5413 if (str[i] == '1') {
5414 struct impr_type *pimprove
5415 = improvement_by_rule_name(loading->improvement.order[i]);
5416
5417 if (pimprove) {
5418 city_add_improvement(pcity, pimprove);
5419 }
5420 }
5421 }
5422
5423 sg_failure_ret_val(loading->worked_tiles != nullptr, FALSE,
5424 "No worked tiles map defined.");
5425
5427
5428 /* Load new savegame with variable (squared) city radius and worked
5429 * tiles map */
5430
5431 int radius_sq
5432 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5433 citystr);
5434 city_map_radius_sq_set(pcity, radius_sq);
5435
5437 if (loading->worked_tiles[ptile->index] == pcity->id) {
5438 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5439 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5440 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5441 TILE_XY(pcity->tile), TILE_XY(ptile));
5442 pcity->specialists[DEFAULT_SPECIALIST]++;
5443 sp_count++;
5444 } else {
5445 tile_set_worked(ptile, pcity);
5446 workers++;
5447 }
5448
5449#ifdef FREECIV_DEBUG
5450 /* Set this tile to unused; a check for not reset tiles is
5451 * included in game_load_internal() */
5452 loading->worked_tiles[ptile->index] = -1;
5453#endif /* FREECIV_DEBUG */
5454 }
5456
5457 if (tile_worked(city_tile(pcity)) != pcity) {
5458 struct city *pwork = tile_worked(city_tile(pcity));
5459
5460 if (pwork != nullptr) {
5461 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5462 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5465
5466 tile_set_worked(city_tile(pcity), nullptr); /* Remove tile from pwork */
5467 pwork->specialists[DEFAULT_SPECIALIST]++;
5469 } else {
5470 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5473 }
5474
5475 /* Repair pcity */
5478 }
5479
5481 if (0 != repair) {
5482 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5483 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5485 workers, FREE_WORKED_TILES, sp_count);
5486
5487 /* Repair pcity */
5489 }
5490
5491 /* worklist_init() done in create_city_virtual() */
5492 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5493
5494 /* Load city options. */
5495 BV_CLR_ALL(pcity->city_options);
5496 for (i = 0; i < loading->coptions.size; i++) {
5497 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5498 citystr, i)) {
5499 BV_SET(pcity->city_options, loading->coptions.order[i]);
5500 }
5501 }
5503 "%s.wlcb", citystr),
5504 FALSE, "%s", secfile_error());
5505 pcity->wlcb = tmp_int;
5506
5507 /* Load the city rally point. */
5508 {
5509 int len = secfile_lookup_int_default(loading->file, 0,
5510 "%s.rally_point_length", citystr);
5511 int unconverted;
5512
5513 pcity->rally_point.length = len;
5514 if (len > 0) {
5516
5517 pcity->rally_point.orders
5518 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5519 pcity->rally_point.persistent
5521 "%s.rally_point_persistent", citystr);
5522 pcity->rally_point.vigilant
5524 "%s.rally_point_vigilant", citystr);
5525
5528 "%s.rally_point_orders", citystr);
5531 "%s.rally_point_dirs", citystr);
5534 "%s.rally_point_activities", citystr);
5535
5536 for (i = 0; i < len; i++) {
5537 struct unit_order *order = &pcity->rally_point.orders[i];
5538
5539 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5540 || rally_activities[i] == '\0') {
5541 log_sg("Invalid rally point.");
5542 free(pcity->rally_point.orders);
5543 pcity->rally_point.orders = nullptr;
5544 pcity->rally_point.length = 0;
5545 break;
5546 }
5547 order->order = char2order(rally_orders[i]);
5548 order->dir = char2dir(rally_dirs[i]);
5549 order->activity = char2activity(rally_activities[i]);
5550
5552 "%s.rally_point_action_vec,%d",
5553 citystr, i);
5554
5555 if (unconverted == -1) {
5556 order->action = ACTION_NONE;
5557 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5558 /* Look up what action id the unconverted number represents. */
5559 order->action = loading->action.order[unconverted];
5560 } else {
5561 if (order->order == ORDER_PERFORM_ACTION) {
5562 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5563 pcity->id);
5564 }
5565
5566 order->action = ACTION_NONE;
5567 }
5568
5569 order->target
5571 "%s.rally_point_tgt_vec,%d",
5572 citystr, i);
5573 order->sub_target
5575 "%s.rally_point_sub_tgt_vec,%d",
5576 citystr, i);
5577 }
5578 } else {
5579 pcity->rally_point.orders = nullptr;
5580
5581 secfile_entry_ignore(loading->file, "%s.rally_point_persistent",
5582 citystr);
5583 secfile_entry_ignore(loading->file, "%s.rally_point_vigilant",
5584 citystr);
5585 secfile_entry_ignore(loading->file, "%s.rally_point_orders",
5586 citystr);
5587 secfile_entry_ignore(loading->file, "%s.rally_point_dirs",
5588 citystr);
5589 secfile_entry_ignore(loading->file, "%s.rally_point_activities",
5590 citystr);
5591 secfile_entry_ignore(loading->file, "%s.rally_point_action_vec",
5592 citystr);
5594 "%s.rally_point_tgt_vec", citystr);
5596 "%s.rally_point_sub_tgt_vec", citystr);
5597 }
5598 }
5599
5600 /* Load the city manager parameters. */
5601 {
5602 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5603 "%s.cma_enabled", citystr);
5604 if (enabled) {
5605 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5606
5607 for (i = 0; i < O_LAST; i++) {
5609 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5611 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5612 }
5613
5615 loading->file, FALSE, "%s.max_growth", citystr);
5617 loading->file, FALSE, "%s.require_happy", citystr);
5619 loading->file, FALSE, "%s.allow_disorder", citystr);
5621 loading->file, FALSE, "%s.allow_specialists", citystr);
5623 loading->file, 0, "%s.happy_factor", citystr);
5624 pcity->cm_parameter = param;
5625 } else {
5626 pcity->cm_parameter = nullptr;
5627
5628 for (i = 0; i < O_LAST; i++) {
5630 "%s.cma_minimal_surplus,%d", citystr, i);
5632 "%s.cma_factor,%d", citystr, i);
5633 }
5634
5635 secfile_entry_ignore(loading->file, "%s.max_growth",
5636 citystr);
5637 secfile_entry_ignore(loading->file, "%s.require_happy",
5638 citystr);
5639 secfile_entry_ignore(loading->file, "%s.allow_disorder",
5640 citystr);
5641 secfile_entry_ignore(loading->file, "%s.allow_specialists",
5642 citystr);
5643 secfile_entry_ignore(loading->file, "%s.happy_factor",
5644 citystr);
5645 }
5646 }
5647
5648 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5649
5650 return TRUE;
5651}
5652
5653/************************************************************************/
5657 struct player *plr,
5658 struct city *pcity,
5659 const char *citystr)
5660{
5662 citizens size;
5663
5665 player_slots_iterate(pslot) {
5666 int nationality;
5667
5668 nationality = secfile_lookup_int_default(loading->file, -1,
5669 "%s.citizen%d", citystr,
5670 player_slot_index(pslot));
5671 if (nationality > 0 && !player_slot_is_used(pslot)) {
5672 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5674 continue;
5675 }
5676
5677 if (nationality != -1 && player_slot_is_used(pslot)) {
5678 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5679 "Invalid value for citizens of player %d in %s: %d.",
5680 player_slot_index(pslot), city_name_get(pcity), nationality);
5681 citizens_nation_set(pcity, pslot, nationality);
5682 }
5684 /* Sanity check. */
5686 if (size != city_size_get(pcity)) {
5687 if (size != 0) {
5688 /* size == 0 can be result from the fact that ruleset had no
5689 * nationality enabled at saving time, so no citizens at all
5690 * were saved. But something more serious must be going on if
5691 * citizens have been saved partially - if some of them are there. */
5692 log_sg("City size and number of citizens does not match in %s "
5693 "(%d != %d)! Repairing ...", city_name_get(pcity),
5695 }
5696 citizens_update(pcity, nullptr);
5697 }
5698 }
5699}
5700
5701/************************************************************************/
5705 struct player *plr)
5706{
5708 int i = 0;
5709 int plrno = player_number(plr);
5711
5712 /* Check status and return if not OK (sg_success FALSE). */
5713 sg_check_ret();
5714
5716 "player%d.ncities", plrno);
5717
5719 /* Initialise the nation list for the citizens information. */
5720 player_slots_iterate(pslot) {
5723 }
5724
5725 /* First determine length of longest worklist, rally point order, and the
5726 * nationalities we have. */
5728 int routes;
5729
5730 /* Check the sanity of the city. */
5733
5734 if (pcity->worklist.length > wlist_max_length) {
5735 wlist_max_length = pcity->worklist.length;
5736 }
5737
5738 if (pcity->rally_point.length > rally_point_max_length) {
5739 rally_point_max_length = pcity->rally_point.length;
5740 }
5741
5742 routes = city_num_trade_routes(pcity);
5743 if (routes > routes_max) {
5744 routes_max = routes;
5745 }
5746
5748 /* Find all nations of the citizens,*/
5749 players_iterate(pplayer) {
5750 if (!nations[player_index(pplayer)]
5751 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5752 nations[player_index(pplayer)] = TRUE;
5753 }
5755 }
5757
5759 "player%d.wl_max_length", plrno);
5761 "player%d.routes_max_length", plrno);
5762
5764 struct tile *pcenter = city_tile(pcity);
5765 char impr_buf[B_LAST + 1];
5766 char buf[32];
5767 int j, nat_x, nat_y;
5768
5769 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5770
5771
5773 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5774 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5775
5776 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5777
5778 if (pcity->original != nullptr) {
5779 secfile_insert_int(saving->file, player_number(pcity->original),
5780 "%s.original", buf);
5781 } else {
5782 secfile_insert_int(saving->file, -1, "%s.original", buf);
5783 }
5784 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5785
5787 "%s.capital", buf);
5788
5789 j = 0;
5791 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5792 buf, j++);
5794
5795 j = 0;
5797 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5798 buf, j);
5800 "%s.route_direction%d", buf, j);
5802 "%s.route_good%d", buf, j);
5803 j++;
5805
5806 /* Save dummy values to keep tabular format happy */
5807 for (; j < routes_max; j++) {
5808 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5810 "%s.route_direction%d", buf, j);
5812 "%s.route_good%d", buf, j);
5813 }
5814
5815 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5816 buf);
5817 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5818 buf);
5819 secfile_insert_int(saving->file, pcity->history, "%s.history",
5820 buf);
5821
5822 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5823 buf);
5824 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5825 buf);
5826 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5827 buf);
5828 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5829 buf);
5830
5831 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5832 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5833 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5834 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5835 buf);
5836 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5837 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5838 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5839 secfile_insert_int(saving->file, pcity->turn_last_built,
5840 "%s.turn_last_built", buf);
5841
5842 /* For visual debugging, variable length strings together here */
5843 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5844
5846 "%s.currently_building_kind", buf);
5848 "%s.currently_building_name", buf);
5849
5850 if (pcity->production.kind == VUT_IMPROVEMENT) {
5852 pcity->server.adv->
5853 building_want[improvement_index(pcity->production.value.building)],
5854 "%s.current_want", buf);
5855 } else {
5856 secfile_insert_int(saving->file, 0,
5857 "%s.current_want", buf);
5858 }
5859
5861 "%s.changed_from_kind", buf);
5863 "%s.changed_from_name", buf);
5864
5865 secfile_insert_int(saving->file, pcity->before_change_shields,
5866 "%s.before_change_shields", buf);
5867 secfile_insert_int(saving->file, pcity->caravan_shields,
5868 "%s.caravan_shields", buf);
5869 secfile_insert_int(saving->file, pcity->disbanded_shields,
5870 "%s.disbanded_shields", buf);
5871 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5872 "%s.last_turns_shield_surplus", buf);
5873
5875 "%s.style", buf);
5876
5877 /* Save the squared city radius and all tiles within the corresponding
5878 * city map. */
5879 secfile_insert_int(saving->file, pcity->city_radius_sq,
5880 "player%d.c%d.city_radius_sq", plrno, i);
5881 /* The tiles worked by the city are saved using the main map.
5882 * See also sg_save_map_worked(). */
5883
5884 /* Save improvement list as bytevector. Note that improvement order
5885 * is saved in savefile.improvement_order. */
5886 improvement_iterate(pimprove) {
5887 impr_buf[improvement_index(pimprove)]
5888 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5889 : '1';
5891 impr_buf[improvement_count()] = '\0';
5892
5894 "Invalid size of the improvement vector (%s.improvements: "
5895 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5896 strlen(impr_buf), sizeof(impr_buf));
5897 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5898
5899 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5900 buf);
5901
5902 for (j = 0; j < CITYO_LAST; j++) {
5903 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5904 "%s.option%d", buf, j);
5905 }
5906 secfile_insert_int(saving->file, pcity->wlcb,
5907 "%s.wlcb", buf);
5908
5909 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5910
5912 /* Save nationality of the citizens,*/
5913 players_iterate(pplayer) {
5914 if (nations[player_index(pplayer)]) {
5916 citizens_nation_get(pcity, pplayer->slot),
5917 "%s.citizen%d", buf, player_index(pplayer));
5918 }
5920 }
5921
5922 secfile_insert_int(saving->file, pcity->rally_point.length,
5923 "%s.rally_point_length", buf);
5924 if (pcity->rally_point.length) {
5925 int len = pcity->rally_point.length;
5926 char orders[len + 1], dirs[len + 1], activities[len + 1];
5927 int actions[len];
5928 int targets[len];
5929 int sub_targets[len];
5930
5931 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5932 "%s.rally_point_persistent", buf);
5933 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5934 "%s.rally_point_vigilant", buf);
5935
5936 for (j = 0; j < len; j++) {
5937 orders[j] = order2char(pcity->rally_point.orders[j].order);
5938 dirs[j] = '?';
5939 activities[j] = '?';
5940 targets[j] = NO_TARGET;
5941 sub_targets[j] = NO_TARGET;
5942 actions[j] = -1;
5943 switch (pcity->rally_point.orders[j].order) {
5944 case ORDER_MOVE:
5945 case ORDER_ACTION_MOVE:
5946 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5947 break;
5948 case ORDER_ACTIVITY:
5949 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5950 activities[j]
5951 = activity2char(pcity->rally_point.orders[j].activity);
5952 actions[j]
5953 = pcity->rally_point.orders[j].action;
5954 break;
5956 actions[j] = pcity->rally_point.orders[j].action;
5957 targets[j] = pcity->rally_point.orders[j].target;
5958 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5959 break;
5960 case ORDER_FULL_MP:
5961 case ORDER_LAST:
5962 break;
5963 }
5964
5965 if (actions[j] == ACTION_NONE) {
5966 actions[j] = -1;
5967 }
5968 }
5969 orders[len] = dirs[len] = activities[len] = '\0';
5970
5971 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5972 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5973 secfile_insert_str(saving->file, activities,
5974 "%s.rally_point_activities", buf);
5975
5977 "%s.rally_point_action_vec", buf);
5978 /* Fill in dummy values for order targets so the registry will save
5979 * the unit table in a tabular format. */
5980 for (j = len; j < rally_point_max_length; j++) {
5981 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5982 buf, j);
5983 }
5984
5985 secfile_insert_int_vec(saving->file, targets, len,
5986 "%s.rally_point_tgt_vec", buf);
5987 /* Fill in dummy values for order targets so the registry will save
5988 * the unit table in a tabular format. */
5989 for (j = len; j < rally_point_max_length; j++) {
5991 "%s.rally_point_tgt_vec,%d", buf, j);
5992 }
5993
5994 secfile_insert_int_vec(saving->file, sub_targets, len,
5995 "%s.rally_point_sub_tgt_vec", buf);
5996 /* Fill in dummy values for order targets so the registry will save
5997 * the unit table in a tabular format. */
5998 for (j = len; j < rally_point_max_length; j++) {
5999 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
6000 buf, j);
6001 }
6002 } else {
6003 /* Put all the same fields into the savegame - otherwise the
6004 * registry code can't correctly use a tabular format and the
6005 * savegame will be bigger. */
6006 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
6007 buf);
6008 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
6009 buf);
6010 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
6011 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
6012 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
6013 buf);
6014
6015 /* Fill in dummy values for order targets so the registry will save
6016 * the unit table in a tabular format. */
6017
6018 /* The start of a vector has no number. */
6019 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
6020 buf);
6021 for (j = 1; j < rally_point_max_length; j++) {
6022 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
6023 buf, j);
6024 }
6025
6026 /* The start of a vector has no number. */
6027 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
6028 buf);
6029 for (j = 1; j < rally_point_max_length; j++) {
6031 "%s.rally_point_tgt_vec,%d", buf, j);
6032 }
6033
6034 /* The start of a vector has no number. */
6035 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
6036 buf);
6037 for (j = 1; j < rally_point_max_length; j++) {
6038 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
6039 buf, j);
6040 }
6041 }
6042
6043 secfile_insert_bool(saving->file, pcity->cm_parameter != nullptr,
6044 "%s.cma_enabled", buf);
6045 if (pcity->cm_parameter) {
6047 pcity->cm_parameter->minimal_surplus, O_LAST,
6048 "%s.cma_minimal_surplus", buf);
6050 pcity->cm_parameter->factor, O_LAST,
6051 "%s.cma_factor", buf);
6052 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6053 "%s.max_growth", buf);
6054 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6055 "%s.require_happy", buf);
6056 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6057 "%s.allow_disorder", buf);
6059 pcity->cm_parameter->allow_specialists,
6060 "%s.allow_specialists", buf);
6061 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6062 "%s.happy_factor", buf);
6063 } else {
6064 int zeros[O_LAST];
6065
6066 memset(zeros, 0, sizeof(zeros));
6068 "%s.cma_minimal_surplus", buf);
6070 "%s.cma_factor", buf);
6071 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6072 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6073 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6074 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6075 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6076 }
6077
6078 i++;
6080
6081 i = 0;
6083 worker_task_list_iterate(pcity->task_reqs, ptask) {
6084 int nat_x, nat_y;
6085
6087 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6088 plrno, i);
6089 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6090 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6092 "player%d.task%d.activity",
6093 plrno, i);
6094 if (ptask->tgt != nullptr) {
6096 "player%d.task%d.target",
6097 plrno, i);
6098 } else {
6099 secfile_insert_str(saving->file, "-",
6100 "player%d.task%d.target",
6101 plrno, i);
6102 }
6103 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6104
6105 i++;
6108}
6109
6110/************************************************************************/
6114 struct player *plr)
6115{
6116 int nunits, i, plrno = player_number(plr);
6117 size_t orders_max_length;
6118
6119 /* Check status and return if not OK (sg_success FALSE). */
6120 sg_check_ret();
6121
6123 "player%d.nunits", plrno),
6124 "%s", secfile_error());
6125 if (!plr->is_alive && nunits > 0) {
6126 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6127 nunits = 0; /* Some old savegames may be buggy. */
6128 }
6129
6131 "player%d.orders_max_length",
6132 plrno);
6133
6134 for (i = 0; i < nunits; i++) {
6135 struct unit *punit;
6136 struct city *pcity;
6137 const char *name;
6138 char buf[32];
6139 struct unit_type *type;
6140 struct tile *ptile;
6141
6142 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6143
6144 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6146 sg_failure_ret(type != nullptr, "%s: unknown unit type \"%s\".", buf, name);
6147
6148 /* Create a dummy unit. */
6149 punit = unit_virtual_create(plr, nullptr, type, 0);
6152 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6153 }
6154
6157
6159 unit_list_prepend(pcity->units_supported, punit);
6160 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6161 log_sg("%s: bad home city %d.", buf, punit->homecity);
6163 }
6164
6165 ptile = unit_tile(punit);
6166
6167 /* allocate the unit's contribution to fog of war */
6170 /* NOTE: There used to be some map_set_known calls here. These were
6171 * unneeded since unfogging the tile when the unit sees it will
6172 * automatically reveal that tile. */
6173
6176 }
6177}
6178
6179/************************************************************************/
6183 struct player *plr, struct unit *punit,
6185 const char *unitstr)
6186{
6187 enum unit_activity activity;
6188 int nat_x, nat_y;
6189 struct extra_type *pextra = nullptr;
6190 struct tile *ptile;
6191 int extra_id;
6192 int ei;
6193 const char *facing_str;
6194 int natnbr;
6195 int unconverted;
6196 const char *str;
6197 enum gen_action action;
6198
6200 unitstr), FALSE, "%s", secfile_error());
6202 FALSE, "%s", secfile_error());
6204 FALSE, "%s", secfile_error());
6205
6206 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6207 sg_warn_ret_val(ptile != nullptr, FALSE, "%s invalid tile (%d, %d)",
6208 unitstr, nat_x, nat_y);
6209 unit_tile_set(punit, ptile);
6210
6213 "%s.facing", unitstr);
6214 if (facing_str[0] != 'x') {
6215 /* We don't touch punit->facing if savegame does not contain that
6216 * information. Initial orientation set by unit_virtual_create()
6217 * is as good as any. */
6218 enum direction8 facing = char2dir(facing_str[0]);
6219
6220 if (direction8_is_valid(facing)) {
6221 punit->facing = facing;
6222 } else {
6223 log_error("Illegal unit orientation '%s'", facing_str);
6224 }
6225 }
6226
6227 /* If savegame has unit nationality, it doesn't hurt to
6228 * internally set it even if nationality rules are disabled. */
6230 player_number(plr),
6231 "%s.nationality", unitstr);
6232
6234 if (punit->nationality == nullptr) {
6235 punit->nationality = plr;
6236 }
6237
6239 "%s.homecity", unitstr), FALSE,
6240 "%s", secfile_error());
6242 "%s.moves", unitstr), FALSE,
6243 "%s", secfile_error());
6245 "%s.fuel", unitstr), FALSE,
6246 "%s", secfile_error());
6247
6249 "%s.activity", unitstr), FALSE,
6250 "%s", secfile_error());
6251 if (ei >= 0 && ei < loading->activities.size) {
6252 activity = unit_activity_by_name(loading->activities.order[ei],
6254 } else {
6255 log_sg("Invalid activity id for unit %d", punit->id);
6256 activity = ACTIVITY_IDLE;
6257 }
6258
6260 "%s.action", unitstr), FALSE,
6261 "%s", secfile_error());
6262 if (ei == -1) {
6264 } else if (ei >= 0 && ei < loading->action.size) {
6265 action = loading->action.order[ei];
6266 } else {
6267 log_sg("Invalid action id for unit %d", punit->id);
6269 }
6270
6273 "%s.born", unitstr);
6276 "%s.current_form_turn", unitstr);
6277
6279 "%s.activity_tgt", unitstr);
6280
6281 if (extra_id != -2) {
6282 if (extra_id >= 0 && extra_id < loading->extra.size) {
6283 pextra = loading->extra.order[extra_id];
6284 set_unit_activity_targeted(punit, activity, pextra, action);
6285 } else if (activity == ACTIVITY_IRRIGATE) {
6289 punit);
6290 if (tgt != nullptr) {
6292 } else {
6294 }
6295 } else if (activity == ACTIVITY_MINE) {
6297 EC_MINE,
6299 punit);
6300 if (tgt != nullptr) {
6302 } else {
6304 }
6305 } else {
6306 set_unit_activity(punit, activity, action);
6307 }
6308 } else {
6309 set_unit_activity_targeted(punit, activity, nullptr, action);
6310 } /* activity_tgt == nullptr */
6311
6313 "%s.activity_count", unitstr), FALSE,
6314 "%s", secfile_error());
6315
6318 "%s.changed_from", unitstr);
6319
6321 "%s.changed_from_tgt", unitstr), FALSE,
6322 "%s", secfile_error());
6323
6324 if (extra_id >= 0 && extra_id < loading->extra.size) {
6325 punit->changed_from_target = loading->extra.order[extra_id];
6326 } else {
6327 punit->changed_from_target = nullptr;
6328 }
6329
6332 "%s.changed_from_count", unitstr);
6333
6334 /* Special case: for a long time, we accidentally incremented
6335 * activity_count while a unit was sentried, so it could increase
6336 * without bound (bug #20641) and be saved in old savefiles.
6337 * We zero it to prevent potential trouble overflowing the range
6338 * in network packets, etc. */
6339 if (activity == ACTIVITY_SENTRY) {
6340 punit->activity_count = 0;
6341 }
6344 }
6345
6346 punit->veteran
6347 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6348 {
6349 /* Protect against change in veteran system in ruleset */
6350 const int levels = utype_veteran_levels(unit_type_get(punit));
6351
6352 if (punit->veteran >= levels) {
6353 fc_assert(levels >= 1);
6354 punit->veteran = levels - 1;
6355 }
6356 }
6359 "%s.done_moving", unitstr);
6362 "%s.battlegroup", unitstr);
6363
6365 "%s.go", unitstr)) {
6366 int gnat_x, gnat_y;
6367
6369 "%s.goto_x", unitstr), FALSE,
6370 "%s", secfile_error());
6372 "%s.goto_y", unitstr), FALSE,
6373 "%s", secfile_error());
6374
6376 } else {
6377 punit->goto_tile = nullptr;
6378
6379 if (punit->activity == ACTIVITY_GOTO) {
6380 /* goto_tile should never be nullptr with ACTIVITY_GOTO */
6381 sg_regr(3020200, "Unit %d on goto without goto_tile. Aborting goto.",
6382 punit->id);
6384 }
6385
6386 /* These variables are not used but needed for saving the unit table.
6387 * Load them to prevent unused variables errors. */
6388 secfile_entry_ignore(loading->file, "%s.goto_x", unitstr);
6389 secfile_entry_ignore(loading->file, "%s.goto_y", unitstr);
6390 }
6391
6392 /* Load AI data of the unit. */
6393 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6394
6397 "%s.server_side_agent",
6398 unitstr);
6399 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6400 /* Look up what server side agent the unconverted number represents. */
6401 punit->ssa_controller = loading->ssa.order[unconverted];
6402 } else {
6403 log_sg("Invalid server side agent %d for unit %d",
6404 unconverted, punit->id);
6405
6407 }
6408
6410 "%s.hp", unitstr), FALSE,
6411 "%s", secfile_error());
6412
6414 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6416 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6417 punit->moved
6418 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6421 "%s.paradropped", unitstr);
6422 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6423 if (str[0] != '\0') {
6425 }
6426
6427 /* The transport status (punit->transported_by) is loaded in
6428 * sg_player_units_transport(). */
6429
6430 /* Initialize upkeep values: these are hopefully initialized
6431 * elsewhere before use (specifically, in city_support(); but
6432 * fixme: check whether always correctly initialized?).
6433 * Below is mainly for units which don't have homecity --
6434 * otherwise these don't get initialized (and AI calculations
6435 * etc may use junk values). */
6439
6441 "%s.action_decision", unitstr),
6442 FALSE, "%s", secfile_error());
6443
6444 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6445 /* Look up what action decision want the unconverted number
6446 * represents. */
6447 punit->action_decision_want = loading->act_dec.order[unconverted];
6448 } else {
6449 log_sg("Invalid action decision want for unit %d", punit->id);
6450
6452 }
6453
6455 /* Load the tile to act against. */
6456 int adwt_x, adwt_y;
6457
6458 if (secfile_lookup_int(loading->file, &adwt_x,
6459 "%s.action_decision_tile_x", unitstr)
6461 "%s.action_decision_tile_y", unitstr)) {
6463 adwt_x, adwt_y);
6464 } else {
6466 punit->action_decision_tile = nullptr;
6467 log_sg("Bad action_decision_tile for unit %d", punit->id);
6468 }
6469 } else {
6470 secfile_entry_ignore(loading->file, "%s.action_decision_tile_x", unitstr);
6471 secfile_entry_ignore(loading->file, "%s.action_decision_tile_y", unitstr);
6472
6473 punit->action_decision_tile = nullptr;
6474 }
6475
6477
6478 /* Load the unit orders */
6479 {
6480 int len = secfile_lookup_int_default(loading->file, 0,
6481 "%s.orders_length", unitstr);
6482
6483 if (len > 0) {
6484 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6485 int j;
6486
6487 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6491 "%s.orders_index", unitstr);
6494 "%s.orders_repeat", unitstr);
6497 "%s.orders_vigilant", unitstr);
6498
6501 "%s.orders_list", unitstr);
6504 "%s.dir_list", unitstr);
6507 "%s.activity_list", unitstr);
6508
6510
6511 for (j = 0; j < len; j++) {
6512 struct unit_order *order = &punit->orders.list[j];
6514 int order_sub_tgt;
6515
6516 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6517 || act_unitstr[j] == '\0') {
6518 log_sg("Invalid unit orders.");
6520 break;
6521 }
6522 order->order = char2order(orders_unitstr[j]);
6523 order->dir = char2dir(dir_unitstr[j]);
6524 order->activity = char2activity(act_unitstr[j]);
6525
6527 "%s.action_vec,%d",
6528 unitstr, j);
6529
6530 if (unconverted == -1) {
6531 order->action = ACTION_NONE;
6532 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6533 /* Look up what action id the unconverted number represents. */
6534 order->action = loading->action.order[unconverted];
6535 } else {
6536 if (order->order == ORDER_PERFORM_ACTION) {
6537 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6538 }
6539
6540 order->action = ACTION_NONE;
6541 }
6542
6543 if (order->order == ORDER_LAST
6544 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6545 || (order->order == ORDER_ACTION_MOVE
6546 && !direction8_is_valid(order->dir))
6547 || (order->order == ORDER_PERFORM_ACTION
6548 && !action_id_exists(order->action))
6549 || (order->order == ORDER_ACTIVITY
6550 && (order->activity == ACTIVITY_LAST
6551 || !action_id_exists(order->action)))) {
6552 /* An invalid order. Just drop the orders for this unit. */
6554 punit->orders.list = nullptr;
6555 punit->orders.length = 0;
6557 punit->goto_tile = nullptr;
6558 break;
6559 }
6560
6562 "%s.tgt_vec,%d",
6563 unitstr, j);
6565 "%s.sub_tgt_vec,%d",
6566 unitstr, j);
6567
6568 if (order->order == ORDER_PERFORM_ACTION) {
6569 /* Validate sub target */
6570 switch (action_id_get_sub_target_kind(order->action)) {
6571 case ASTK_BUILDING:
6572 /* Sub target is a building. */
6573 if (order_sub_tgt < 0
6574 || order_sub_tgt >= loading->improvement.size
6575 || !loading->improvement.order[order_sub_tgt]) {
6576 /* Sub target is invalid. */
6577 log_sg("Cannot find building %d for %s to %s",
6580 order->sub_target = B_LAST;
6581 } else {
6582 struct impr_type *pimprove
6583 = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
6584
6585 if (pimprove != nullptr) {
6586 order->sub_target = improvement_index(pimprove);
6587 }
6588 }
6589 break;
6590 case ASTK_TECH:
6591 /* Sub target is a technology. */
6592 {
6593 bool failure = order_sub_tgt < 0
6594 || order_sub_tgt >= loading->technology.size
6595 || !loading->technology.order[order_sub_tgt];
6596 struct advance *padvance = nullptr;
6597
6598 if (!failure) {
6599 padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
6600 }
6601 if (padvance == nullptr) {
6602 /* Target tech is invalid. */
6603 log_sg("Cannot find tech %d for %s to steal",
6605 order->sub_target = A_NONE;
6606 } else {
6608 }
6609 }
6610 break;
6611 case ASTK_EXTRA:
6613 /* These take an extra. */
6615 break;
6616 case ASTK_SPECIALIST:
6617 /* A valid specialist must be supplied. */
6618 if (order_sub_tgt < 0
6619 || order_sub_tgt >= loading->specialist.size
6620 || !loading->specialist.order[order_sub_tgt]) {
6621 log_sg("Cannot find specialist %d for %s to become",
6623 order->sub_target = NO_TARGET;
6624 } else {
6625 order->sub_target = specialist_index(loading->specialist.order[order_sub_tgt]);
6626 }
6627 break;
6628 case ASTK_NONE:
6629 /* None of these can take a sub target. */
6631 "Specified sub target for action %d unsupported.",
6632 order->action);
6633 order->sub_target = NO_TARGET;
6634 break;
6635 case ASTK_COUNT:
6637 "Bad action action %d.",
6638 order->action);
6639 order->sub_target = NO_TARGET;
6640 break;
6641 }
6642 }
6643
6644 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6645 enum unit_activity act;
6646
6648 || !loading->extra.order[order_sub_tgt]) {
6649 if (order_sub_tgt != EXTRA_NONE) {
6650 log_sg("Cannot find extra %d for %s to build",
6652 }
6653
6654 order->sub_target = EXTRA_NONE;
6655 } else {
6656 order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
6657 }
6658
6659 /* An action or an activity may require an extra target. */
6660 if (action_wants_extra) {
6661 act = action_id_get_activity(order->action);
6662 } else {
6663 act = order->activity;
6664 }
6665
6666 if (unit_activity_is_valid(act)
6668 && order->sub_target == EXTRA_NONE) {
6669 /* Missing required action extra target. */
6671 punit->orders.list = nullptr;
6672 punit->orders.length = 0;
6674 punit->goto_tile = nullptr;
6675 break;
6676 }
6677 } else if (order->order != ORDER_PERFORM_ACTION) {
6678 if (order_sub_tgt != -1) {
6679 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6680 order_sub_tgt, -1, order->order);
6681 }
6682 order->sub_target = NO_TARGET;
6683 }
6684 }
6685
6686 for (; j < orders_max_length; j++) {
6688 "%s.action_vec,%d", unitstr, j);
6690 "%s.tgt_vec,%d", unitstr, j);
6692 "%s.sub_tgt_vec,%d", unitstr, j);
6693 }
6694 } else {
6695 int j;
6696
6698
6699 /* Never nullify goto_tile for a unit that is in active goto. */
6700 if (punit->activity != ACTIVITY_GOTO) {
6701 punit->goto_tile = nullptr;
6702 }
6703
6704 punit->orders.list = nullptr;
6705 punit->orders.length = 0;
6706
6707 secfile_entry_ignore(loading->file, "%s.orders_index", unitstr);
6708 secfile_entry_ignore(loading->file, "%s.orders_repeat", unitstr);
6709 secfile_entry_ignore(loading->file, "%s.orders_vigilant", unitstr);
6710 secfile_entry_ignore(loading->file, "%s.orders_list", unitstr);
6711 secfile_entry_ignore(loading->file, "%s.dir_list", unitstr);
6712 secfile_entry_ignore(loading->file, "%s.activity_list", unitstr);
6713 secfile_entry_ignore(loading->file, "%s.action_vec", unitstr);
6714 secfile_entry_ignore(loading->file, "%s.tgt_vec", unitstr);
6715 secfile_entry_ignore(loading->file, "%s.sub_tgt_vec", unitstr);
6716
6717 for (j = 1; j < orders_max_length; j++) {
6719 "%s.action_vec,%d", unitstr, j);
6721 "%s.tgt_vec,%d", unitstr, j);
6723 "%s.sub_tgt_vec,%d", unitstr, j);
6724 }
6725 }
6726 }
6727
6728 return TRUE;
6729}
6730
6731/************************************************************************/
6736 struct player *plr)
6737{
6738 int nunits, i, plrno = player_number(plr);
6739
6740 /* Check status and return if not OK (sg_success FALSE). */
6741 sg_check_ret();
6742
6743 /* Recheck the number of units for the player. This is a copied from
6744 * sg_load_player_units(). */
6746 "player%d.nunits", plrno),
6747 "%s", secfile_error());
6748 if (!plr->is_alive && nunits > 0) {
6749 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6750 nunits = 0; /* Some old savegames may be buggy. */
6751 }
6752
6753 for (i = 0; i < nunits; i++) {
6754 int id_unit, id_trans;
6755 struct unit *punit, *ptrans;
6756
6758 "player%d.u%d.id",
6759 plrno, i);
6761 fc_assert_action(punit != nullptr, continue);
6762
6764 "player%d.u%d.transported_by",
6765 plrno, i);
6766 if (id_trans == -1) {
6767 /* Not transported. */
6768 continue;
6769 }
6770
6772 fc_assert_action(id_trans == -1 || ptrans != nullptr, continue);
6773
6774 if (ptrans) {
6775#ifndef FREECIV_NDEBUG
6776 bool load_success =
6777#endif
6779
6780 fc_assert_action(load_success, continue);
6781 }
6782 }
6783}
6784
6785/************************************************************************/
6789 struct player *plr)
6790{
6791 int i = 0;
6792 int longest_order = 0;
6793 int plrno = player_number(plr);
6794
6795 /* Check status and return if not OK (sg_success FALSE). */
6796 sg_check_ret();
6797
6799 "player%d.nunits", plrno);
6800
6801 /* Find the longest unit order so different order length won't break
6802 * storing units in the tabular format. */
6804 if (punit->has_orders) {
6805 if (longest_order < punit->orders.length) {
6807 }
6808 }
6810
6812 "player%d.orders_max_length", plrno);
6813
6815 char buf[32];
6816 char dirbuf[2] = " ";
6817 int nat_x, nat_y;
6818 int last_order, j;
6819
6820 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6821 dirbuf[0] = dir2char(punit->facing);
6822 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6823
6825 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6826 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6827
6828 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6831 "%s.nationality", buf);
6832 }
6833 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6834 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6835 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6837 "%s.type_by_name", buf);
6838
6839 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6841 "%s.activity_count", buf);
6842 if (punit->action == ACTION_NONE) {
6843 secfile_insert_int(saving->file, -1, "%s.action", buf);
6844 } else {
6845 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6846 }
6847 if (punit->activity_target == nullptr) {
6848 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6849 } else {
6851 "%s.activity_tgt", buf);
6852 }
6853
6855 "%s.changed_from", buf);
6857 "%s.changed_from_count", buf);
6858 if (punit->changed_from_target == nullptr) {
6859 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6860 } else {
6862 "%s.changed_from_tgt", buf);
6863 }
6864
6866 "%s.done_moving", buf);
6867 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6868 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6870 "%s.born", buf);
6872 "%s.current_form_turn", buf);
6874 "%s.battlegroup", buf);
6875
6876 if (punit->goto_tile) {
6878 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6879 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6880 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6881 } else {
6882 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6883 /* Set this values to allow saving it as table. */
6884 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6885 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6886 }
6887
6889 "%s.server_side_agent", buf);
6890
6891 /* Save AI data of the unit. */
6892 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6893
6895 "%s.ord_map", buf);
6897 "%s.ord_city", buf);
6898 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6900 "%s.paradropped", buf);
6902 ? unit_transport_get(punit)->id : -1,
6903 "%s.transported_by", buf);
6904 if (punit->carrying != nullptr) {
6906 "%s.carrying", buf);
6907 } else {
6908 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6909 }
6910
6912 "%s.action_decision", buf);
6913
6914 /* Stored as tile rather than direction to make sure the target tile is
6915 * sane. */
6920 "%s.action_decision_tile_x", buf);
6922 "%s.action_decision_tile_y", buf);
6923 } else {
6924 /* Dummy values to get tabular format. */
6925 secfile_insert_int(saving->file, -1,
6926 "%s.action_decision_tile_x", buf);
6927 secfile_insert_int(saving->file, -1,
6928 "%s.action_decision_tile_y", buf);
6929 }
6930
6932 "%s.stay", buf);
6933
6934 if (punit->has_orders) {
6935 int len = punit->orders.length;
6936 char orders_buf[len + 1], dir_buf[len + 1];
6937 char act_buf[len + 1];
6938 int action_buf[len];
6939 int tgt_vec[len];
6940 int sub_tgt_vec[len];
6941
6942 last_order = len;
6943
6944 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6946 "%s.orders_index", buf);
6948 "%s.orders_repeat", buf);
6950 "%s.orders_vigilant", buf);
6951
6952 for (j = 0; j < len; j++) {
6954 dir_buf[j] = '?';
6955 act_buf[j] = '?';
6956 tgt_vec[j] = NO_TARGET;
6957 sub_tgt_vec[j] = -1;
6958 action_buf[j] = -1;
6959 switch (punit->orders.list[j].order) {
6960 case ORDER_MOVE:
6961 case ORDER_ACTION_MOVE:
6962 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6963 break;
6964 case ORDER_ACTIVITY:
6968 break;
6971 tgt_vec[j] = punit->orders.list[j].target;
6973 break;
6974 case ORDER_FULL_MP:
6975 case ORDER_LAST:
6976 break;
6977 }
6978
6979 if (action_buf[j] == ACTION_NONE) {
6980 action_buf[j] = -1;
6981 }
6982 }
6983 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6984
6985 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6986 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6987 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6988
6990 "%s.action_vec", buf);
6991 /* Fill in dummy values for order targets so the registry will save
6992 * the unit table in a tabular format. */
6993 for (j = last_order; j < longest_order; j++) {
6994 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6995 }
6996
6998 "%s.tgt_vec", buf);
6999 /* Fill in dummy values for order targets so the registry will save
7000 * the unit table in a tabular format. */
7001 for (j = last_order; j < longest_order; j++) {
7002 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
7003 }
7004
7006 "%s.sub_tgt_vec", buf);
7007 /* Fill in dummy values for order targets so the registry will save
7008 * the unit table in a tabular format. */
7009 for (j = last_order; j < longest_order; j++) {
7010 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
7011 }
7012 } else {
7013
7014 /* Put all the same fields into the savegame - otherwise the
7015 * registry code can't correctly use a tabular format and the
7016 * savegame will be bigger. */
7017 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
7018 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
7019 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
7020 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
7021 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
7022 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
7023 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
7024
7025 /* Fill in dummy values for order targets so the registry will save
7026 * the unit table in a tabular format. */
7027
7028 /* The start of a vector has no number. */
7029 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
7030 for (j = 1; j < longest_order; j++) {
7031 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
7032 }
7033
7034 /* The start of a vector has no number. */
7035 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
7036 for (j = 1; j < longest_order; j++) {
7037 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
7038 }
7039
7040 /* The start of a vector has no number. */
7041 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
7042 for (j = 1; j < longest_order; j++) {
7043 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
7044 }
7045 }
7046
7047 i++;
7049}
7050
7051/************************************************************************/
7055 struct player *plr)
7056{
7057 int plrno = player_number(plr);
7058
7059 /* Check status and return if not OK (sg_success FALSE). */
7060 sg_check_ret();
7061
7062 /* Toss any existing attribute_block (should not exist) */
7063 if (plr->attribute_block.data) {
7065 plr->attribute_block.data = nullptr;
7066 }
7067
7068 /* This is a big heap of opaque data for the client, check everything! */
7070 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
7071
7072 if (0 > plr->attribute_block.length) {
7073 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
7074 plr->attribute_block.length);
7075 plr->attribute_block.length = 0;
7076 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
7077 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
7079 plr->attribute_block.length = 0;
7080 } else if (0 < plr->attribute_block.length) {
7081 int part_nr, parts;
7082 int quoted_length;
7083 char *quoted;
7084#ifndef FREECIV_NDEBUG
7085 size_t actual_length;
7086#endif
7087
7090 "player%d.attribute_v2_block_length_quoted",
7091 plrno), "%s", secfile_error());
7094 "player%d.attribute_v2_block_parts", plrno),
7095 "%s", secfile_error());
7096
7098 quoted[0] = '\0';
7100 for (part_nr = 0; part_nr < parts; part_nr++) {
7101 const char *current =
7103 "player%d.attribute_v2_block_data.part%d",
7104 plrno, part_nr);
7105 if (!current) {
7106 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7107 break;
7108 }
7109 log_debug("attribute_v2_block_length_quoted=%d"
7110 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7111 quoted_length, strlen(quoted), strlen(current));
7112 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7113 strcat(quoted, current);
7114 }
7116 "attribute_v2_block_length_quoted=%d"
7117 " actual=" SIZE_T_PRINTF,
7119
7120#ifndef FREECIV_NDEBUG
7122#endif
7124 plr->attribute_block.data,
7125 plr->attribute_block.length);
7127 free(quoted);
7128 }
7129}
7130
7131/************************************************************************/
7135 struct player *plr)
7136{
7137 int plrno = player_number(plr);
7138
7139 /* Check status and return if not OK (sg_success FALSE). */
7140 sg_check_ret();
7141
7142 /* This is a big heap of opaque data from the client. Although the binary
7143 * format is not user editable, keep the lines short enough for debugging,
7144 * and hope that data compression will keep the file a reasonable size.
7145 * Note that the "quoted" format is a multiple of 3.
7146 */
7147#define PART_SIZE (3*256)
7148#define PART_ADJUST (3)
7149 if (plr->attribute_block.data) {
7150 char part[PART_SIZE + PART_ADJUST];
7151 int parts;
7152 int current_part_nr;
7154 plr->attribute_block.length);
7155 char *quoted_at = strchr(quoted, ':');
7156 size_t bytes_left = strlen(quoted);
7157 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7159
7161 "player%d.attribute_v2_block_length", plrno);
7163 "player%d.attribute_v2_block_length_quoted", plrno);
7164
7165 /* Try to wring some compression efficiencies out of the "quoted" format.
7166 * The first line has a variable length decimal, mis-aligning triples.
7167 */
7168 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7169 /* first line can be longer */
7170 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7171 } else {
7172 parts = 1;
7173 }
7174
7176 "player%d.attribute_v2_block_parts", plrno);
7177
7178 if (parts > 1) {
7180
7181 /* first line can be longer */
7183 part[size_of_current_part] = '\0';
7185 "player%d.attribute_v2_block_data.part%d",
7186 plrno, 0);
7189 current_part_nr = 1;
7190 } else {
7191 quoted_at = quoted;
7192 current_part_nr = 0;
7193 }
7194
7197
7199 part[size_of_current_part] = '\0';
7201 "player%d.attribute_v2_block_data.part%d",
7202 plrno,
7206 }
7207 fc_assert(bytes_left == 0);
7208 free(quoted);
7209 }
7210#undef PART_ADJUST
7211#undef PART_SIZE
7212}
7213
7214/************************************************************************/
7218 struct player *plr)
7219{
7220 int plrno = player_number(plr);
7221 int total_ncities
7223 "player%d.dc_total", plrno);
7224 int i;
7225 bool someone_alive = FALSE;
7226
7227 /* Check status and return if not OK (sg_success FALSE). */
7228 sg_check_ret();
7229
7232 if (pteam_member->is_alive) {
7234 break;
7235 }
7237
7238 if (!someone_alive) {
7239 /* Reveal all for completely dead teams. */
7241 }
7242 }
7243
7244 if (-1 == total_ncities
7245 || !game.info.fogofwar
7247 "game.save_private_map")) {
7248 /* We have:
7249 * - a dead player;
7250 * - fogged cities are not saved for any reason;
7251 * - a savegame with fog of war turned off;
7252 * - or game.save_private_map is not set to FALSE in the scenario /
7253 * savegame. The players private knowledge is set to be what they could
7254 * see without fog of war. */
7255 whole_map_iterate(&(wld.map), ptile) {
7256 if (map_is_known(ptile, plr)) {
7257 struct city *pcity = tile_city(ptile);
7258
7259 update_player_tile_last_seen(plr, ptile);
7260 update_player_tile_knowledge(plr, ptile);
7261
7262 if (pcity != nullptr) {
7263 update_dumb_city(plr, pcity);
7264 }
7265 }
7267
7268 /* Nothing more to do; */
7269 return;
7270 }
7271
7272 /* Load player map (terrain). */
7273 LOAD_MAP_CHAR(ch, ptile,
7274 map_get_player_tile(ptile, plr)->terrain
7275 = char2terrain(ch), loading->file,
7276 "player%d.map_t%04d", plrno);
7277
7278 /* Load player map (extras). */
7279 halfbyte_iterate_extras(j, loading->extra.size) {
7280 LOAD_MAP_CHAR(ch, ptile,
7282 ch, loading->extra.order + 4 * j),
7283 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7285
7286 whole_map_iterate(&(wld.map), ptile) {
7287 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7288 bool regr_warn = FALSE;
7289
7291 int pres_id = extra_number(pres);
7292
7293 if (BV_ISSET(plrtile->extras, pres_id)) {
7294 if (plrtile->terrain == nullptr) {
7295 if (!regr_warn) {
7296 sg_regr(3030000, "FoW tile (%d, %d) has extras, though it's on unknown.",
7297 TILE_XY(ptile));
7298 regr_warn = TRUE;
7299 }
7300 BV_CLR(plrtile->extras, pres_id);
7301 } else {
7302 plrtile->resource = pres;
7303 if (!terrain_has_resource(plrtile->terrain, pres)) {
7304 BV_CLR(plrtile->extras, pres_id);
7305 }
7306 }
7307 }
7310
7312 /* Load player map (border). */
7313 int x, y;
7314
7315 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7316 const char *buffer
7317 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7318 plrno, y);
7319 const char *buffer2
7320 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7321 plrno, y);
7322 const char *ptr = buffer;
7323 const char *ptr2 = buffer2;
7324
7325 sg_failure_ret(buffer != nullptr,
7326 "Savegame corrupt - map line %d not found.", y);
7327 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7328 char token[TOKEN_SIZE];
7329 char token2[TOKEN_SIZE];
7330 int number;
7331 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7332
7333 scanin(&ptr, ",", token, sizeof(token));
7334 sg_failure_ret('\0' != token[0],
7335 "Savegame corrupt - map size not correct.");
7336 if (strcmp(token, "-") == 0) {
7337 map_get_player_tile(ptile, plr)->owner = nullptr;
7338 } else {
7339 sg_failure_ret(str_to_int(token, &number),
7340 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7341 token, x, y);
7342 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7343 }
7344
7345 scanin(&ptr2, ",", token2, sizeof(token2));
7346 sg_failure_ret('\0' != token2[0],
7347 "Savegame corrupt - map size not correct.");
7348 if (strcmp(token2, "-") == 0) {
7349 map_get_player_tile(ptile, plr)->extras_owner = nullptr;
7350 } else {
7352 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7353 token, x, y);
7354 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7355 }
7356 }
7357 }
7358 }
7359
7360 /* Load player map (update time). */
7361 for (i = 0; i < 4; i++) {
7362 /* put 4-bit segments of 16-bit "updated" field */
7363 if (i == 0) {
7364 LOAD_MAP_CHAR(ch, ptile,
7365 map_get_player_tile(ptile, plr)->last_updated
7366 = ascii_hex2bin(ch, i),
7367 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7368 } else {
7369 LOAD_MAP_CHAR(ch, ptile,
7370 map_get_player_tile(ptile, plr)->last_updated
7371 |= ascii_hex2bin(ch, i),
7372 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7373 }
7374 }
7375
7376 /* Load player map known cities. */
7377 for (i = 0; i < total_ncities; i++) {
7378 struct vision_site *pdcity;
7379 char buf[32];
7380 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7381
7382 pdcity = vision_site_new(0, nullptr, nullptr);
7385 pdcity);
7387 } else {
7388 /* Error loading the data. */
7389 log_sg("Skipping seen city %d for player %d.", i, plrno);
7390 if (pdcity != nullptr) {
7392 }
7393 }
7394 }
7395
7396 /* Repair inconsistent player maps. */
7397 whole_map_iterate(&(wld.map), ptile) {
7398 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7399 struct city *pcity = tile_city(ptile);
7400
7401 update_player_tile_knowledge(plr, ptile);
7402 reality_check_city(plr, ptile);
7403
7404 if (pcity != nullptr) {
7405 update_dumb_city(plr, pcity);
7406 }
7407 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7408 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7409 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7410
7411 plrtile->owner = tile_owner(ptile);
7412 }
7414}
7415
7416/************************************************************************/
7420 struct player *plr,
7421 struct vision_site *pdcity,
7422 const char *citystr)
7423{
7424 const char *str;
7425 int i, id, size;
7426 citizens city_size;
7427 int nat_x, nat_y;
7428 const char *stylename;
7429 enum capital_type cap;
7430 const char *vname;
7431
7433 citystr),
7434 FALSE, "%s", secfile_error());
7436 citystr),
7437 FALSE, "%s", secfile_error());
7438 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7439 sg_warn_ret_val(pdcity->location != nullptr, FALSE,
7440 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7441
7442 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7443 citystr),
7444 FALSE, "%s", secfile_error());
7445 pdcity->owner = player_by_number(id);
7446 sg_warn_ret_val(pdcity->owner != nullptr, FALSE,
7447 "%s has invalid owner (%d); skipping.", citystr, id);
7448
7449 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7450 citystr),
7451 FALSE, "%s", secfile_error());
7452 if (id >= 0) {
7453 pdcity->original = player_by_number(id);
7454 sg_warn_ret_val(pdcity->original != nullptr, FALSE,
7455 "%s has invalid original owner (%d); skipping.", citystr, id);
7456 } else {
7457 pdcity->original = nullptr;
7458 }
7459
7461 "%s.id", citystr),
7462 FALSE, "%s", secfile_error());
7464 "%s has invalid id (%d); skipping.", citystr, id);
7465
7467 "%s.size", citystr),
7468 FALSE, "%s", secfile_error());
7469 city_size = (citizens)size; /* set the correct type */
7470 sg_warn_ret_val(size == (int)city_size, FALSE,
7471 "Invalid city size: %d; set to %d.", size, city_size);
7472 vision_site_size_set(pdcity, city_size);
7473
7474 /* Initialise list of improvements */
7475 BV_CLR_ALL(pdcity->improvements);
7476 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7477 sg_warn_ret_val(str != nullptr, FALSE, "%s", secfile_error());
7478 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7479 "Invalid length of '%s.improvements' ("
7480 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7481 citystr, strlen(str), loading->improvement.size);
7482 for (i = 0; i < loading->improvement.size; i++) {
7483 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7484 "Undefined value '%c' within '%s.improvements'.",
7485 str[i], citystr)
7486
7487 if (str[i] == '1') {
7488 struct impr_type *pimprove =
7489 improvement_by_rule_name(loading->improvement.order[i]);
7490 if (pimprove) {
7491 BV_SET(pdcity->improvements, improvement_index(pimprove));
7492 }
7493 }
7494 }
7495
7496 vname = secfile_lookup_str_default(loading->file, nullptr,
7497 "%s.name", citystr);
7498
7499 if (vname != nullptr) {
7500 pdcity->name = fc_strdup(vname);
7501 }
7502
7504 "%s.occupied", citystr);
7506 "%s.walls", citystr);
7508 "%s.happy", citystr);
7510 "%s.unhappy", citystr);
7512 "%s.style", citystr);
7513 if (stylename != nullptr) {
7515 } else {
7516 pdcity->style = 0;
7517 }
7518 if (pdcity->style < 0) {
7519 pdcity->style = 0;
7520 }
7521
7522 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7523 "%s.city_image", citystr);
7524
7526 "%s.capital", citystr),
7528
7530 pdcity->capital = cap;
7531 } else {
7532 pdcity->capital = CAPITAL_NOT;
7533 }
7534
7535 return TRUE;
7536}
7537
7538/************************************************************************/
7542 struct player *plr)
7543{
7544 int i, plrno = player_number(plr);
7545
7546 /* Check status and return if not OK (sg_success FALSE). */
7547 sg_check_ret();
7548
7550 /* The player can see all, there's no reason to save the private map. */
7551 return;
7552 }
7553
7554 /* Save the map (terrain). */
7555 SAVE_MAP_CHAR(ptile,
7557 saving->file, "player%d.map_t%04d", plrno);
7558
7560 /* Save the map (borders). */
7561 int x, y;
7562
7563 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7565
7566 line[0] = '\0';
7567 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7568 char token[TOKEN_SIZE];
7569 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7570 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7571
7572 if (plrtile == nullptr || plrtile->owner == nullptr) {
7573 strcpy(token, "-");
7574 } else {
7575 fc_snprintf(token, sizeof(token), "%d",
7576 player_number(plrtile->owner));
7577 }
7578 strcat(line, token);
7579 if (x < MAP_NATIVE_WIDTH) {
7580 strcat(line, ",");
7581 }
7582 }
7583 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7584 plrno, y);
7585 }
7586
7587 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7589
7590 line[0] = '\0';
7591 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7592 char token[TOKEN_SIZE];
7593 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7594 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7595
7596 if (plrtile == nullptr || plrtile->extras_owner == nullptr) {
7597 strcpy(token, "-");
7598 } else {
7599 fc_snprintf(token, sizeof(token), "%d",
7600 player_number(plrtile->extras_owner));
7601 }
7602 strcat(line, token);
7603 if (x < MAP_NATIVE_WIDTH) {
7604 strcat(line, ",");
7605 }
7606 }
7607 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7608 plrno, y);
7609 }
7610 }
7611
7612 /* Save the map (extras). */
7614 int mod[4];
7615 int l;
7616
7617 for (l = 0; l < 4; l++) {
7618 if (4 * j + 1 > game.control.num_extra_types) {
7619 mod[l] = -1;
7620 } else {
7621 mod[l] = 4 * j + l;
7622 }
7623 }
7624
7625 SAVE_MAP_CHAR(ptile,
7627 map_get_player_tile(ptile, plr)->resource,
7628 mod),
7629 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7631
7632 /* Save the map (update time). */
7633 for (i = 0; i < 4; i++) {
7634 /* put 4-bit segments of 16-bit "updated" field */
7635 SAVE_MAP_CHAR(ptile,
7637 map_get_player_tile(ptile, plr)->last_updated, i),
7638 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7639 }
7640
7641 /* Save known cities. */
7642 i = 0;
7643 whole_map_iterate(&(wld.map), ptile) {
7644 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7645 char impr_buf[B_LAST + 1];
7646 char buf[32];
7647
7648 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7649
7650 if (pdcity != nullptr && plr != vision_site_owner(pdcity)) {
7651 int nat_x, nat_y;
7652
7654 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7655 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7656
7657 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7659 "%s.owner", buf);
7660 if (pdcity->original != nullptr) {
7662 "%s.original", buf);
7663 } else {
7664 secfile_insert_int(saving->file, -1, "%s.original", buf);
7665 }
7666
7668 "%s.size", buf);
7669 secfile_insert_bool(saving->file, pdcity->occupied,
7670 "%s.occupied", buf);
7671 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7672 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7673 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7675 "%s.style", buf);
7676 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7678 "%s.capital", buf);
7679
7680 /* Save improvement list as bitvector. Note that improvement order
7681 * is saved in savefile.improvement.order. */
7682 improvement_iterate(pimprove) {
7683 impr_buf[improvement_index(pimprove)]
7684 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7685 ? '1' : '0';
7687 impr_buf[improvement_count()] = '\0';
7689 "Invalid size of the improvement vector (%s.improvements: "
7690 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7691 buf, strlen(impr_buf), sizeof(impr_buf));
7692 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7693 if (pdcity->name != nullptr) {
7694 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7695 }
7696
7697 i++;
7698 }
7700
7701 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7702}
7703
7704/* =======================================================================
7705 * Load / save the researches.
7706 * ======================================================================= */
7707
7708/************************************************************************/
7712{
7713 struct research *presearch;
7714 int count;
7715 int number;
7716 const char *str;
7717 int i, j;
7718 int *vlist_research;
7719
7720 vlist_research = nullptr;
7721 /* Check status and return if not OK (sg_success FALSE). */
7722 sg_check_ret();
7723
7724 /* Initialize all researches. */
7728
7729 /* May be unsaved (e.g. scenario case). */
7730 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7731 for (i = 0; i < count; i++) {
7733 "research.r%d.number", i),
7734 "%s", secfile_error());
7735 presearch = research_by_number(number);
7736 sg_failure_ret(presearch != nullptr,
7737 "Invalid research number %d in 'research.r%d.number'",
7738 number, i);
7739
7740 presearch->tech_goal = technology_load(loading->file,
7741 "research.r%d.goal", i);
7743 &presearch->future_tech,
7744 "research.r%d.futuretech", i),
7745 "%s", secfile_error());
7747 &presearch->bulbs_researched,
7748 "research.r%d.bulbs", i),
7749 "%s", secfile_error());
7751 &presearch->bulbs_researching_saved,
7752 "research.r%d.bulbs_before", i),
7753 "%s", secfile_error());
7754 presearch->researching_saved = technology_load(loading->file,
7755 "research.r%d.saved", i);
7756 presearch->researching = technology_load(loading->file,
7757 "research.r%d.now", i);
7759 &presearch->free_bulbs,
7760 "research.r%d.free_bulbs", i),
7761 "%s", secfile_error());
7762
7763 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7764 sg_failure_ret(str != nullptr, "%s", secfile_error());
7765 sg_failure_ret(strlen(str) == loading->technology.size,
7766 "Invalid length of 'research.r%d.done' ("
7767 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7768 i, strlen(str), loading->technology.size);
7769 for (j = 0; j < loading->technology.size; j++) {
7770 sg_failure_ret(str[j] == '1' || str[j] == '0',
7771 "Undefined value '%c' within 'research.r%d.done'.",
7772 str[j], i);
7773
7774 if (str[j] == '1') {
7775 struct advance *padvance
7776 = advance_by_rule_name(loading->technology.order[j]);
7777
7778 if (padvance) {
7780 TECH_KNOWN);
7781 }
7782 }
7783 }
7784
7786 size_t count_res;
7787 int tn;
7788
7790 "research.r%d.vbs", i);
7791
7792 for (tn = 0; tn < count_res; tn++) {
7793 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7794
7795 if (padvance != nullptr) {
7796 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7797 = vlist_research[tn];
7798 }
7799 }
7800 }
7801 }
7802
7803 /* In case of tech_leakage, we can update research only after all the
7804 * researches have been loaded */
7808}
7809
7810/************************************************************************/
7814{
7815 char invs[A_LAST];
7816 int i = 0;
7817 int *vlist_research;
7818
7819 vlist_research = nullptr;
7820 /* Check status and return if not OK (sg_success FALSE). */
7821 sg_check_ret();
7822
7823 if (saving->save_players) {
7826 "research.r%d.number", i);
7827 technology_save(saving->file, "research.r%d.goal",
7828 i, presearch->tech_goal);
7829 secfile_insert_int(saving->file, presearch->future_tech,
7830 "research.r%d.futuretech", i);
7831 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7832 "research.r%d.bulbs_before", i);
7836 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7840 "research.r%d.vbs", i);
7841 if (vlist_research) {
7843 }
7844 }
7845 technology_save(saving->file, "research.r%d.saved",
7846 i, presearch->researching_saved);
7847 secfile_insert_int(saving->file, presearch->bulbs_researched,
7848 "research.r%d.bulbs", i);
7849 technology_save(saving->file, "research.r%d.now",
7850 i, presearch->researching);
7851 secfile_insert_int(saving->file, presearch->free_bulbs,
7852 "research.r%d.free_bulbs", i);
7853 /* Save technology lists as bytevector. Note that technology order is
7854 * saved in savefile.technology.order */
7855 advance_index_iterate(A_NONE, tech_id) {
7856 invs[tech_id] = (valid_advance_by_number(tech_id) != nullptr
7858 == TECH_KNOWN ? '1' : '0');
7861 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7862 i++;
7864 secfile_insert_int(saving->file, i, "research.count");
7865 }
7866}
7867
7868/* =======================================================================
7869 * Load / save the event cache. Should be the last thing to do.
7870 * ======================================================================= */
7871
7872/************************************************************************/
7876{
7877 /* Check status and return if not OK (sg_success FALSE). */
7878 sg_check_ret();
7879
7880 event_cache_load(loading->file, "event_cache");
7881}
7882
7883/************************************************************************/
7887{
7888 /* Check status and return if not OK (sg_success FALSE). */
7889 sg_check_ret();
7890
7891 if (saving->scenario) {
7892 /* Do _not_ save events in a scenario. */
7893 return;
7894 }
7895
7896 event_cache_save(saving->file, "event_cache");
7897}
7898
7899/* =======================================================================
7900 * Load / save the open treaties
7901 * ======================================================================= */
7902
7903/************************************************************************/
7907{
7908 int tidx;
7909 const char *plr0;
7910
7911 /* Check status and return if not OK (sg_success FALSE). */
7912 sg_check_ret();
7913
7914 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, nullptr,
7915 "treaty%d.plr0", tidx)) != nullptr ;
7916 tidx++) {
7917 const char *plr1;
7918 const char *ct;
7919 int cidx;
7920 struct player *p0, *p1;
7921
7922 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7923
7924 p0 = player_by_name(plr0);
7925 p1 = player_by_name(plr1);
7926
7927 if (p0 == nullptr || p1 == nullptr) {
7928 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7929 } else {
7930 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7931
7934
7935 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, nullptr,
7936 "treaty%d.clause%d.type",
7937 tidx, cidx)) != nullptr ;
7938 cidx++ ) {
7940 const char *plrx;
7941
7942 if (!clause_type_is_valid(type)) {
7943 log_error("Invalid clause type \"%s\"", ct);
7944 } else {
7945 struct player *pgiver = nullptr;
7946
7947 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7948 tidx, cidx);
7949
7950 if (!fc_strcasecmp(plrx, plr0)) {
7951 pgiver = p0;
7952 } else if (!fc_strcasecmp(plrx, plr1)) {
7953 pgiver = p1;
7954 } else {
7955 log_error("Clause giver %s is not participant of the treaty"
7956 "between %s and %s", plrx, plr0, plr1);
7957 }
7958
7959 if (pgiver != nullptr) {
7960 int value;
7961
7962 value = secfile_lookup_int_default(loading->file, 0,
7963 "treaty%d.clause%d.value",
7964 tidx, cidx);
7965
7966 add_clause(ptreaty, pgiver, type, value, nullptr);
7967 }
7968 }
7969 }
7970
7971 /* These must be after clauses have been added so that acceptance
7972 * does not get cleared by what seems like changes to the treaty. */
7974 "treaty%d.accept0", tidx);
7976 "treaty%d.accept1", tidx);
7977 }
7978 }
7979}
7980
7981typedef struct {
7982 int tidx;
7985
7986/************************************************************************/
7989static void treaty_save(struct treaty *ptr, void *data_in)
7990{
7991 char tpath[512];
7992 int cidx = 0;
7994
7995 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7996
7997 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7998 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7999 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
8000 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
8001
8003 char cpath[512];
8004
8005 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
8006
8007 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
8008 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
8009 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
8011}
8012
8013/************************************************************************/
8017{
8018 treaty_cb_data data = { .tidx = 0, .file = saving->file };
8019
8021}
8022
8023/* =======================================================================
8024 * Load / save the history report
8025 * ======================================================================= */
8026
8027/************************************************************************/
8031{
8033 int turn;
8034
8035 /* Check status and return if not OK (sg_success FALSE). */
8036 sg_check_ret();
8037
8038 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
8039
8040 if (turn != -2) {
8041 hist->turn = turn;
8042 }
8043
8044 if (turn + 1 >= game.info.turn) {
8045 const char *str;
8046
8047 str = secfile_lookup_str(loading->file, "history.title");
8048 sg_failure_ret(str != nullptr, "%s", secfile_error());
8049 sz_strlcpy(hist->title, str);
8050 str = secfile_lookup_str(loading->file, "history.body");
8051 sg_failure_ret(str != nullptr, "%s", secfile_error());
8052 sz_strlcpy(hist->body, str);
8053 }
8054}
8055
8056/************************************************************************/
8059static void sg_save_history(struct savedata *saving)
8060{
8062
8063 secfile_insert_int(saving->file, hist->turn, "history.turn");
8064
8065 if (hist->turn + 1 >= game.info.turn) {
8066 secfile_insert_str(saving->file, hist->title, "history.title");
8067 secfile_insert_str(saving->file, hist->body, "history.body");
8068 }
8069}
8070
8071/* =======================================================================
8072 * Load / save the mapimg definitions.
8073 * ======================================================================= */
8074
8075/************************************************************************/
8078static void sg_load_mapimg(struct loaddata *loading)
8079{
8080 int mapdef_count, i;
8081
8082 /* Check status and return if not OK (sg_success FALSE). */
8083 sg_check_ret();
8084
8085 /* Clear all defined map images. */
8086 while (mapimg_count() > 0) {
8087 mapimg_delete(0);
8088 }
8089
8091 "mapimg.count");
8092 log_verbose("Saved map image definitions: %d.", mapdef_count);
8093
8094 if (0 >= mapdef_count) {
8095 return;
8096 }
8097
8098 for (i = 0; i < mapdef_count; i++) {
8099 const char *p;
8100
8101 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
8102 if (p == nullptr) {
8103 log_verbose("[Mapimg %4d] Missing definition.", i);
8104 continue;
8105 }
8106
8107 if (!mapimg_define(p, FALSE)) {
8108 log_error("Invalid map image definition %4d: %s.", i, p);
8109 }
8110
8111 log_verbose("Mapimg %4d loaded.", i);
8112 }
8113}
8114
8115/************************************************************************/
8118static void sg_save_mapimg(struct savedata *saving)
8119{
8120 /* Check status and return if not OK (sg_success FALSE). */
8121 sg_check_ret();
8122
8123 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8124 if (mapimg_count() > 0) {
8125 int i;
8126
8127 for (i = 0; i < mapimg_count(); i++) {
8128 char buf[MAX_LEN_MAPDEF];
8129
8130 mapimg_id2str(i, buf, sizeof(buf));
8131 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8132 }
8133 }
8134}
8135
8136/* =======================================================================
8137 * Sanity checks for loading / saving a game.
8138 * ======================================================================= */
8139
8140/************************************************************************/
8144{
8145 int players;
8146
8147 /* Check status and return if not OK (sg_success FALSE). */
8148 sg_check_ret();
8149
8150 if (game.info.is_new_game) {
8151 /* Nothing to do for new games (or not started scenarios). */
8152 return;
8153 }
8154
8155 /* Old savegames may have maxplayers lower than current player count,
8156 * fix. */
8157 players = normal_player_count();
8158 if (game.server.max_players < players) {
8159 log_verbose("Max players lower than current players, fixing");
8160 game.server.max_players = players;
8161 }
8162
8163 /* Fix ferrying sanity */
8164 players_iterate(pplayer) {
8165 unit_list_iterate_safe(pplayer->units, punit) {
8168 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8174 }
8177
8178 /* Fix stacking issues. We don't rely on the savegame preserving
8179 * alliance invariants (old savegames often did not) so if there are any
8180 * unallied units on the same tile we just bounce them. */
8181 players_iterate(pplayer) {
8183 resolve_unit_stacks(pplayer, aplayer, TRUE);
8186
8187 /* Recalculate the potential buildings for each city. Has caused some
8188 * problems with game random state.
8189 * This also changes the game state if you save the game directly after
8190 * loading it and compare the results. */
8191 players_iterate(pplayer) {
8192 /* Building advisor needs data phase open in order to work */
8193 adv_data_phase_init(pplayer, FALSE);
8194 building_advisor(pplayer);
8195 /* Close data phase again so it can be opened again when game starts. */
8196 adv_data_phase_done(pplayer);
8198
8199 /* Prevent a buggy or intentionally crafted save game from crashing
8200 * Freeciv. See hrm Bug #887748 */
8201 players_iterate(pplayer) {
8202 city_list_iterate(pplayer->cities, pcity) {
8203 worker_task_list_iterate(pcity->task_reqs, ptask) {
8204 if (!worker_task_is_sane(ptask)) {
8205 log_error("[city id: %d] Bad worker task %d.",
8206 pcity->id, ptask->act);
8207 worker_task_list_remove(pcity->task_reqs, ptask);
8208 free(ptask);
8209 ptask = nullptr;
8210 }
8214
8215 /* Check worked tiles map */
8216#ifdef FREECIV_DEBUG
8217 if (loading->worked_tiles != nullptr) {
8218 /* Check the entire map for unused worked tiles */
8219 whole_map_iterate(&(wld.map), ptile) {
8220 if (loading->worked_tiles[ptile->index] != -1) {
8221 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8222 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8223 }
8225 }
8226#endif /* FREECIV_DEBUG */
8227
8228 /* Check researching technologies and goals. */
8230 if (presearch->researching != A_UNSET
8231 && !is_future_tech(presearch->researching)
8232 && (valid_advance_by_number(presearch->researching) == nullptr
8234 != TECH_PREREQS_KNOWN))) {
8235 log_sg(_("%s had invalid researching technology."),
8237 presearch->researching = A_UNSET;
8238 }
8239 if (presearch->tech_goal != A_UNSET
8240 && !is_future_tech(presearch->tech_goal)
8241 && (valid_advance_by_number(presearch->tech_goal) == nullptr
8244 == TECH_KNOWN))) {
8245 log_sg(_("%s had invalid technology goal."),
8247 presearch->tech_goal = A_UNSET;
8248 }
8249
8252
8253 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8254 players_iterate(pplayer) {
8255 int unique_count[U_LAST];
8256
8257 memset(unique_count, 0, sizeof(unique_count));
8258
8259 unit_list_iterate(pplayer->units, punit) {
8262
8265 log_sg(_("%s has multiple units of type %s though it should be possible "
8266 "to have only one."),
8268 }
8271
8272 players_iterate(pplayer) {
8273 unit_list_iterate_safe(pplayer->units, punit) {
8274 if (punit->has_orders
8276 punit->orders.list)) {
8277 log_sg("Invalid unit orders for unit %d.", punit->id);
8279 }
8282
8283 /* Check max rates (rules may have changed since saving) */
8284 players_iterate(pplayer) {
8287
8288 /* Check initial city sanity */
8289 players_iterate(pplayer) {
8290 if (!player_has_flag(pplayer, PLRF_FIRST_CITY)
8291 && city_list_size(pplayer->cities) > 0) {
8292 log_sg(_("%s inconsistency: Has never had their first city, "
8293 "but has cities this very moment. Fixing."),
8294 player_name(pplayer));
8295 BV_SET(pplayer->flags, PLRF_FIRST_CITY);
8296 }
8298
8299 if (0 == strlen(server.game_identifier)
8300 || !is_base64url(server.game_identifier)) {
8301 /* This uses fc_rand(), so random state has to be initialized before. */
8302 randomize_base64url_string(server.game_identifier,
8303 sizeof(server.game_identifier));
8304 }
8305
8306 /* Restore game random state, just in case various initialization code
8307 * inexplicably altered the previously existing state. */
8308 if (!game.info.is_new_game) {
8309 fc_rand_set_state(loading->rstate);
8310 }
8311
8312 /* At the end do the default sanity checks. */
8313 sanity_check();
8314}
8315
8316/************************************************************************/
8320{
8321 /* Check status and return if not OK (sg_success FALSE). */
8322 sg_check_ret();
8323}
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:57
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1271
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1260
bool action_id_exists(const action_id act_id)
Definition actions.c:1089
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:421
#define NUM_ACTIONS
Definition actions.h:63
#define action_id_get_activity(act_id)
Definition actions.h:466
#define ACTION_NONE
Definition actions.h:59
void building_advisor(struct player *pplayer)
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:270
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:574
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:390
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:380
#define ai_type_iterate_end
Definition ai.h:375
#define ai_type_iterate(NAME_ai)
Definition ai.h:368
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:142
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:174
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
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:1197
const char * city_name_get(const struct city *pcity)
Definition city.c:1157
const char * city_style_rule_name(const int style)
Definition city.c:1818
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3538
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2938
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1232
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3465
void destroy_city_virtual(struct city *pcity)
Definition city.c:3628
int city_style_by_rule_name(const char *s)
Definition city.c:1791
#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:565
#define cities_iterate(pcity)
Definition city.h:512
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:84
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
#define output_type_iterate(output)
Definition city.h:853
#define FREE_WORKED_TILES
Definition city.h:890
#define MAX_CITY_SIZE
Definition city.h:104
#define city_list_iterate_end
Definition city.h:510
#define I_NEVER
Definition city.h:245
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:228
#define city_tile_iterate_end
Definition city.h:236
#define output_type_iterate_end
Definition city.h:859
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2787
bool send_city_suppression(bool now)
Definition citytools.c:2176
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:136
void city_thaw_workers(struct city *pcity)
Definition citytools.c:146
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2858
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3460
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:367
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:853
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
char * incite_cost
Definition comments.c:77
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:186
int counter_index(const struct counter *pcount)
Definition counters.c:176
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:116
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:166
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:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
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:108
struct treaty * ptreaty
Definition diplodlg_g.h:28
void treaty_add(struct treaty *ptreaty)
Definition diptreaty.c:377
void init_treaty(struct treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
bool add_clause(struct treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
#define clause_list_iterate_end
Definition diptreaty.h:73
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:71
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:779
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:1128
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:160
#define NO_TARGET
Definition fc_types.h:215
int Tech_type_id
Definition fc_types.h:238
unsigned char citizens
Definition fc_types.h:249
int Specialist_type_id
Definition fc_types.h:236
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:128
#define MAX_LEN_NAME
Definition fc_types.h:68
@ O_LAST
Definition fc_types.h:103
int Multiplier_type_id
Definition fc_types.h:247
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:94
#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:115
void initialize_globals(void)
Definition game.c:692
struct city * game_city_by_number(int id)
Definition game.c:106
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:603
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:602
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:605
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:604
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:607
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:622
struct government * government_of_player(const struct player *pplayer)
Definition government.c:115
const char * government_rule_name(const struct government *pgovern)
Definition government.c:132
struct government * government_by_rule_name(const char *name)
Definition government.c:57
#define governments_iterate(NAME_pgov)
Definition government.h:136
#define governments_iterate_end
Definition government.h:139
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
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:502
void adv_city_alloc(struct city *pcity)
Definition infracache.c:489
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_fatal(message,...)
Definition log.h:101
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1813
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2030
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1829
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1852
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1925
void map_init_topology(struct civ_map *nmap)
Definition map.c:315
void main_map_allocate(void)
Definition map.c:534
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_startpos_count(void)
Definition map.c:2017
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1912
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1796
#define map_startpos_iterate(NAME_psp)
Definition map.h:136
#define map_startpos_iterate_end
Definition map.h:139
#define whole_map_iterate(_map, _tile)
Definition map.h:582
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define whole_map_iterate_end
Definition map.h:591
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:1228
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1475
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2174
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:901
bool send_tile_suppression(bool now)
Definition maphand.c:474
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:344
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1203
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1406
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1375
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2187
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1185
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:927
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1166
void map_calculate_borders(void)
Definition maphand.c:2332
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1640
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1390
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1312
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1205
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:350
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:443
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:134
char * lines
Definition packhand.c:133
int len
Definition packhand.c:129
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:441
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1217
struct player * player_by_number(const int player_id)
Definition player.c:837
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1468
int player_count(void)
Definition player.c:806
int player_slot_count(void)
Definition player.c:415
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:454
int player_number(const struct player *pplayer)
Definition player.c:826
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:164
const char * player_name(const struct player *pplayer)
Definition player.c:885
int player_slot_max_used_number(void)
Definition player.c:467
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
struct player * player_by_name(const char *name)
Definition player.c:871
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:245
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1191
int player_index(const struct player *pplayer)
Definition player.c:818
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:849
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:325
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1485
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1477
#define players_iterate_end
Definition player.h:552
dipl_reason
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:194
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:194
#define players_iterate(_pplayer)
Definition player.h:547
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:570
static bool is_barbarian(const struct player *pplayer)
Definition player.h:499
#define player_slots_iterate(_pslot)
Definition player.h:538
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:572
#define players_iterate_alive_end
Definition player.h:562
#define player_slots_iterate_end
Definition player.h:542
#define players_iterate_alive(_pplayer)
Definition player.h:557
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2270
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1896
int normal_player_count(void)
Definition plrhand.c:3217
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2059
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:2466
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2416
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3263
void shuffle_players(void)
Definition plrhand.c:2391
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1945
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1620
void assign_player_colors(void)
Definition plrhand.c:1736
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3250
void fit_nationset_to_players(void)
Definition plrhand.c:2672
#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:51
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,...)
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,...)
float secfile_lookup_float_default(const struct section_file *secfile, float def, 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 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_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define secfile_entry_ignore_by_path(_sfile_, _path_)
#define secfile_insert_float(secfile, value, path,...)
struct history_report * history_report_get(void)
Definition report.c:1859
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:671
const char * research_name_translation(const struct research *presearch)
Definition research.c:158
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:640
struct research * research_by_number(int number)
Definition research.c:119
int research_number(const struct research *presearch)
Definition research.c:109
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1357
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
void research_update(struct research *presearch)
Definition research.c:504
#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:70
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:86
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, char *path,...)
Definition rgbcolor.c:116
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 ruleload.c:9489
#define sanity_check()
Definition sanitycheck.h:44
#define sanity_check_city(x)
Definition sanitycheck.h:42
int current_compat_ver(void)
Definition savecompat.c:233
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:243
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:154
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:255
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:205
#define sg_check_ret(...)
Definition savecompat.h:148
#define sg_warn(condition, message,...)
Definition savecompat.h:158
#define hex_chars
Definition savecompat.h:203
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:182
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:175
#define sg_regr(fixversion, message,...)
Definition savecompat.h:191
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:144
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:169
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:436
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:8059
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1208
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2774
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3040
static void unit_ordering_apply(void)
Definition savegame3.c:1089
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3732
static struct loaddata * loaddata_new(struct section_file *file)
Definition savegame3.c:586
static void worklist_save(struct section_file *file, const struct worklist *pwl, int max_length, const char *path,...)
Definition savegame3.c:1022
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3612
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3271
bool sg_success
Definition savecompat.c:35
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:155
static char * quote_block(const void *const data, int length)
Definition savegame3.c:899
#define halfbyte_iterate_extras_end
Definition savegame3.c:265
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:260
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2833
static enum unit_orders char2order(char order)
Definition savegame3.c:712
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:920
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:3103
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3573
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:154
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4188
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:224
static void treaty_save(struct treaty *ptr, void *data_in)
Definition savegame3.c:7989
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5704
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5656
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5066
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2938
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:6182
static char activity2char(int activity)
Definition savegame3.c:825
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:681
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1345
static enum unit_activity char2activity(char activity)
Definition savegame3.c:876
static void unit_ordering_calc(void)
Definition savegame3.c:1060
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2679
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6113
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1260
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2450
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3216
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7711
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3529
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:175
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2055
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2409
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1789
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6735
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:8030
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:8016
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3393
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7813
static void savegame3_save_real(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:529
#define TOKEN_SIZE
Definition savegame3.c:281
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2488
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2514
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2103
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:700
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4249
static char order2char(enum unit_orders order)
Definition savegame3.c:739
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7906
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2602
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1143
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6788
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2258
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1175
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1272
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7541
static enum direction8 char2dir(char dir)
Definition savegame3.c:763
#define ACTIVITY_LAST_SAVEGAME3
Definition savegame3.c:156
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:5190
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1237
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8319
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:8078
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7054
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7134
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2078
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2893
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7217
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2979
static void worklist_load(struct section_file *file, int wlist_max_length, struct worklist *pwl, const char *path,...)
Definition savegame3.c:968
static void sg_save_mapimg(struct savedata *saving)
Definition savegame3.c:8118
static const char savefile_options_default[]
Definition savegame3.c:283
static char dir2char(enum direction8 dir)
Definition savegame3.c:792
static bool sg_load_player_vision_city(struct loaddata *loading, struct player *plr, struct vision_site *pdcity, const char *citystr)
Definition savegame3.c:7419
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2717
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3129
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:625
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3993
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:3007
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1308
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7886
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3071
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8143
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7875
void savegame3_load(struct section_file *file)
Definition savegame3.c:463
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1110
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2278
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4740
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2499
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2695
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3669
void save_restore_sane_state(void)
Definition savemain.c:347
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:4958
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4870
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:1094
bool str_to_int(const char *str, int *pint)
Definition shared.c:515
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
bool is_base64url(const char *s)
Definition shared.c:321
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1923
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:343
#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:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:90
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
Specialist_type_id specialist_count(void)
Definition specialist.c:71
bool is_normal_specialist_id(Specialist_type_id sp)
Definition specialist.c:196
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
#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
const char * aifill(int amount)
Definition srv_main.c:2556
bool game_was_started(void)
Definition srv_main.c:357
void identity_number_reserve(int id)
Definition srv_main.c:2083
struct server_arguments srvarg
Definition srv_main.c:182
void init_game_seed(void)
Definition srv_main.c:209
void update_nations_with_startpos(void)
Definition srv_main.c:2361
enum server_states server_state(void)
Definition srv_main.c:341
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 * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
Definition city.h:318
size_t length
Definition city.h:415
bool multiresearch
Definition game.h:170
bool last_updated_year
Definition game.h:243
int world_peace_start
Definition game.h:245
float turn_change_time
Definition game.h:225
bool vision_reveal_tiles
Definition game.h:207
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:269
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:241
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:214
char rulesetdir[MAX_LEN_NAME]
Definition game.h:246
int additional_phase_seconds
Definition game.h:219
struct section_file * luadata
Definition game.h:254
int scoreturn
Definition game.h:232
randseed seed
Definition game.h:234
int dbid
Definition game.h:255
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:210
struct timer * phase_timer
Definition game.h:218
unsigned revealmap
Definition game.h:184
char orig_game_version[MAX_LEN_NAME]
Definition game.h:228
bool save_known
Definition game.h:266
bool foggedborders
Definition game.h:154
struct civ_game::@32::@36::@39 save_options
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:212
struct civ_game::@32::@36 server
int timeoutinc
Definition game.h:211
int phase_mode_stored
Definition game.h:223
int max_players
Definition game.h:163
bool save_starts
Definition game.h:268
int timeoutintinc
Definition game.h:213
randseed seed
Definition map_types.h:105
bool have_resources
Definition map_types.h:121
bool altitude_info
Definition map_types.h:74
struct civ_map::@44::@46 server
bool have_huts
Definition map_types.h:120
enum map_generator generator
Definition map_types.h:111
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:66
struct section_file * file
Definition savecompat.h:46
bool global_advances[A_LAST]
int great_wonder_owners[B_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char alt_dir[MAX_LEN_NAME]
char version[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char authors[MAX_LEN_PACKET/3]
char datafile[MAX_LEN_NAME]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:116
struct ai_trait * traits
Definition player.h:126
enum barbarian_type barbarian_type
Definition player.h:122
int science_cost
Definition player.h:119
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:124
int expand
Definition player.h:118
int fuzzy
Definition player.h:117
enum diplstate_type type
Definition player.h:199
int infra_points
Definition player.h:67
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int angry
Definition player.h:89
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct 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:281
int bulbs_last_turn
Definition player.h:351
struct player_ai ai_common
Definition player.h:288
bv_plr_flags flags
Definition player.h:292
int primary_capital_id
Definition player.h:275
bool is_male
Definition player.h:257
int wonders[B_LAST]
Definition player.h:305
bool unassigned_ranked
Definition player.h:255
struct government * target_government
Definition player.h:259
int autoselect_weight
Definition player.h:299
char username[MAX_LEN_NAME]
Definition player.h:252
int revolution_finishes
Definition player.h:273
int nturns_idle
Definition player.h:265
struct government * government
Definition player.h:258
struct team * team
Definition player.h:261
int turns_alive
Definition player.h:266
const struct ai_type * ai
Definition player.h:289
struct unit_list * units
Definition player.h:282
char ranked_username[MAX_LEN_NAME]
Definition player.h:254
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
bv_player real_embassy
Definition player.h:277
struct player::@73::@75 server
struct player_economic economic
Definition player.h:284
struct player_spaceship spaceship
Definition player.h:286
struct attribute_block_s attribute_block
Definition player.h:307
struct player_score score
Definition player.h:283
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:314
struct nation_type * nation
Definition player.h:260
struct nation_style * style
Definition player.h:279
bool border_vision
Definition player.h:327
bool phase_done
Definition player.h:263
struct adv_data * adv
Definition player.h:334
int history
Definition player.h:316
char orig_username[MAX_LEN_NAME]
Definition player.h:347
int last_war_action
Definition player.h:270
struct rgbcolor * rgb
Definition player.h:312
bool unassigned_user
Definition player.h:253
const char * save_reason
Definition savegame3.c:274
struct section_file * file
Definition savegame3.c:270
bool scenario
Definition savegame3.c:275
bool save_players
Definition savegame3.c:278
char secfile_options[512]
Definition savegame3.c:271
char metaserver_addr[256]
Definition srv_main.h:29
char serverid[256]
Definition srv_main.h:49
Definition map.c:40
Definition team.c:40
char identifier
Definition terrain.h:84
Definition tile.h:50
int altitude
Definition tile.h:65
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:7983
struct player * plr1
Definition diptreaty.h:82
struct clause_list * clauses
Definition diptreaty.h:84
bool accept1
Definition diptreaty.h:83
struct player * plr0
Definition diptreaty.h:82
bool accept0
Definition diptreaty.h:83
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:139
int length
Definition unit.h:197
int upkeep[O_LAST]
Definition unit.h:149
bool has_orders
Definition unit.h:195
enum action_decision action_decision_want
Definition unit.h:204
int battlegroup
Definition unit.h:193
enum unit_activity activity
Definition unit.h:158
int moves_left
Definition unit.h:151
int id
Definition unit.h:146
enum gen_action action
Definition unit.h:159
int ord_city
Definition unit.h:244
struct unit::@83 orders
bool moved
Definition unit.h:175
int ord_map
Definition unit.h:243
int index
Definition unit.h:197
struct vision * vision
Definition unit.h:246
bool vigilant
Definition unit.h:199
int hp
Definition unit.h:152
int fuel
Definition unit.h:154
struct extra_type * changed_from_target
Definition unit.h:172
int current_form_turn
Definition unit.h:210
bool stay
Definition unit.h:207
enum direction8 facing
Definition unit.h:143
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:141
struct extra_type * activity_target
Definition unit.h:166
int activity_count
Definition unit.h:164
struct unit_order * list
Definition unit.h:200
enum unit_activity changed_from
Definition unit.h:170
struct unit_adv * adv
Definition unit.h:238
struct player * nationality
Definition unit.h:145
bool repeat
Definition unit.h:198
int homecity
Definition unit.h:147
bool paradropped
Definition unit.h:176
bool done_moving
Definition unit.h:183
int birth_turn
Definition unit.h:209
struct goods_type * carrying
Definition unit.h:188
struct tile * goto_tile
Definition unit.h:156
struct tile * action_decision_tile
Definition unit.h:205
int veteran
Definition unit.h:153
int changed_from_count
Definition unit.h:171
enum server_side_agent ssa_controller
Definition unit.h:174
struct civ_map map
int city_style(struct city *pcity)
Definition style.c:235
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:113
struct nation_style * style_by_number(int id)
Definition style.c:84
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:104
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:742
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:851
#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:375
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:173
bool team_add_player(struct player *pplayer, struct team *pteam)
Definition team.c:452
struct team * team_new(struct team_slot *tslot)
Definition team.c:309
const struct player_list * team_members(const struct team *pteam)
Definition team.c:443
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
bool is_future_tech(Tech_type_id tech)
Definition tech.c:286
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:181
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:90
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:246
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:273
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:274
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:242
void init_tech(struct research *research, bool update)
Definition techtools.c:1168
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:188
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:127
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:257
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:273
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1098
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:350
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:107
#define tile_index(_pt_)
Definition tile.h:89
#define tile_worked(_tile)
Definition tile.h:119
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
void timer_stop(struct timer *t)
Definition timing.c:305
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:379
#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)
void free_unit_orders(struct unit *punit)
Definition unit.c:1827
int unit_upkeep_cost(const struct unit *punit, Output_type_id otype)
Definition unit.c:2973
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2462
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1299
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2526
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:882
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1682
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2731
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target, enum gen_action trigger_action)
Definition unit.c:1157
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1787
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1308
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1139
#define unit_tile(_pu)
Definition unit.h:408
#define BATTLEGROUP_NONE
Definition unit.h:192
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:407
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:1414
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5029
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1238
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1071
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1794
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2662
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:93
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define unit_type_iterate(_p)
Definition unittype.h:865
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:872
const char * freeciv_datafile_version(void)
Definition version.c:186
#define MINOR_VERSION
Definition version_gen.h:7
#define EMERGENCY_VERSION
Definition version_gen.h:9
#define MAJOR_VERSION
Definition version_gen.h:6
#define PATCH_VERSION
Definition version_gen.h:8
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:128
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
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT