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