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/************************************************************************/
1261 const char *path, int plrno)
1262{
1263 char path_with_name[128];
1264 const char *name;
1265 struct advance *padvance;
1266
1268 "%s_name", path);
1269
1271
1272 if (!name || name[0] == '\0') {
1273 /* used by researching_saved */
1274 return A_UNKNOWN;
1275 }
1276 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1277 return A_FUTURE;
1278 }
1279 if (fc_strcasecmp(name, "A_NONE") == 0) {
1280 return A_NONE;
1281 }
1282 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1283 return A_UNSET;
1284 }
1285
1288 "%s: unknown technology \"%s\".", path_with_name, name);
1289
1290 return advance_number(padvance);
1291}
1292
1293/************************************************************************/
1296static void technology_save(struct section_file *file,
1297 const char *path, int plrno, Tech_type_id tech)
1298{
1299 char path_with_name[128];
1300 const char *name;
1301
1303 "%s_name", path);
1304
1305 switch (tech) {
1306 case A_UNKNOWN: /* used by researching_saved */
1307 name = "";
1308 break;
1309 case A_NONE:
1310 name = "A_NONE";
1311 break;
1312 case A_UNSET:
1313 name = "A_UNSET";
1314 break;
1315 case A_FUTURE:
1316 name = "A_FUTURE";
1317 break;
1318 default:
1320 break;
1321 }
1322
1324}
1325
1326/* =======================================================================
1327 * Load / save savefile data.
1328 * ======================================================================= */
1329
1330/************************************************************************/
1334{
1335 int i;
1336 const char *terr_name;
1337 bool ruleset_datafile;
1339 const char *str;
1340
1341 /* Check status and return if not OK (sg_success FALSE). */
1342 sg_check_ret();
1343
1344 /* Load savefile options. */
1345 loading->secfile_options
1346 = secfile_lookup_str(loading->file, "savefile.options");
1347
1348 /* We don't need these entries, but read them anyway to avoid
1349 * warnings about unread secfile entries. */
1350 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1351 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1352
1353 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1355
1356 if (game.scenario.datafile[0] != '\0') {
1358 } else {
1360 }
1361
1364 const char *req_caps;
1365
1368 /* Failed to load correct ruleset */
1369 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1371 }
1372
1373 req_caps = secfile_lookup_str_default(loading->file, "",
1374 "scenario.ruleset_caps");
1375 strncpy(game.scenario.req_caps, req_caps,
1376 sizeof(game.scenario.req_caps) - 1);
1377 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1378
1379 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1380 /* Current ruleset lacks required capabilities. */
1381 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1382 log_normal(_("Ruleset has capabilities: %s"),
1384 /* TRANS: ... ruleset dir ... scenario name ... */
1385 log_error(_("Current ruleset %s not compatible with the scenario %s."
1386 " Trying to switch to the ruleset specified by the"
1387 " scenario."),
1389
1391 }
1392 }
1393
1396 const char *ruleset, *alt_dir;
1397
1400 "savefile.rulesetdir");
1401
1402 /* Load ruleset. */
1404 if (!strcmp("default", game.server.rulesetdir)) {
1405 /* Here 'default' really means current default.
1406 * Saving happens with real ruleset name, so savegames containing this
1407 * are special scenarios. */
1409 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1411 }
1412
1413 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1414 "savefile.ruleset_alt_dir");
1415
1416 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1417 if (alt_dir) {
1419 _("Failed to load either of rulesets '%s' or '%s' "
1420 "needed for savegame."),
1421 ruleset, alt_dir);
1422 } else {
1424 _("Failed to load ruleset '%s' needed for savegame."),
1425 ruleset);
1426 }
1427 }
1428
1430 /* TRANS: ruleset dir */
1431 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1432 }
1433 }
1434
1435 /* Remove all aifill players. Correct number of them get created later
1436 * with correct skill level etc. */
1437 (void) aifill(0);
1438
1439 /* Time to load scenario specific luadata */
1440 if (game.scenario.datafile[0] != '\0') {
1441 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1443 } else {
1444 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1445 const struct strvec **path;
1446 const char *found = NULL;
1447 char testfile[MAX_LEN_PATH];
1448 struct section_file *secfile;
1449
1450 for (path = paths; found == NULL && *path != NULL; path++) {
1451 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1452
1453 found = fileinfoname(*path, testfile);
1454 }
1455
1456 if (found == NULL) {
1457 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1458 sg_success = FALSE;
1459 return;
1460 }
1461
1462 secfile = secfile_load(found, FALSE);
1463 if (secfile == NULL) {
1464 log_error(_("Failed to load scenario luadata file %s.luadata"),
1466 sg_success = FALSE;
1467 return;
1468 }
1469
1470 game.server.luadata = secfile;
1471 }
1472 }
1473
1475 "savefile.dbid");
1476
1477 /* This is in the savegame only if the game has been started before savegame3.c time,
1478 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1480 "savefile.last_updated_as_year");
1481
1482 /* Load improvements. */
1483 loading->improvement.size
1485 "savefile.improvement_size");
1486 if (loading->improvement.size) {
1487 loading->improvement.order
1488 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1489 "savefile.improvement_vector");
1490 sg_failure_ret(loading->improvement.size != 0,
1491 "Failed to load improvement order: %s",
1492 secfile_error());
1493 }
1494
1495 /* Load technologies. */
1496 loading->technology.size
1498 "savefile.technology_size");
1499 if (loading->technology.size) {
1500 loading->technology.order
1501 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1502 "savefile.technology_vector");
1503 sg_failure_ret(loading->technology.size != 0,
1504 "Failed to load technology order: %s",
1505 secfile_error());
1506 }
1507
1508 /* Load Activities. */
1509 loading->activities.size
1511 "savefile.activities_size");
1512 if (loading->activities.size) {
1513 loading->activities.order
1514 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1515 "savefile.activities_vector");
1516 sg_failure_ret(loading->activities.size != 0,
1517 "Failed to load activity order: %s",
1518 secfile_error());
1519 }
1520
1521 /* Load traits. */
1522 loading->trait.size
1524 "savefile.trait_size");
1525 if (loading->trait.size) {
1526 loading->trait.order
1527 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1528 "savefile.trait_vector");
1529 sg_failure_ret(loading->trait.size != 0,
1530 "Failed to load trait order: %s",
1531 secfile_error());
1532 }
1533
1534 /* Load extras. */
1535 loading->extra.size
1537 "savefile.extras_size");
1538 if (loading->extra.size) {
1539 const char **modname;
1540 size_t nmod;
1541 int j;
1542
1543 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1544 "savefile.extras_vector");
1545 sg_failure_ret(loading->extra.size != 0,
1546 "Failed to load extras order: %s",
1547 secfile_error());
1549 "Number of extras defined by the ruleset (= %d) are "
1550 "lower than the number in the savefile (= %d).",
1551 game.control.num_extra_types, (int)loading->extra.size);
1552 /* make sure that the size of the array is divisible by 4 */
1553 nmod = 4 * ((loading->extra.size + 3) / 4);
1554 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1555 for (j = 0; j < loading->extra.size; j++) {
1556 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1557 }
1558 free(modname);
1559 for (; j < nmod; j++) {
1560 loading->extra.order[j] = NULL;
1561 }
1562 }
1563
1564 /* Load multipliers. */
1565 loading->multiplier.size
1567 "savefile.multipliers_size");
1568 if (loading->multiplier.size) {
1569 const char **modname;
1570 int j;
1571
1572 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1573 "savefile.multipliers_vector");
1574 sg_failure_ret(loading->multiplier.size != 0,
1575 "Failed to load multipliers order: %s",
1576 secfile_error());
1577 /* It's OK for the set of multipliers in the savefile to differ
1578 * from those in the ruleset. */
1579 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1580 sizeof(*loading->multiplier.order));
1581 for (j = 0; j < loading->multiplier.size; j++) {
1582 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1583 if (!loading->multiplier.order[j]) {
1584 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1585 "discarding", modname[j]);
1586 }
1587 }
1588 free(modname);
1589 }
1590
1591 /* Load specialists. */
1592 loading->specialist.size
1594 "savefile.specialists_size");
1595 if (loading->specialist.size) {
1596 const char **modname;
1597 size_t nmod;
1598 int j;
1599
1600 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1601 "savefile.specialists_vector");
1602 sg_failure_ret(loading->specialist.size != 0,
1603 "Failed to load specialists order: %s",
1604 secfile_error());
1606 "Number of specialists defined by the ruleset (= %d) are "
1607 "lower than the number in the savefile (= %d).",
1608 game.control.num_specialist_types, (int)loading->specialist.size);
1609 /* make sure that the size of the array is divisible by 4 */
1610 /* That's not really needed with specialists at the moment, but done this way
1611 * for consistency with other types, and to be prepared for the time it needs
1612 * to be this way. */
1613 nmod = 4 * ((loading->specialist.size + 3) / 4);
1614 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1615 for (j = 0; j < loading->specialist.size; j++) {
1616 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1617 }
1618 free(modname);
1619 for (; j < nmod; j++) {
1620 loading->specialist.order[j] = NULL;
1621 }
1622 }
1623
1624 /* Load action order. */
1625 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1626 "savefile.action_size");
1627
1628 sg_failure_ret(loading->action.size > 0,
1629 "Failed to load action order: %s",
1630 secfile_error());
1631
1632 if (loading->action.size) {
1633 const char **modname;
1634 int j;
1635
1636 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1637 "savefile.action_vector");
1638
1639 loading->action.order = fc_calloc(loading->action.size,
1640 sizeof(*loading->action.order));
1641
1642 for (j = 0; j < loading->action.size; j++) {
1644
1645 if (real_action) {
1646 loading->action.order[j] = real_action->id;
1647 } else {
1648 log_sg("Unknown action \'%s\'", modname[j]);
1649 loading->action.order[j] = ACTION_NONE;
1650 }
1651 }
1652
1653 free(modname);
1654 }
1655
1656 /* Load action decision order. */
1657 loading->act_dec.size
1659 "savefile.action_decision_size");
1660
1661 sg_failure_ret(loading->act_dec.size > 0,
1662 "Failed to load action decision order: %s",
1663 secfile_error());
1664
1665 if (loading->act_dec.size) {
1666 const char **modname;
1667 int j;
1668
1669 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1670 "savefile.action_decision_vector");
1671
1672 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1673 sizeof(*loading->act_dec.order));
1674
1675 for (j = 0; j < loading->act_dec.size; j++) {
1676 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1678 }
1679
1680 free(modname);
1681 }
1682
1683 /* Load server side agent order. */
1684 loading->ssa.size
1686 "savefile.server_side_agent_size");
1687
1688 sg_failure_ret(loading->ssa.size > 0,
1689 "Failed to load server side agent order: %s",
1690 secfile_error());
1691
1692 if (loading->ssa.size) {
1693 const char **modname;
1694 int j;
1695
1696 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1697 "savefile.server_side_agent_list");
1698
1699 loading->ssa.order = fc_calloc(loading->ssa.size,
1700 sizeof(*loading->ssa.order));
1701
1702 for (j = 0; j < loading->ssa.size; j++) {
1703 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1705 }
1706
1707 free(modname);
1708 }
1709
1710 /* Load city options order. */
1711 loading->coptions.size
1713 "savefile.city_options_size");
1714
1715 sg_failure_ret(loading->coptions.size > 0,
1716 "Failed to load city options order: %s",
1717 secfile_error());
1718
1719 if (loading->coptions.size) {
1720 const char **modname;
1721 int j;
1722
1723 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1724 "savefile.city_options_vector");
1725
1726 loading->coptions.order = fc_calloc(loading->coptions.size,
1727 sizeof(*loading->coptions.order));
1728
1729 for (j = 0; j < loading->coptions.size; j++) {
1730 loading->coptions.order[j] = city_options_by_name(modname[j],
1732 }
1733
1734 free(modname);
1735 }
1736
1737 /* Terrain identifiers */
1739 pterr->identifier_load = '\0';
1741
1742 i = 0;
1744 "savefile.terrident%d.name", i)) != NULL) {
1746
1747 if (pterr != NULL) {
1748 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1749 "savefile.terrident%d.identifier", i);
1750
1751 pterr->identifier_load = *iptr;
1752 } else {
1753 log_error("Identifier for unknown terrain type %s.", terr_name);
1754 }
1755 i++;
1756 }
1757
1760 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1761 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1762 "%s and %s share a saved identifier",
1764 }
1767}
1768
1769/************************************************************************/
1773{
1774 int i;
1775
1776 /* Check status and return if not OK (sg_success FALSE). */
1777 sg_check_ret();
1778
1779 /* Save savefile options. */
1781
1782 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1783
1784 /* Save reason of the savefile generation. */
1785 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1786
1787 /* Save as accurate freeciv revision information as possible */
1788 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1789
1790 /* Freeciv version used in the very first launch of this game -
1791 * or even saving in pregame. */
1793 "savefile.orig_version");
1794
1795 /* Save rulesetdir at this point as this ruleset is required by this
1796 * savefile. */
1797 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1798
1799 if (game.control.version[0] != '\0') {
1800 /* Current ruleset has version information, save it.
1801 * This is never loaded, but exist in savegame file only for debugging purposes. */
1802 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1803 }
1804
1805 if (game.control.alt_dir[0] != '\0') {
1806 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1807 }
1808
1810 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1811 }
1812
1813 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1814
1815 /* Save improvement order in savegame, so we are not dependent on ruleset
1816 * order. If the game isn't started improvements aren't loaded so we can
1817 * not save the order. */
1819 "savefile.improvement_size");
1820 if (improvement_count() > 0) {
1821 const char *buf[improvement_count()];
1822
1823 improvement_iterate(pimprove) {
1824 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1826
1828 "savefile.improvement_vector");
1829 }
1830
1831 /* Save technology order in savegame, so we are not dependent on ruleset
1832 * order. If the game isn't started advances aren't loaded so we can not
1833 * save the order. */
1835 "savefile.technology_size");
1836 if (game.control.num_tech_types > 0) {
1837 const char *buf[game.control.num_tech_types];
1838
1839 buf[A_NONE] = "A_NONE";
1840 advance_iterate(a) {
1844 "savefile.technology_vector");
1845 }
1846
1847 /* Save activities order in the savegame. */
1849 "savefile.activities_size");
1850 if (ACTIVITY_LAST > 0) {
1851 const char **modname;
1852 int j;
1853
1854 i = 0;
1855
1857
1858 for (j = 0; j < ACTIVITY_LAST; j++) {
1860 }
1861
1864 "savefile.activities_vector");
1865 free(modname);
1866 }
1867
1868 /* Save specialists order in the savegame. */
1870 "savefile.specialists_size");
1871 {
1872 const char **modname;
1873
1874 i = 0;
1876
1880
1882 "savefile.specialists_vector");
1883
1884 free(modname);
1885 }
1886
1887 /* Save trait order in savegame. */
1889 "savefile.trait_size");
1890 {
1891 const char **modname;
1892 enum trait tr;
1893 int j;
1894
1895 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1896
1897 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1898 modname[j] = trait_name(tr);
1899 }
1900
1902 "savefile.trait_vector");
1903 free(modname);
1904 }
1905
1906 /* Save extras order in the savegame. */
1908 "savefile.extras_size");
1909 if (game.control.num_extra_types > 0) {
1910 const char **modname;
1911
1912 i = 0;
1914
1915 extra_type_iterate(pextra) {
1916 modname[i++] = extra_rule_name(pextra);
1918
1921 "savefile.extras_vector");
1922 free(modname);
1923 }
1924
1925 /* Save multipliers order in the savegame. */
1927 "savefile.multipliers_size");
1928 if (multiplier_count() > 0) {
1929 const char **modname;
1930
1932
1933 multipliers_iterate(pmul) {
1936
1939 "savefile.multipliers_vector");
1940 free(modname);
1941 }
1942
1943 /* Save city_option order in the savegame. */
1945 "savefile.city_options_size");
1946 if (CITYO_LAST > 0) {
1947 const char **modname;
1948 int j;
1949
1950 i = 0;
1951 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1952
1953 for (j = 0; j < CITYO_LAST; j++) {
1954 modname[i++] = city_options_name(j);
1955 }
1956
1958 CITYO_LAST,
1959 "savefile.city_options_vector");
1960 free(modname);
1961 }
1962
1963 /* Save action order in the savegame. */
1965 "savefile.action_size");
1966 if (NUM_ACTIONS > 0) {
1967 const char **modname;
1968 int j;
1969
1970 i = 0;
1971 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1972
1973 for (j = 0; j < NUM_ACTIONS; j++) {
1975 }
1976
1979 "savefile.action_vector");
1980 free(modname);
1981 }
1982
1983 /* Save action decision order in the savegame. */
1985 "savefile.action_decision_size");
1986 if (ACT_DEC_COUNT > 0) {
1987 const char **modname;
1988 int j;
1989
1990 i = 0;
1992
1993 for (j = 0; j < ACT_DEC_COUNT; j++) {
1995 }
1996
1999 "savefile.action_decision_vector");
2000 free(modname);
2001 }
2002
2003 /* Save server side agent order in the savegame. */
2005 "savefile.server_side_agent_size");
2006 if (SSA_COUNT > 0) {
2007 const char **modname;
2008 int j;
2009
2010 i = 0;
2011 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2012
2013 for (j = 0; j < SSA_COUNT; j++) {
2015 }
2016
2018 SSA_COUNT,
2019 "savefile.server_side_agent_list");
2020 free(modname);
2021 }
2022
2023 /* Save terrain character mapping in the savegame. */
2024 i = 0;
2026 char buf[2];
2027
2028 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2030 buf[1] = '\0';
2031 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2033}
2034
2035/************************************************************************/
2039 const char *option)
2040{
2041 /* Check status and return if not OK (sg_success FALSE). */
2042 sg_check_ret();
2043
2044 if (option == NULL) {
2045 /* no additional option */
2046 return;
2047 }
2048
2049 sz_strlcat(saving->secfile_options, option);
2050 secfile_replace_str(saving->file, saving->secfile_options,
2051 "savefile.options");
2052}
2053
2054/* =======================================================================
2055 * Load / save game status.
2056 * ======================================================================= */
2057
2058/************************************************************************/
2062{
2063 int i;
2064 const char *name;
2065
2066 /* Check status and return if not OK (sg_success FALSE). */
2067 sg_check_ret();
2068
2069 for (i = 0;
2071 "ruledata.government%d.name", i));
2072 i++) {
2074
2075 if (gov != NULL) {
2077 "ruledata.government%d.changes", i);
2078 }
2079 }
2080}
2081
2082/************************************************************************/
2085static void sg_load_game(struct loaddata *loading)
2086{
2087 const char *str;
2088 int i;
2089
2090 /* Check status and return if not OK (sg_success FALSE). */
2091 sg_check_ret();
2092
2093 /* Load server state. */
2094 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2095 "game.server_state");
2096 loading->server_state = server_states_by_name(str, strcmp);
2097 if (!server_states_is_valid(loading->server_state)) {
2098 /* Don't take any risk! */
2099 loading->server_state = S_S_INITIAL;
2100 }
2101
2103 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2104
2107 "game.meta_patches");
2109
2111 /* Do not overwrite this if the user requested a specific metaserver
2112 * from the command line (option --Metaserver). */
2116 "game.meta_server"));
2117 }
2118
2119 if ('\0' == srvarg.serverid[0]) {
2120 /* Do not overwrite this if the user requested a specific metaserver
2121 * from the command line (option --serverid). */
2124 "game.serverid"));
2125 }
2126 sz_strlcpy(server.game_identifier,
2127 secfile_lookup_str_default(loading->file, "", "game.id"));
2128 /* We are not checking game_identifier legality just yet.
2129 * That's done when we are sure that rand seed has been initialized,
2130 * so that we can generate new game_identifier, if needed.
2131 * See sq_load_sanitycheck(). */
2132
2134 "game.phase_mode");
2135 if (str != NULL) {
2138 log_error("Illegal phase mode \"%s\"", str);
2140 }
2141 } else {
2142 log_error("Phase mode missing");
2143 }
2144
2146 "game.phase_mode_stored");
2147 if (str != NULL) {
2150 log_error("Illegal stored phase mode \"%s\"", str);
2152 }
2153 } else {
2154 log_error("Stored phase mode missing");
2155 }
2158 "game.phase");
2162 "game.scoreturn");
2163
2166 "game.timeoutint");
2169 "game.timeoutintinc");
2172 "game.timeoutinc");
2175 "game.timeoutincmult");
2178 "game.timeoutcounter");
2179
2180 game.info.turn
2181 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2183 "game.year"), "%s", secfile_error());
2185 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2186
2188 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2190 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2192 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2193
2195 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2197 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2199 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2200
2201 /* Savegame may have stored random_seed for documentation purposes only,
2202 * but we want to keep it for resaving. */
2203 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2204
2205 /* Global advances. */
2207 "game.global_advances");
2208 if (str != NULL) {
2209 sg_failure_ret(strlen(str) == loading->technology.size,
2210 "Invalid length of 'game.global_advances' ("
2211 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2212 strlen(str), loading->technology.size);
2213 for (i = 0; i < loading->technology.size; i++) {
2214 sg_failure_ret(str[i] == '1' || str[i] == '0',
2215 "Undefined value '%c' within 'game.global_advances'.",
2216 str[i]);
2217 if (str[i] == '1') {
2218 struct advance *padvance =
2219 advance_by_rule_name(loading->technology.order[i]);
2220
2221 if (padvance != NULL) {
2223 }
2224 }
2225 }
2226 }
2227
2229 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2230
2232 = secfile_lookup_int_default(loading->file, 0, "game.last_turn_change_time") / 100.0;
2233}
2234
2235/************************************************************************/
2239{
2240 int set_count = 0;
2241
2243 char path[256];
2244
2245 fc_snprintf(path, sizeof(path),
2246 "ruledata.government%d", set_count++);
2247
2249 "%s.name", path);
2250 secfile_insert_int(saving->file, pgov->changed_to_times,
2251 "%s.changes", path);
2253}
2254
2255/************************************************************************/
2258static void sg_save_game(struct savedata *saving)
2259{
2261 char global_advances[game.control.num_tech_types + 1];
2262 int i;
2263
2264 /* Check status and return if not OK (sg_success FALSE). */
2265 sg_check_ret();
2266
2267 /* Game state: once the game is no longer a new game (ie, has been
2268 * started the first time), it should always be considered a running
2269 * game for savegame purposes. */
2270 if (saving->scenario && !game.scenario.players) {
2272 } else {
2274 }
2276 "game.server_state");
2277
2278 if (game.server.phase_timer != NULL) {
2282 "game.phase_seconds");
2283 }
2284
2286 "game.meta_patches");
2287 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2288
2289 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2290 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2291
2294 "game.phase_mode");
2297 "game.phase_mode_stored");
2299 "game.phase");
2301 "game.scoreturn");
2302
2304 "game.timeoutint");
2306 "game.timeoutintinc");
2308 "game.timeoutinc");
2310 "game.timeoutincmult");
2312 "game.timeoutcounter");
2313
2314 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2315 secfile_insert_int(saving->file, game.info.year, "game.year");
2317 "game.year_0_hack");
2318
2320 "game.globalwarming");
2322 "game.heating");
2324 "game.warminglevel");
2325
2327 "game.nuclearwinter");
2329 "game.cooling");
2331 "game.coolinglevel");
2332 /* For debugging purposes only.
2333 * Do not save it if it's 0 (not known);
2334 * this confuses people reading this 'document' less than
2335 * saving 0. */
2336 if (game.server.seed != 0) {
2338 "game.random_seed");
2339 }
2340
2341 /* Global advances. */
2342 for (i = 0; i < game.control.num_tech_types; i++) {
2343 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2344 }
2345 global_advances[i] = '\0';
2346 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2347
2348 if (!game_was_started()) {
2349 saving->save_players = FALSE;
2350 } else {
2351 if (saving->scenario) {
2352 saving->save_players = game.scenario.players;
2353 } else {
2354 saving->save_players = TRUE;
2355 }
2356#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2358 "game.last_turn_change_time");
2359#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2361 "game.last_turn_change_time");
2362#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2363 }
2364 secfile_insert_bool(saving->file, saving->save_players,
2365 "game.save_players");
2366
2367 if (srv_state != S_S_INITIAL) {
2368 const char *ainames[ai_type_get_count()];
2369
2370 i = 0;
2371 ai_type_iterate(ait) {
2372 ainames[i] = ait->name;
2373 i++;
2375
2377 "game.ai_types");
2378 }
2379}
2380
2381/* =======================================================================
2382 * Load / save random status.
2383 * ======================================================================= */
2384
2385/************************************************************************/
2388static void sg_load_random(struct loaddata *loading)
2389{
2390 /* Check status and return if not OK (sg_success FALSE). */
2391 sg_check_ret();
2392
2393 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2394 const char *str;
2395 int i;
2396
2398 "random.index_J"), "%s", secfile_error());
2400 "random.index_K"), "%s", secfile_error());
2402 "random.index_X"), "%s", secfile_error());
2403
2404 for (i = 0; i < 8; i++) {
2405 str = secfile_lookup_str(loading->file, "random.table%d",i);
2406 sg_failure_ret(NULL != str, "%s", secfile_error());
2407 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2408 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2409 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2410 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2411 }
2412 loading->rstate.is_init = TRUE;
2413 fc_rand_set_state(loading->rstate);
2414 } else {
2415 /* No random values - mark the setting. */
2416 (void) secfile_entry_by_path(loading->file, "random.saved");
2417
2418 /* We're loading a game without a seed (which is okay, if it's a scenario).
2419 * We need to generate the game seed now because it will be needed later
2420 * during the load. */
2422 loading->rstate = fc_rand_state();
2423 }
2424}
2425
2426/************************************************************************/
2429static void sg_save_random(struct savedata *saving)
2430{
2431 /* Check status and return if not OK (sg_success FALSE). */
2432 sg_check_ret();
2433
2434 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2435 int i;
2436 RANDOM_STATE rstate = fc_rand_state();
2437
2438 secfile_insert_bool(saving->file, TRUE, "random.saved");
2439 fc_assert(rstate.is_init);
2440
2441 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2442 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2443 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2444
2445 for (i = 0; i < 8; i++) {
2446 char vec[100];
2447
2448 fc_snprintf(vec, sizeof(vec),
2449 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2450 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2451 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2452 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2453 secfile_insert_str(saving->file, vec, "random.table%d", i);
2454 }
2455 } else {
2456 secfile_insert_bool(saving->file, FALSE, "random.saved");
2457 }
2458}
2459
2460/* =======================================================================
2461 * Load / save lua script data.
2462 * ======================================================================= */
2463
2464/************************************************************************/
2467static void sg_load_script(struct loaddata *loading)
2468{
2469 /* Check status and return if not OK (sg_success FALSE). */
2470 sg_check_ret();
2471
2473}
2474
2475/************************************************************************/
2478static void sg_save_script(struct savedata *saving)
2479{
2480 /* Check status and return if not OK (sg_success FALSE). */
2481 sg_check_ret();
2482
2484}
2485
2486/* =======================================================================
2487 * Load / save scenario data.
2488 * ======================================================================= */
2489
2490/************************************************************************/
2494{
2495 const char *buf;
2496 int game_version;
2497
2498 /* Check status and return if not OK (sg_success FALSE). */
2499 sg_check_ret();
2500
2501 /* Load version. */
2503 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2504 /* We require at least version 2.90.99 - and at that time we saved version
2505 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2506 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2507 "version 2.90.99 required.");
2508
2509 loading->full_version = game_version;
2510
2511 game.scenario.datafile[0] = '\0';
2512
2514 "scenario.is_scenario"), "%s", secfile_error());
2515 if (!game.scenario.is_scenario) {
2516 return;
2517 }
2518
2519 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2520 if (buf[0] != '\0') {
2522 }
2523
2525 "scenario.authors");
2526 if (buf[0] != '\0') {
2528 } else {
2529 game.scenario.authors[0] = '\0';
2530 }
2531
2533 "scenario.description");
2534 if (buf[0] != '\0') {
2536 } else {
2537 game.scenario_desc.description[0] = '\0';
2538 }
2540 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2542 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2545 "scenario.startpos_nations");
2548 "scenario.prevent_new_cities");
2551 "scenario.lake_flooding");
2554 "scenario.handmade");
2557 "scenario.allow_ai_type_fallback");
2558
2561 "scenario.ruleset_locked");
2562
2564 "scenario.datafile");
2565 if (buf[0] != '\0') {
2567 }
2568
2569 sg_failure_ret(loading->server_state == S_S_INITIAL
2570 || (loading->server_state == S_S_RUNNING
2571 && game.scenario.players),
2572 "Invalid scenario definition (server state '%s' and "
2573 "players are %s).",
2574 server_states_name(loading->server_state),
2575 game.scenario.players ? "saved" : "not saved");
2576}
2577
2578/************************************************************************/
2582{
2583 struct entry *mod_entry;
2584 int game_version;
2585
2586 /* Check status and return if not OK (sg_success FALSE). */
2587 sg_check_ret();
2588
2589 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2590#ifdef EMERGENCY_VERSION
2592#endif /* EMERGENCY_VERSION */
2593 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2594
2595 if (!saving->scenario || !game.scenario.is_scenario) {
2596 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2597 return;
2598 }
2599
2600 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2601
2602 /* Name is mandatory to the level that is saved even if empty. */
2603 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2605
2606 /* Authors list is saved only if it exist */
2607 if (game.scenario.authors[0] != '\0') {
2609 "scenario.authors");
2611 }
2612
2613 /* Description is saved only if it exist */
2614 if (game.scenario_desc.description[0] != '\0') {
2616 "scenario.description");
2618 }
2619
2620 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2621 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2623 "scenario.startpos_nations");
2626 "scenario.prevent_new_cities");
2627 }
2629 "scenario.lake_flooding");
2630 if (game.scenario.handmade) {
2632 "scenario.handmade");
2633 }
2636 "scenario.allow_ai_type_fallback");
2637 }
2638
2639 if (game.scenario.datafile[0] != '\0') {
2641 "scenario.datafile");
2642 }
2644 "scenario.ruleset_locked");
2645 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2647 "scenario.ruleset_caps");
2648 }
2649}
2650
2651/* =======================================================================
2652 * Load / save game settings.
2653 * ======================================================================= */
2654
2655/************************************************************************/
2659{
2660 /* Check status and return if not OK (sg_success FALSE). */
2661 sg_check_ret();
2662
2663 settings_game_load(loading->file, "settings");
2664
2665 /* Save current status of fogofwar. */
2667
2668 /* Add all compatibility settings here. */
2669}
2670
2671/************************************************************************/
2675{
2677
2678 /* Check status and return if not OK (sg_success FALSE). */
2679 sg_check_ret();
2680
2681 if (saving->scenario) {
2682 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2683 }
2684
2685 settings_game_save(saving->file, "settings");
2686 /* Restore real map generator. */
2688
2689 /* Add all compatibility settings here. */
2690}
2691
2692
2693/************************************************************************/
2697{
2698 struct city *pcity;
2699 int i, j;
2700 size_t length, length2;
2701 int *city_count;
2703 "savefile.city_counters_order_size");
2704
2705 if (0==length) {
2706
2707 return;
2708 }
2709
2710 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2711
2712 sg_failure_ret(loading->counter.order != 0,
2713 "Failed to load counter's ruleset order: %s",
2714 secfile_error());
2715 sg_failure_ret(loading->counter.size = length,
2716 "Counter vector in savegame have bad size: %s",
2717 secfile_error());
2718
2719 int corder[length];
2720
2721 for (i = 0; i < length; i++) {
2722
2723 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2725 }
2726
2727 i = 0;
2728 while (NULL != (city_count =
2730 "counters.c%d", i))) {
2731
2732 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);
2733
2734 pcity = game_city_by_number(city_count[0]);
2735
2736 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2737
2738 for (j = 0; j < length; j++) {
2739
2740 pcity->counter_values[corder[j]] = city_count[j+1];
2741 }
2742 i++;
2743 }
2744}
2745
2746/************************************************************************/
2750{
2751 /* Check status and return if not OK (sg_success FALSE). */
2752 sg_check_ret();
2753
2754 const char **countnames;;
2755 int *countvalues;
2756 int i, j, count;
2757
2759
2760 secfile_insert_int(saving->file, count,
2761 "savefile.city_counters_order_size");
2762
2763 if (0 == count) {
2764
2765 return;
2766 }
2767
2768 countnames = fc_calloc(count, sizeof(*countnames));
2769 for (j = 0; j < count; j++) {
2771 }
2772
2774 "savefile.city_counters_order_vector");
2775
2777
2778 // Saving city's counters
2779
2780 j = 0;
2781 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2782
2784
2785 city_list_iterate(_pplayer->cities, pcity) {
2786
2787 countvalues[0] = pcity->id;
2788 for (i = 0; i < count; ++i) {
2789
2790 countvalues[i+1] = pcity->counter_values[i];
2791 }
2792
2793 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2794 ++j;
2797
2799}
2800
2801/* =======================================================================
2802 * Load / save the main map.
2803 * ======================================================================= */
2804
2805/************************************************************************/
2808static void sg_load_map(struct loaddata *loading)
2809{
2810 /* Check status and return if not OK (sg_success FALSE). */
2811 sg_check_ret();
2812
2813 /* This defaults to TRUE even if map has not been generated.
2814 * We rely on that
2815 * 1) scenario maps have it explicitly right.
2816 * 2) when map is actually generated, it re-initialize this to FALSE. */
2818 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2820 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2821
2823
2824 /* Savegame may have stored random_seed for documentation purposes only,
2825 * but we want to keep it for resaving. */
2827 = secfile_lookup_int_default(loading->file, 0, "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 secfile_entry_ignore(loading->file, "game.save_known");
2841
2842 return;
2843 }
2844
2845 if (S_S_INITIAL == loading->server_state) {
2846 /* Nothing more to do if it is not a scenario but in initial state. */
2847 return;
2848 }
2849
2856}
2857
2858/************************************************************************/
2861static void sg_save_map(struct savedata *saving)
2862{
2863 /* Check status and return if not OK (sg_success FALSE). */
2864 sg_check_ret();
2865
2866 if (map_is_empty()) {
2867 /* No map. */
2868 return;
2869 }
2870
2871 if (saving->scenario) {
2873 "map.have_huts");
2875 "map.have_resources");
2876 } else {
2877 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2878 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2879 }
2880
2881 /* For debugging purposes only.
2882 * Do not save it if it's 0 (not known);
2883 * this confuses people reading this 'document' less than
2884 * saving 0. */
2885 if (wld.map.server.seed != 0) {
2887 "map.random_seed");
2888 }
2889
2896}
2897
2898/************************************************************************/
2902{
2903 /* Check status and return if not OK (sg_success FALSE). */
2904 sg_check_ret();
2905
2906 /* Initialize the map for the current topology. 'map.xsize' and
2907 * 'map.ysize' must be set. */
2909
2910 /* Allocate map. */
2912
2913 /* get the terrain type */
2914 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2915 "map.t%04d");
2917
2918 /* Check for special tile sprites. */
2919 whole_map_iterate(&(wld.map), ptile) {
2920 const char *spec_sprite;
2921 const char *label;
2922 int nat_x, nat_y;
2923
2925 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2926 nat_x, nat_y);
2927 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2928 nat_x, nat_y);
2929 if (NULL != ptile->spec_sprite) {
2930 ptile->spec_sprite = fc_strdup(spec_sprite);
2931 }
2932 if (label != NULL) {
2933 tile_set_label(ptile, label);
2934 }
2936}
2937
2938/************************************************************************/
2942{
2943 /* Check status and return if not OK (sg_success FALSE). */
2944 sg_check_ret();
2945
2946 /* Save the terrain type. */
2947 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2948 "map.t%04d");
2949
2950 /* Save special tile sprites. */
2951 whole_map_iterate(&(wld.map), ptile) {
2952 int nat_x, nat_y;
2953
2955 if (ptile->spec_sprite) {
2956 secfile_insert_str(saving->file, ptile->spec_sprite,
2957 "map.spec_sprite_%d_%d", nat_x, nat_y);
2958 }
2959 if (ptile->label != NULL) {
2960 secfile_insert_str(saving->file, ptile->label,
2961 "map.label_%d_%d", nat_x, nat_y);
2962 }
2964}
2965
2966/************************************************************************/
2970{
2971 /* Check status and return if not OK (sg_success FALSE). */
2972 sg_check_ret();
2973
2974 /* Load extras. */
2975 halfbyte_iterate_extras(j, loading->extra.size) {
2976 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
2977 loading->extra.order + 4 * j),
2978 loading->file, "map.e%02d_%04d", j);
2980
2981 if (S_S_INITIAL != loading->server_state
2984 whole_map_iterate(&(wld.map), ptile) {
2986 if (tile_has_extra(ptile, pres)) {
2987 tile_set_resource(ptile, pres);
2988
2989 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
2990 BV_CLR(ptile->extras, extra_index(pres));
2991 }
2992 }
2995 }
2996}
2997
2998/************************************************************************/
3002{
3003 /* Check status and return if not OK (sg_success FALSE). */
3004 sg_check_ret();
3005
3006 /* Save extras. */
3008 int mod[4];
3009 int l;
3010
3011 for (l = 0; l < 4; l++) {
3012 if (4 * j + 1 > game.control.num_extra_types) {
3013 mod[l] = -1;
3014 } else {
3015 mod[l] = 4 * j + l;
3016 }
3017 }
3018 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3019 saving->file, "map.e%02d_%04d", j);
3021}
3022
3023/************************************************************************/
3028{
3029 struct nation_type *pnation;
3030 struct startpos *psp;
3031 struct tile *ptile;
3032 const char SEPARATOR = '#';
3033 const char *nation_names;
3034 int nat_x, nat_y;
3035 bool exclude;
3036 int i, startpos_count;
3037
3038 /* Check status and return if not OK (sg_success FALSE). */
3039 sg_check_ret();
3040
3042 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3043
3044 if (0 == startpos_count) {
3045 /* Nothing to do. */
3046 return;
3047 }
3048
3049 for (i = 0; i < startpos_count; i++) {
3050 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3051 || !secfile_lookup_int(loading->file, &nat_y,
3052 "map.startpos%d.y", i)) {
3053 log_sg("Warning: Undefined coordinates for startpos %d", i);
3054 continue;
3055 }
3056
3057 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3058 if (NULL == ptile) {
3059 log_error("Start position native coordinates (%d, %d) do not exist "
3060 "in this map. Skipping...", nat_x, nat_y);
3061 continue;
3062 }
3063
3064 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3065 "map.startpos%d.exclude", i);
3066
3067 psp = map_startpos_new(ptile);
3068
3070 "map.startpos%d.nations", i);
3071 if (NULL != nation_names && '\0' != nation_names[0]) {
3072 const size_t size = strlen(nation_names) + 1;
3073 char buf[size], *start, *end;
3074
3076 for (start = buf - 1; NULL != start; start = end) {
3077 start++;
3078 if ((end = strchr(start, SEPARATOR))) {
3079 *end = '\0';
3080 }
3081
3082 pnation = nation_by_rule_name(start);
3083 if (NO_NATION_SELECTED != pnation) {
3084 if (exclude) {
3085 startpos_disallow(psp, pnation);
3086 } else {
3087 startpos_allow(psp, pnation);
3088 }
3089 } else {
3090 log_verbose("Missing nation \"%s\".", start);
3091 }
3092 }
3093 }
3094 }
3095
3096 if (0 < map_startpos_count()
3097 && loading->server_state == S_S_INITIAL
3099 log_verbose("Number of starts (%d) are lower than rules.max_players "
3100 "(%d), lowering rules.max_players.",
3103 }
3104
3105 /* Re-initialize nation availability in light of start positions.
3106 * This has to be after loading [scenario] and [map].startpos and
3107 * before we seek nations for players. */
3109}
3110
3111/************************************************************************/
3115{
3116 struct tile *ptile;
3117 const char SEPARATOR = '#';
3118 int i = 0;
3119
3120 /* Check status and return if not OK (sg_success FALSE). */
3121 sg_check_ret();
3122
3124 return;
3125 }
3126
3128 "map.startpos_count");
3129
3131 int nat_x, nat_y;
3132
3133 ptile = startpos_tile(psp);
3134
3136 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3137 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3138
3140 "map.startpos%d.exclude", i);
3141 if (startpos_allows_all(psp)) {
3142 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3143 } else {
3144 const struct nation_hash *nations = startpos_raw_nations(psp);
3146
3147 nation_names[0] = '\0';
3148 nation_hash_iterate(nations, pnation) {
3149 if ('\0' == nation_names[0]) {
3151 sizeof(nation_names));
3152 } else {
3154 "%c%s", SEPARATOR, nation_rule_name(pnation));
3155 }
3158 "map.startpos%d.nations", i);
3159 }
3160 i++;
3162
3164}
3165
3166/************************************************************************/
3170{
3171 int x, y;
3172 struct tile *claimer = NULL;
3173 struct extra_type *placing = NULL;
3174
3175 /* Check status and return if not OK (sg_success FALSE). */
3176 sg_check_ret();
3177
3178 if (game.info.is_new_game) {
3179 /* No owner/source information for a new game / scenario. */
3180 return;
3181 }
3182
3183 /* Owner, ownership source, and infra turns are stored as plain numbers */
3184 for (y = 0; y < wld.map.ysize; y++) {
3185 const char *buffer1 = secfile_lookup_str(loading->file,
3186 "map.owner%04d", y);
3187 const char *buffer2 = secfile_lookup_str(loading->file,
3188 "map.source%04d", y);
3189 const char *buffer3 = secfile_lookup_str(loading->file,
3190 "map.eowner%04d", y);
3192 NULL,
3193 "map.placing%04d", y);
3195 NULL,
3196 "map.infra_turns%04d", y);
3197 const char *ptr1 = buffer1;
3198 const char *ptr2 = buffer2;
3199 const char *ptr3 = buffer3;
3200 const char *ptr_placing = buffer_placing;
3201 const char *ptr_turns = buffer_turns;
3202
3206
3207 for (x = 0; x < wld.map.xsize; x++) {
3208 char token1[TOKEN_SIZE];
3209 char token2[TOKEN_SIZE];
3210 char token3[TOKEN_SIZE];
3212 char token_turns[TOKEN_SIZE];
3213 struct player *owner = NULL;
3214 struct player *eowner = NULL;
3215 int turns;
3216 int number;
3217 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3218
3219 scanin(&ptr1, ",", token1, sizeof(token1));
3220 sg_failure_ret(token1[0] != '\0',
3221 "Map size not correct (map.owner%d).", y);
3222 if (strcmp(token1, "-") == 0) {
3223 owner = NULL;
3224 } else {
3226 "Got map owner %s in (%d, %d).", token1, x, y);
3227 owner = player_by_number(number);
3228 }
3229
3230 scanin(&ptr2, ",", token2, sizeof(token2));
3231 sg_failure_ret(token2[0] != '\0',
3232 "Map size not correct (map.source%d).", y);
3233 if (strcmp(token2, "-") == 0) {
3234 claimer = NULL;
3235 } else {
3237 "Got map source %s in (%d, %d).", token2, x, y);
3238 claimer = index_to_tile(&(wld.map), number);
3239 }
3240
3241 scanin(&ptr3, ",", token3, sizeof(token3));
3242 sg_failure_ret(token3[0] != '\0',
3243 "Map size not correct (map.eowner%d).", y);
3244 if (strcmp(token3, "-") == 0) {
3245 eowner = NULL;
3246 } else {
3248 "Got base owner %s in (%d, %d).", token3, x, y);
3249 eowner = player_by_number(number);
3250 }
3251
3252 if (ptr_placing != NULL) {
3254 sg_failure_ret(token_placing[0] != '\0',
3255 "Map size not correct (map.placing%d).", y);
3256 if (strcmp(token_placing, "-") == 0) {
3257 placing = NULL;
3258 } else {
3260 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3261 placing = extra_by_number(number);
3262 }
3263 } else {
3264 placing = NULL;
3265 }
3266
3267 if (ptr_turns != NULL) {
3268 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3269 sg_failure_ret(token_turns[0] != '\0',
3270 "Map size not correct (map.infra_turns%d).", y);
3272 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3273 turns = number;
3274 } else {
3275 turns = 1;
3276 }
3277
3279 tile_claim_bases(ptile, eowner);
3280 ptile->placing = placing;
3281 ptile->infra_turns = turns;
3282 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3283 }
3284 }
3285}
3286
3287/************************************************************************/
3291{
3292 int x, y;
3293
3294 /* Check status and return if not OK (sg_success FALSE). */
3295 sg_check_ret();
3296
3297 if (saving->scenario && !saving->save_players) {
3298 /* Nothing to do for a scenario without saved players. */
3299 return;
3300 }
3301
3302 /* Store owner and ownership source as plain numbers. */
3303 for (y = 0; y < wld.map.ysize; y++) {
3304 char line[wld.map.xsize * TOKEN_SIZE];
3305
3306 line[0] = '\0';
3307 for (x = 0; x < wld.map.xsize; x++) {
3308 char token[TOKEN_SIZE];
3309 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3310
3311 if (!saving->save_players || tile_owner(ptile) == NULL) {
3312 strcpy(token, "-");
3313 } else {
3314 fc_snprintf(token, sizeof(token), "%d",
3315 player_number(tile_owner(ptile)));
3316 }
3317 strcat(line, token);
3318 if (x + 1 < wld.map.xsize) {
3319 strcat(line, ",");
3320 }
3321 }
3322 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3323 }
3324
3325 for (y = 0; y < wld.map.ysize; y++) {
3326 char line[wld.map.xsize * TOKEN_SIZE];
3327
3328 line[0] = '\0';
3329 for (x = 0; x < wld.map.xsize; x++) {
3330 char token[TOKEN_SIZE];
3331 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3332
3333 if (ptile->claimer == NULL) {
3334 strcpy(token, "-");
3335 } else {
3336 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3337 }
3338 strcat(line, token);
3339 if (x + 1 < wld.map.xsize) {
3340 strcat(line, ",");
3341 }
3342 }
3343 secfile_insert_str(saving->file, line, "map.source%04d", y);
3344 }
3345
3346 for (y = 0; y < wld.map.ysize; y++) {
3347 char line[wld.map.xsize * TOKEN_SIZE];
3348
3349 line[0] = '\0';
3350 for (x = 0; x < wld.map.xsize; x++) {
3351 char token[TOKEN_SIZE];
3352 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3353
3354 if (!saving->save_players || extra_owner(ptile) == NULL) {
3355 strcpy(token, "-");
3356 } else {
3357 fc_snprintf(token, sizeof(token), "%d",
3358 player_number(extra_owner(ptile)));
3359 }
3360 strcat(line, token);
3361 if (x + 1 < wld.map.xsize) {
3362 strcat(line, ",");
3363 }
3364 }
3365 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3366 }
3367
3368 for (y = 0; y < wld.map.ysize; y++) {
3369 char line[wld.map.xsize * TOKEN_SIZE];
3370
3371 line[0] = '\0';
3372 for (x = 0; x < wld.map.xsize; x++) {
3373 char token[TOKEN_SIZE];
3374 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3375
3376 if (ptile->placing == NULL) {
3377 strcpy(token, "-");
3378 } else {
3379 fc_snprintf(token, sizeof(token), "%d",
3380 extra_number(ptile->placing));
3381 }
3382 strcat(line, token);
3383 if (x + 1 < wld.map.xsize) {
3384 strcat(line, ",");
3385 }
3386 }
3387 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3388 }
3389
3390 for (y = 0; y < wld.map.ysize; y++) {
3391 char line[wld.map.xsize * TOKEN_SIZE];
3392
3393 line[0] = '\0';
3394 for (x = 0; x < wld.map.xsize; x++) {
3395 char token[TOKEN_SIZE];
3396 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3397
3398 if (ptile->placing != NULL) {
3399 fc_snprintf(token, sizeof(token), "%d",
3400 ptile->infra_turns);
3401 } else {
3402 fc_snprintf(token, sizeof(token), "0");
3403 }
3404 strcat(line, token);
3405 if (x + 1 < wld.map.xsize) {
3406 strcat(line, ",");
3407 }
3408 }
3409 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3410 }
3411}
3412
3413/************************************************************************/
3417{
3418 int x, y;
3419
3420 /* Check status and return if not OK (sg_success FALSE). */
3421 sg_check_ret();
3422
3423 sg_failure_ret(loading->worked_tiles == NULL,
3424 "City worked map not loaded!");
3425
3426 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3427 sizeof(*loading->worked_tiles));
3428
3429 for (y = 0; y < wld.map.ysize; y++) {
3430 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3431 y);
3432 const char *ptr = buffer;
3433
3434 sg_failure_ret(NULL != buffer,
3435 "Savegame corrupt - map line %d not found.", y);
3436 for (x = 0; x < wld.map.xsize; x++) {
3437 char token[TOKEN_SIZE];
3438 int number;
3439 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3440
3441 scanin(&ptr, ",", token, sizeof(token));
3442 sg_failure_ret('\0' != token[0],
3443 "Savegame corrupt - map size not correct.");
3444 if (strcmp(token, "-") == 0) {
3445 number = -1;
3446 } else {
3447 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3448 "Savegame corrupt - got tile worked by city "
3449 "id=%s in (%d, %d).", token, x, y);
3450 }
3451
3452 loading->worked_tiles[ptile->index] = number;
3453 }
3454 }
3455}
3456
3457/************************************************************************/
3461{
3462 int x, y;
3463
3464 /* Check status and return if not OK (sg_success FALSE). */
3465 sg_check_ret();
3466
3467 if (saving->scenario && !saving->save_players) {
3468 /* Nothing to do for a scenario without saved players. */
3469 return;
3470 }
3471
3472 /* additionally save the tiles worked by the cities */
3473 for (y = 0; y < wld.map.ysize; y++) {
3474 char line[wld.map.xsize * TOKEN_SIZE];
3475
3476 line[0] = '\0';
3477 for (x = 0; x < wld.map.xsize; x++) {
3478 char token[TOKEN_SIZE];
3479 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3480 struct city *pcity = tile_worked(ptile);
3481
3482 if (pcity == NULL) {
3483 strcpy(token, "-");
3484 } else {
3485 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3486 }
3487 strcat(line, token);
3488 if (x < wld.map.xsize) {
3489 strcat(line, ",");
3490 }
3491 }
3492 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3493 }
3494}
3495
3496/************************************************************************/
3500{
3501 /* Check status and return if not OK (sg_success FALSE). */
3502 sg_check_ret();
3503
3504 players_iterate(pplayer) {
3505 /* Allocate player private map here; it is needed in different modules
3506 * besides this one ((i.e. sg_load_player_*()). */
3507 player_map_init(pplayer);
3509
3511 "game.save_known")) {
3512 int lines = player_slot_max_used_number() / 32 + 1;
3513 int j, p, l, i;
3514 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3515
3516 for (l = 0; l < lines; l++) {
3517 for (j = 0; j < 8; j++) {
3518 for (i = 0; i < 4; i++) {
3519 /* Only bother trying to load the map for this halfbyte if at least
3520 * one of the corresponding player slots is in use. */
3521 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3522 LOAD_MAP_CHAR(ch, ptile,
3523 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3524 |= ascii_hex2bin(ch, j),
3525 loading->file, "map.k%02d_%04d", l * 8 + j);
3526 break;
3527 }
3528 }
3529 }
3530 }
3531
3532 players_iterate(pplayer) {
3533 dbv_clr_all(&pplayer->tile_known);
3535
3536 /* HACK: we read the known data from hex into 32-bit integers, and
3537 * now we convert it to the known tile data of each player. */
3538 whole_map_iterate(&(wld.map), ptile) {
3539 players_iterate(pplayer) {
3540 p = player_index(pplayer);
3541 l = player_index(pplayer) / 32;
3542
3543 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3544 map_set_known(ptile, pplayer);
3545 }
3548
3549 FC_FREE(known);
3550 }
3551}
3552
3553/************************************************************************/
3557{
3558 /* Check status and return if not OK (sg_success FALSE). */
3559 sg_check_ret();
3560
3561 if (!saving->save_players) {
3562 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3563 return;
3564 } else {
3565 int lines = player_slot_max_used_number() / 32 + 1;
3566
3568 "game.save_known");
3570 int j, p, l, i;
3571 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3572
3573 /* HACK: we convert the data into a 32-bit integer, and then save it as
3574 * hex. */
3575
3576 whole_map_iterate(&(wld.map), ptile) {
3577 players_iterate(pplayer) {
3578 if (map_is_known(ptile, pplayer)) {
3579 p = player_index(pplayer);
3580 l = p / 32;
3581 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3582 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3583 }
3586
3587 for (l = 0; l < lines; l++) {
3588 for (j = 0; j < 8; j++) {
3589 for (i = 0; i < 4; i++) {
3590 /* Only bother saving the map for this halfbyte if at least one
3591 * of the corresponding player slots is in use */
3592 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3593 /* put 4-bit segments of the 32-bit "known" field */
3595 + tile_index(ptile)], j),
3596 saving->file, "map.k%02d_%04d", l * 8 + j);
3597 break;
3598 }
3599 }
3600 }
3601 }
3602
3603 FC_FREE(known);
3604 }
3605 }
3606}
3607
3608/* =======================================================================
3609 * Load / save player data.
3610 *
3611 * This is split into two parts as some data can only be loaded if the
3612 * number of players is known and the corresponding player slots are
3613 * defined.
3614 * ======================================================================= */
3615
3616/************************************************************************/
3620{
3621 int i, k, nplayers;
3622 const char *str;
3623 bool shuffle_loaded = TRUE;
3624
3625 /* Check status and return if not OK (sg_success FALSE). */
3626 sg_check_ret();
3627
3628 if (S_S_INITIAL == loading->server_state
3629 || game.info.is_new_game) {
3630 /* Nothing more to do. */
3631 return;
3632 }
3633
3634 /* Load destroyed wonders: */
3636 "players.destroyed_wonders");
3637 sg_failure_ret(str != NULL, "%s", secfile_error());
3638 sg_failure_ret(strlen(str) == loading->improvement.size,
3639 "Invalid length for 'players.destroyed_wonders' ("
3640 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3641 strlen(str), loading->improvement.size);
3642 for (k = 0; k < loading->improvement.size; k++) {
3643 sg_failure_ret(str[k] == '1' || str[k] == '0',
3644 "Undefined value '%c' within "
3645 "'players.destroyed_wonders'.", str[k]);
3646
3647 if (str[k] == '1') {
3648 struct impr_type *pimprove =
3649 improvement_by_rule_name(loading->improvement.order[k]);
3650 if (pimprove) {
3653 }
3654 }
3655 }
3656
3657 server.identity_number
3658 = secfile_lookup_int_default(loading->file, server.identity_number,
3659 "players.identity_number_used");
3660
3661 /* First remove all defined players. */
3662 players_iterate(pplayer) {
3663 server_remove_player(pplayer);
3665
3666 /* Now, load the players from the savefile. */
3667 player_slots_iterate(pslot) {
3668 struct player *pplayer;
3669 struct rgbcolor *prgbcolor = NULL;
3670 int pslot_id = player_slot_index(pslot);
3671
3672 if (NULL == secfile_section_lookup(loading->file, "player%d",
3673 pslot_id)) {
3674 continue;
3675 }
3676
3677 /* Get player AI type. */
3678 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3679 player_slot_index(pslot));
3680 sg_failure_ret(str != NULL, "%s", secfile_error());
3681
3682 /* Get player color */
3683 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3684 pslot_id)) {
3685 if (game_was_started()) {
3686 log_sg("Game has started, yet player %d has no color defined.",
3687 pslot_id);
3688 /* This will be fixed up later */
3689 } else {
3690 log_verbose("No color defined for player %d.", pslot_id);
3691 /* Colors will be assigned on game start, or at end of savefile
3692 * loading if game has already started */
3693 }
3694 }
3695
3696 /* Create player. */
3697 pplayer = server_create_player(player_slot_index(pslot), str,
3698 prgbcolor,
3701 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3702
3703 server_player_init(pplayer, FALSE, FALSE);
3704
3705 /* Free the color definition. */
3707
3708 /* Multipliers (policies) */
3709
3710 /* First initialise player values with ruleset defaults; this will
3711 * cover any in the ruleset not known when the savefile was created. */
3712 multipliers_iterate(pmul) {
3713 pplayer->multipliers[multiplier_index(pmul)].value
3714 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3716
3717 /* Now override with any values from the savefile. */
3718 for (k = 0; k < loading->multiplier.size; k++) {
3719 const struct multiplier *pmul = loading->multiplier.order[k];
3720
3721 if (pmul) {
3723 int val =
3725 "player%d.multiplier%d.val",
3726 player_slot_index(pslot), k);
3727 int rval = (((CLIP(pmul->start, val, pmul->stop)
3728 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3729
3730 if (rval != val) {
3731 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3732 "was %d, clamped to %d", pslot_id,
3733 multiplier_rule_name(pmul), val, rval);
3734 }
3735 pplayer->multipliers[idx].value = rval;
3736
3737 val =
3739 pplayer->multipliers[idx].value,
3740 "player%d.multiplier%d.target",
3741 player_slot_index(pslot), k);
3742 rval = (((CLIP(pmul->start, val, pmul->stop)
3743 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3744
3745 if (rval != val) {
3746 log_verbose("Player %d had illegal value for multiplier_target "
3747 " \"%s\": was %d, clamped to %d", pslot_id,
3748 multiplier_rule_name(pmul), val, rval);
3749 }
3750 pplayer->multipliers[idx].target = rval;
3751
3752 pplayer->multipliers[idx].changed
3754 "player%d.multiplier%d.changed",
3755 player_slot_index(pslot), k);
3756 } /* else silently discard multiplier not in current ruleset */
3757 }
3758
3759 /* Must be loaded before tile owner is set. */
3760 pplayer->server.border_vision =
3762 "player%d.border_vision",
3763 player_slot_index(pslot));
3764
3766 "player%d.autoselect_weight",
3767 pslot_id);
3769
3770 /* check number of players */
3771 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3772 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3773 "(%d) from the loaded game does not match the number of "
3774 "players present (%d).", nplayers, player_count());
3775
3776 /* Load team information. */
3777 players_iterate(pplayer) {
3778 int team;
3779 struct team_slot *tslot = NULL;
3780
3782 "player%d.team_no",
3783 player_number(pplayer))
3785 "Invalid team definition for player %s (nb %d).",
3786 player_name(pplayer), player_number(pplayer));
3787 /* Should never fail when slot given is not NULL */
3788 team_add_player(pplayer, team_new(tslot));
3790
3791 /* Loading the shuffle list is quite complex. At the time of saving the
3792 * shuffle data is saved as
3793 * shuffled_player_<number> = player_slot_id
3794 * where number is an increasing number and player_slot_id is a number
3795 * between 0 and the maximum number of player slots. Now we have to create
3796 * a list
3797 * shuffler_players[number] = player_slot_id
3798 * where all player slot IDs are used exactly one time. The code below
3799 * handles this ... */
3800 if (secfile_lookup_int_default(loading->file, -1,
3801 "players.shuffled_player_%d", 0) >= 0) {
3802 int slots = player_slot_count();
3803 int plrcount = player_count();
3806
3807 for (i = 0; i < slots; i++) {
3808 /* Array to save used numbers. */
3810 /* List of all player IDs (needed for set_shuffled_players()). It is
3811 * initialised with the value -1 to indicate that no value is set. */
3812 shuffled_players[i] = -1;
3813 }
3814
3815 /* Load shuffled player list. */
3816 for (i = 0; i < plrcount; i++) {
3817 int shuffle
3819 "players.shuffled_player_%d", i);
3820
3821 if (shuffle == -1) {
3822 log_sg("Missing player shuffle information (index %d) "
3823 "- reshuffle player list!", i);
3825 break;
3826 } else if (shuffled_player_set[shuffle]) {
3827 log_sg("Player shuffle %d used two times "
3828 "- reshuffle player list!", shuffle);
3830 break;
3831 }
3832 /* Set this ID as used. */
3834
3835 /* Save the player ID in the shuffle list. */
3837 }
3838
3839 if (shuffle_loaded) {
3840 /* Insert missing numbers. */
3841 int shuffle_index = plrcount;
3842
3843 for (i = 0; i < slots; i++) {
3844 if (!shuffled_player_set[i]) {
3846 }
3847
3848 /* shuffle_index must not grow higher than size of shuffled_players. */
3850 "Invalid player shuffle data!");
3851 }
3852
3853#ifdef FREECIV_DEBUG
3854 log_debug("[load shuffle] player_count() = %d", player_count());
3855 player_slots_iterate(pslot) {
3856 int plrid = player_slot_index(pslot);
3857
3858 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3860 shuffled_player_set[plrid] ? "is used" : "-");
3862#endif /* FREECIV_DEBUG */
3863
3864 /* Set shuffle list from savegame. */
3866 }
3867 }
3868
3869 if (!shuffle_loaded) {
3870 /* No shuffled players included or error loading them, so shuffle them
3871 * (this may include scenarios). */
3873 }
3874}
3875
3876/************************************************************************/
3880{
3881 /* Check status and return if not OK (sg_success FALSE). */
3882 sg_check_ret();
3883
3884 if (game.info.is_new_game) {
3885 /* Nothing to do. */
3886 return;
3887 }
3888
3889 players_iterate(pplayer) {
3890 sg_load_player_main(loading, pplayer);
3892 sg_load_player_units(loading, pplayer);
3894
3895 /* Check the success of the functions above. */
3896 sg_check_ret();
3897
3898 /* Print out some information */
3899 if (is_ai(pplayer)) {
3900 log_normal(_("%s has been added as %s level AI-controlled player "
3901 "(%s)."), player_name(pplayer),
3902 ai_level_translated_name(pplayer->ai_common.skill_level),
3903 ai_name(pplayer->ai));
3904 } else {
3905 log_normal(_("%s has been added as human player."),
3906 player_name(pplayer));
3907 }
3909
3910 /* Also load the transport status of the units here. It must be a special
3911 * case as all units must be known (unit on an allied transporter). */
3912 players_iterate(pplayer) {
3913 /* Load unit transport status. */
3916
3917 /* Savegame may contain nation assignments that are incompatible with the
3918 * current nationset. Ensure they are compatible, one way or another. */
3920
3921 /* Some players may have invalid nations in the ruleset. Once all players
3922 * are loaded, pick one of the remaining nations for them. */
3923 players_iterate(pplayer) {
3924 if (pplayer->nation == NO_NATION_SELECTED) {
3927 /* TRANS: Minor error message: <Leader> ... <Poles>. */
3928 log_sg(_("%s had invalid nation; changing to %s."),
3929 player_name(pplayer), nation_plural_for_player(pplayer));
3930
3931 ai_traits_init(pplayer);
3932 }
3934
3935 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
3938 if (pplayers_allied(plr, aplayer)) {
3940 DS_ALLIANCE);
3941
3944 log_sg("Illegal alliance structure detected: "
3945 "%s alliance to %s reduced to peace treaty.",
3950 }
3951 }
3954
3955 /* Update cached city illness. This can depend on trade routes,
3956 * so can't be calculated until all players have been loaded. */
3957 if (game.info.illness_on) {
3958 cities_iterate(pcity) {
3959 pcity->server.illness
3960 = city_illness_calc(pcity, NULL, NULL,
3961 &(pcity->illness_trade), NULL);
3963 }
3964
3965 /* Update all city information. This must come after all cities are
3966 * loaded (in player_load) but before player (dumb) cities are loaded
3967 * in player_load_vision(). */
3968 players_iterate(plr) {
3969 city_list_iterate(plr->cities, pcity) {
3970 city_refresh(pcity);
3971 sanity_check_city(pcity);
3972 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
3975
3976 /* Since the cities must be placed on the map to put them on the
3977 player map we do this afterwards */
3978 players_iterate(pplayer) {
3980 /* Check the success of the function above. */
3981 sg_check_ret();
3983
3984 /* Check shared vision and tiles. */
3985 players_iterate(pplayer) {
3986 BV_CLR_ALL(pplayer->gives_shared_vision);
3987 BV_CLR_ALL(pplayer->gives_shared_tiles);
3988 BV_CLR_ALL(pplayer->server.really_gives_vision);
3990
3991 /* Set up shared vision... */
3992 players_iterate(pplayer) {
3993 int plr1 = player_index(pplayer);
3994
3996 int plr2 = player_index(pplayer2);
3997
3999 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4000 give_shared_vision(pplayer, pplayer2);
4001 }
4003 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4004 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4005 }
4008
4009 /* ...and check it */
4012 /* TODO: Is there a good reason player is not marked as
4013 * giving shared vision to themselves -> really_gives_vision()
4014 * returning FALSE when pplayer1 == pplayer2 */
4015 if (pplayer1 != pplayer2
4018 sg_regr(3000900,
4019 _("%s did not give shared vision to team member %s."),
4022 }
4024 sg_regr(3000900,
4025 _("%s did not give shared vision to team member %s."),
4028 }
4029 }
4032
4035
4036 /* All vision is ready; this calls city_thaw_workers_queue(). */
4038
4039 /* Make sure everything is consistent. */
4040 players_iterate(pplayer) {
4041 unit_list_iterate(pplayer->units, punit) {
4043 struct tile *ptile = unit_tile(punit);
4044
4045 log_sg("%s doing illegal activity in savegame!",
4047 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4051 : "missing",
4052 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4054 }
4057
4058 cities_iterate(pcity) {
4059 city_refresh(pcity);
4060 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4062
4063 /* Player colors are always needed once game has started. Pre-2.4 savegames
4064 * lack them. This cannot be in compatibility conversion layer as we need
4065 * all the player data available to be able to assign best colors. */
4066 if (game_was_started()) {
4068 }
4069}
4070
4071/************************************************************************/
4074static void sg_save_players(struct savedata *saving)
4075{
4076 /* Check status and return if not OK (sg_success FALSE). */
4077 sg_check_ret();
4078
4079 if ((saving->scenario && !saving->save_players)
4080 || !game_was_started()) {
4081 /* Nothing to do for a scenario without saved players or a game in
4082 * INITIAL state. */
4083 return;
4084 }
4085
4086 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4087
4088 /* Save destroyed wonders as bitvector. Note that improvement order
4089 * is saved in 'savefile.improvement.order'. */
4090 {
4091 char destroyed[B_LAST+1];
4092
4093 improvement_iterate(pimprove) {
4094 if (is_great_wonder(pimprove)
4095 && great_wonder_is_destroyed(pimprove)) {
4096 destroyed[improvement_index(pimprove)] = '1';
4097 } else {
4098 destroyed[improvement_index(pimprove)] = '0';
4099 }
4101 destroyed[improvement_count()] = '\0';
4103 "players.destroyed_wonders");
4104 }
4105
4106 secfile_insert_int(saving->file, server.identity_number,
4107 "players.identity_number_used");
4108
4109 /* Save player order. */
4110 {
4111 int i = 0;
4112 shuffled_players_iterate(pplayer) {
4113 secfile_insert_int(saving->file, player_number(pplayer),
4114 "players.shuffled_player_%d", i);
4115 i++;
4117 }
4118
4119 /* Sort units. */
4121
4122 /* Save players. */
4123 players_iterate(pplayer) {
4124 sg_save_player_main(saving, pplayer);
4125 sg_save_player_cities(saving, pplayer);
4126 sg_save_player_units(saving, pplayer);
4128 sg_save_player_vision(saving, pplayer);
4130}
4131
4132/************************************************************************/
4136 struct player *plr)
4137{
4138 const char **slist;
4139 int i, plrno = player_number(plr);
4140 const char *str;
4141 struct government *gov;
4142 const char *level;
4143 const char *barb_str;
4144 size_t nval;
4145 const char *kind;
4146
4147 /* Check status and return if not OK (sg_success FALSE). */
4148 sg_check_ret();
4149
4150 /* Basic player data. */
4151 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4152 sg_failure_ret(str != NULL, "%s", secfile_error());
4154 sz_strlcpy(plr->username,
4156 "player%d.username", plrno));
4158 "player%d.unassigned_user", plrno),
4159 "%s", secfile_error());
4162 "player%d.orig_username", plrno));
4165 "player%d.ranked_username",
4166 plrno));
4168 "player%d.unassigned_ranked", plrno),
4169 "%s", secfile_error());
4171 "player%d.delegation_username",
4172 plrno);
4173 /* Defaults to no delegation. */
4174 if (strlen(str)) {
4176 }
4177
4178 /* Player flags */
4179 BV_CLR_ALL(plr->flags);
4180 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4181 for (i = 0; i < nval; i++) {
4182 const char *sval = slist[i];
4184
4185 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4186
4187 BV_SET(plr->flags, fid);
4188 }
4189 free(slist);
4190
4191 /* Nation */
4192 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4194 if (plr->nation != NULL) {
4195 ai_traits_init(plr);
4196 }
4197
4198 /* Government */
4199 str = secfile_lookup_str(loading->file, "player%d.government_name",
4200 plrno);
4202 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4203 plrno, str);
4204 plr->government = gov;
4205
4206 /* Target government */
4208 "player%d.target_government_name", plrno);
4209 if (str != NULL) {
4211 } else {
4212 plr->target_government = NULL;
4213 }
4216 "player%d.revolution_finishes", plrno);
4217
4218 /* Load diplomatic data (diplstate + embassy + vision).
4219 * Shared vision is loaded in sg_load_players(). */
4221 players_iterate(pplayer) {
4222 char buf[32];
4223 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4224 i = player_index(pplayer);
4225
4226 /* Load diplomatic status */
4227 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4228
4229 ds->type =
4231 diplstate_type, "%s.current", buf);
4232 ds->max_state =
4234 diplstate_type, "%s.closest", buf);
4235
4236 /* FIXME: If either party is barbarian, we cannot enforce below check */
4237#if 0
4238 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4239 sg_regr(3020000,
4240 "Player%d: War with player %d who has never been met. "
4241 "Reverted to No Contact state.", plrno, i);
4242 ds->type = DS_NO_CONTACT;
4243 }
4244#endif
4245
4246 if (valid_dst_closest(ds) != ds->max_state) {
4247 sg_regr(3020000,
4248 "Player%d: closest diplstate to player %d less than current. "
4249 "Updated.", plrno, i);
4250 ds->max_state = ds->type;
4251 }
4252
4253 ds->first_contact_turn =
4255 "%s.first_contact_turn", buf);
4256 ds->turns_left =
4257 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4258 ds->has_reason_to_cancel =
4260 "%s.has_reason_to_cancel", buf);
4261 ds->contact_turns_left =
4263 "%s.contact_turns_left", buf);
4264
4265 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4266 buf)) {
4267 BV_SET(plr->real_embassy, i);
4268 }
4269 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4270 * must be known. */
4272
4273 /* load ai data */
4275 char buf[32];
4276
4277 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4279
4281 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4282 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4284
4286 "player%d.adv.wonder_city",
4287 plrno);
4288
4289 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4290
4291 /* Some sane defaults */
4292 plr->ai_common.fuzzy = 0;
4293 plr->ai_common.expand = 100;
4294 plr->ai_common.science_cost = 100;
4295
4296
4298 "player%d.ai.level", plrno);
4299 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4300 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4302 } else {
4304 }
4305
4307 log_sg("Player%d: Invalid AI level \"%s\". "
4308 "Changed to \"%s\".", plrno, level,
4311 }
4312
4314 "player%d.ai.barb_type", plrno);
4316
4318 log_sg("Player%d: Invalid barbarian type \"%s\". "
4319 "Changed to \"None\".", plrno, barb_str);
4321 }
4322
4323 if (is_barbarian(plr)) {
4324 server.nbarbarians++;
4325 }
4326
4327 if (is_ai(plr)) {
4329 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4330 }
4331
4332 /* Load nation style. */
4333 {
4334 struct nation_style *style;
4335
4336 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4337
4338 sg_failure_ret(str != NULL, "%s", secfile_error());
4339 style = style_by_rule_name(str);
4340 if (style == NULL) {
4341 style = style_by_number(0);
4342 log_sg("Player%d: unsupported city_style_name \"%s\". "
4343 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4344 }
4345 plr->style = style;
4346 }
4347
4349 "player%d.idle_turns", plrno),
4350 "%s", secfile_error());
4351 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4352 if (sex_by_name(kind) == SEX_MALE) {
4353 plr->is_male = TRUE;
4354 } else {
4355 plr->is_male = FALSE;
4356 }
4358 "player%d.is_alive", plrno),
4359 "%s", secfile_error());
4361 "player%d.turns_alive", plrno),
4362 "%s", secfile_error());
4364 "player%d.last_war", plrno),
4365 "%s", secfile_error());
4367 "player%d.phase_done", plrno);
4369 "player%d.gold", plrno),
4370 "%s", secfile_error());
4372 "player%d.rates.tax", plrno),
4373 "%s", secfile_error());
4375 "player%d.rates.science", plrno),
4376 "%s", secfile_error());
4378 "player%d.rates.luxury", plrno),
4379 "%s", secfile_error());
4381 "player%d.infrapts",
4382 plrno);
4383 plr->server.bulbs_last_turn =
4385 "player%d.research.bulbs_last_turn", plrno);
4386
4387 /* Traits */
4388 if (plr->nation) {
4389 for (i = 0; i < loading->trait.size; i++) {
4390 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4391
4392 if (trait_is_valid(tr)) {
4393 int val;
4394
4395 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4396 plrno, i),
4397 "%s", secfile_error());
4398 plr->ai_common.traits[tr].val = val;
4399
4401 "player%d.trait%d.mod", plrno, i),
4402 "%s", secfile_error());
4403 plr->ai_common.traits[tr].mod = val;
4404 }
4405 }
4406 }
4407
4408 /* Achievements */
4409 {
4410 int count;
4411
4412 count = secfile_lookup_int_default(loading->file, -1,
4413 "player%d.achievement_count", plrno);
4414
4415 if (count > 0) {
4416 for (i = 0; i < count; i++) {
4417 const char *name;
4418 struct achievement *pach;
4419 bool first;
4420
4422 "player%d.achievement%d.name", plrno, i);
4424
4426 "Unknown achievement \"%s\".", name);
4427
4429 "player%d.achievement%d.first",
4430 plrno, i),
4431 "achievement error: %s", secfile_error());
4432
4433 sg_failure_ret(pach->first == NULL || !first,
4434 "Multiple players listed as first to get achievement \"%s\".",
4435 name);
4436
4437 BV_SET(pach->achievers, player_index(plr));
4438
4439 if (first) {
4440 pach->first = plr;
4441 }
4442 }
4443 }
4444 }
4445
4446 /* Player score. */
4447 plr->score.happy =
4449 "score%d.happy", plrno);
4450 plr->score.content =
4452 "score%d.content", plrno);
4453 plr->score.unhappy =
4455 "score%d.unhappy", plrno);
4456 plr->score.angry =
4458 "score%d.angry", plrno);
4459
4460 /* Make sure that the score about specialists in current ruleset that
4461 * were not present at saving time are set to zero. */
4463 plr->score.specialists[sp] = 0;
4465
4466 for (i = 0; i < loading->specialist.size; i++) {
4467 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4469 "score%d.specialists%d", plrno, i);
4470 }
4471
4472 plr->score.wonders =
4474 "score%d.wonders", plrno);
4475 plr->score.techs =
4477 "score%d.techs", plrno);
4478 plr->score.techout =
4480 "score%d.techout", plrno);
4481 plr->score.landarea =
4483 "score%d.landarea", plrno);
4484 plr->score.settledarea =
4486 "score%d.settledarea", plrno);
4487 plr->score.population =
4489 "score%d.population", plrno);
4490 plr->score.cities =
4492 "score%d.cities", plrno);
4493 plr->score.units =
4495 "score%d.units", plrno);
4496 plr->score.pollution =
4498 "score%d.pollution", plrno);
4499 plr->score.literacy =
4501 "score%d.literacy", plrno);
4502 plr->score.bnp =
4504 "score%d.bnp", plrno);
4505 plr->score.mfg =
4507 "score%d.mfg", plrno);
4508 plr->score.spaceship =
4510 "score%d.spaceship", plrno);
4511 plr->score.units_built =
4513 "score%d.units_built", plrno);
4514 plr->score.units_killed =
4516 "score%d.units_killed", plrno);
4517 plr->score.units_lost =
4519 "score%d.units_lost", plrno);
4520 plr->score.units_used =
4522 "score%d.units_used", plrno);
4523 plr->score.culture =
4525 "score%d.culture", plrno);
4526 plr->score.game =
4528 "score%d.total", plrno);
4529
4530 /* Load space ship data. */
4531 {
4532 struct player_spaceship *ship = &plr->spaceship;
4533 char prefix[32];
4534 const char *st;
4535 int ei;
4536
4537 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4540 &ei,
4541 "%s.state", prefix),
4542 "%s", secfile_error());
4543 ship->state = ei;
4544
4545 if (ship->state != SSHIP_NONE) {
4546 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4547 "%s.structurals", prefix),
4548 "%s", secfile_error());
4549 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4550 "%s.components", prefix),
4551 "%s", secfile_error());
4553 "%s.modules", prefix),
4554 "%s", secfile_error());
4556 "%s.fuel", prefix),
4557 "%s", secfile_error());
4558 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4559 "%s.propulsion", prefix),
4560 "%s", secfile_error());
4561 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4562 "%s.habitation", prefix),
4563 "%s", secfile_error());
4564 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4565 "%s.life_support", prefix),
4566 "%s", secfile_error());
4567 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4568 "%s.solar_panels", prefix),
4569 "%s", secfile_error());
4570
4571 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4572 sg_failure_ret(st != NULL, "%s", secfile_error())
4573 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4574 sg_failure_ret(st[i] == '1' || st[i] == '0',
4575 "Undefined value '%c' within '%s.structure'.", st[i],
4576 prefix)
4577
4578 if (!(st[i] == '0')) {
4579 BV_SET(ship->structure, i);
4580 }
4581 }
4582 if (ship->state >= SSHIP_LAUNCHED) {
4583 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4584 "%s.launch_year", prefix),
4585 "%s", secfile_error());
4586 }
4588 }
4589 }
4590
4591 /* Load lost wonder data. */
4592 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4593 /* If not present, probably an old savegame; nothing to be done */
4594 if (str != NULL) {
4595 int k;
4596
4597 sg_failure_ret(strlen(str) == loading->improvement.size,
4598 "Invalid length for 'player%d.lost_wonders' ("
4599 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4600 plrno, strlen(str), loading->improvement.size);
4601 for (k = 0; k < loading->improvement.size; k++) {
4602 sg_failure_ret(str[k] == '1' || str[k] == '0',
4603 "Undefined value '%c' within "
4604 "'player%d.lost_wonders'.", plrno, str[k]);
4605
4606 if (str[k] == '1') {
4607 struct impr_type *pimprove =
4608 improvement_by_rule_name(loading->improvement.order[k]);
4609 if (pimprove) {
4610 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4611 }
4612 }
4613 }
4614 }
4615
4616 plr->history =
4617 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4618 plr->server.huts =
4619 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4620}
4621
4622/************************************************************************/
4626 struct player *plr)
4627{
4628 int i, k, plrno = player_number(plr);
4629 struct player_spaceship *ship = &plr->spaceship;
4630 const char *flag_names[PLRF_COUNT];
4631 int set_count;
4632
4633 /* Check status and return if not OK (sg_success FALSE). */
4634 sg_check_ret();
4635
4636 set_count = 0;
4637 for (i = 0; i < PLRF_COUNT; i++) {
4638 if (player_has_flag(plr, i)) {
4640 }
4641 }
4642
4644 "player%d.flags", plrno);
4645
4646 secfile_insert_str(saving->file, ai_name(plr->ai),
4647 "player%d.ai_type", plrno);
4649 "player%d.name", plrno);
4651 "player%d.username", plrno);
4653 "player%d.unassigned_user", plrno);
4654 if (plr->rgb != NULL) {
4655 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4656 } else {
4657 /* Colorless players are ok in pregame */
4658 if (game_was_started()) {
4659 log_sg("Game has started, yet player %d has no color defined.", plrno);
4660 }
4661 }
4663 "player%d.ranked_username", plrno);
4665 "player%d.unassigned_ranked", plrno);
4667 "player%d.orig_username", plrno);
4670 : "",
4671 "player%d.delegation_username", plrno);
4673 "player%d.nation", plrno);
4674 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4675 "player%d.team_no", plrno);
4676
4679 "player%d.government_name", plrno);
4680
4681 if (plr->target_government) {
4684 "player%d.target_government_name", plrno);
4685 }
4686
4688 "player%d.style_by_name", plrno);
4689
4691 "player%d.idle_turns", plrno);
4692 if (plr->is_male) {
4694 "player%d.kind", plrno);
4695 } else {
4697 "player%d.kind", plrno);
4698 }
4700 "player%d.is_alive", plrno);
4702 "player%d.turns_alive", plrno);
4704 "player%d.last_war", plrno);
4706 "player%d.phase_done", plrno);
4707
4708 players_iterate(pplayer) {
4709 char buf[32];
4710 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4711
4712 i = player_index(pplayer);
4713
4714 /* save diplomatic state */
4715 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4716
4717 secfile_insert_enum(saving->file, ds->type,
4718 diplstate_type, "%s.current", buf);
4719 secfile_insert_enum(saving->file, ds->max_state,
4720 diplstate_type, "%s.closest", buf);
4721 secfile_insert_int(saving->file, ds->first_contact_turn,
4722 "%s.first_contact_turn", buf);
4723 secfile_insert_int(saving->file, ds->turns_left,
4724 "%s.turns_left", buf);
4725 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4726 "%s.has_reason_to_cancel", buf);
4727 secfile_insert_int(saving->file, ds->contact_turns_left,
4728 "%s.contact_turns_left", buf);
4730 "%s.embassy", buf);
4731 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4732 "%s.gives_shared_vision", buf);
4733 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4734 "%s.gives_shared_tiles", buf);
4736
4739 /* save ai data */
4741 "player%d.ai%d.love", plrno, i);
4742 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4744
4746 "player%d.adv.wonder_city", plrno);
4747
4748 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4749
4750 /* Multipliers (policies) */
4751 i = multiplier_count();
4752
4753 for (k = 0; k < i; k++) {
4755 "player%d.multiplier%d.val", plrno, k);
4757 "player%d.multiplier%d.target", plrno, k);
4759 "player%d.multiplier%d.changed", plrno, k);
4760 }
4761
4763 "player%d.ai.level", plrno);
4765 "player%d.ai.barb_type", plrno);
4767 "player%d.gold", plrno);
4769 "player%d.rates.tax", plrno);
4771 "player%d.rates.science", plrno);
4773 "player%d.rates.luxury", plrno);
4775 "player%d.infrapts", plrno);
4777 "player%d.research.bulbs_last_turn", plrno);
4778
4779 /* Save traits */
4780 {
4781 enum trait tr;
4782 int j;
4783
4784 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4786 "player%d.trait%d.val", plrno, j);
4788 "player%d.trait%d.mod", plrno, j);
4789 }
4790 }
4791
4792 /* Save achievements */
4793 {
4794 int j = 0;
4795
4797 if (achievement_player_has(pach, plr)) {
4799 "player%d.achievement%d.name", plrno, j);
4800 if (pach->first == plr) {
4802 "player%d.achievement%d.first", plrno, j);
4803 } else {
4805 "player%d.achievement%d.first", plrno, j);
4806 }
4807
4808 j++;
4809 }
4811
4812 secfile_insert_int(saving->file, j,
4813 "player%d.achievement_count", plrno);
4814 }
4815
4817 "player%d.revolution_finishes", plrno);
4818
4819 /* Player score */
4821 "score%d.happy", plrno);
4823 "score%d.content", plrno);
4825 "score%d.unhappy", plrno);
4827 "score%d.angry", plrno);
4830 "score%d.specialists%d", plrno, sp);
4833 "score%d.wonders", plrno);
4835 "score%d.techs", plrno);
4837 "score%d.techout", plrno);
4839 "score%d.landarea", plrno);
4841 "score%d.settledarea", plrno);
4843 "score%d.population", plrno);
4845 "score%d.cities", plrno);
4847 "score%d.units", plrno);
4849 "score%d.pollution", plrno);
4851 "score%d.literacy", plrno);
4852 secfile_insert_int(saving->file, plr->score.bnp,
4853 "score%d.bnp", plrno);
4854 secfile_insert_int(saving->file, plr->score.mfg,
4855 "score%d.mfg", plrno);
4857 "score%d.spaceship", plrno);
4859 "score%d.units_built", plrno);
4861 "score%d.units_killed", plrno);
4863 "score%d.units_lost", plrno);
4865 "score%d.units_used", plrno);
4867 "score%d.culture", plrno);
4868 secfile_insert_int(saving->file, plr->score.game,
4869 "score%d.total", plrno);
4870
4871 /* Save space ship status. */
4872 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4873 plrno);
4874 if (ship->state != SSHIP_NONE) {
4875 char buf[32];
4876 char st[NUM_SS_STRUCTURALS+1];
4877 int ssi;
4878
4879 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4880
4881 secfile_insert_int(saving->file, ship->structurals,
4882 "%s.structurals", buf);
4883 secfile_insert_int(saving->file, ship->components,
4884 "%s.components", buf);
4885 secfile_insert_int(saving->file, ship->modules,
4886 "%s.modules", buf);
4887 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4888 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4889 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4890 secfile_insert_int(saving->file, ship->life_support,
4891 "%s.life_support", buf);
4892 secfile_insert_int(saving->file, ship->solar_panels,
4893 "%s.solar_panels", buf);
4894
4895 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4896 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4897 }
4898 st[ssi] = '\0';
4899 secfile_insert_str(saving->file, st, "%s.structure", buf);
4900 if (ship->state >= SSHIP_LAUNCHED) {
4901 secfile_insert_int(saving->file, ship->launch_year,
4902 "%s.launch_year", buf);
4903 }
4904 }
4905
4906 /* Save lost wonders info. */
4907 {
4908 char lost[B_LAST+1];
4909
4910 improvement_iterate(pimprove) {
4911 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
4912 lost[improvement_index(pimprove)] = '1';
4913 } else {
4914 lost[improvement_index(pimprove)] = '0';
4915 }
4917 lost[improvement_count()] = '\0';
4919 "player%d.lost_wonders", plrno);
4920 }
4921
4922 secfile_insert_int(saving->file, plr->history,
4923 "player%d.history", plrno);
4925 "player%d.hut_count", plrno);
4926
4928 "player%d.border_vision", plrno);
4929
4930 if (saving->scenario) {
4931 if (plr->autoselect_weight < 0) { /* Apply default behavior */
4932 int def = 1; /* We want users to get a player in a scenario */
4933
4935 /* This isn't usable player */
4936 def = 0;
4937 }
4938
4939 secfile_insert_int(saving->file, def,
4940 "player%d.autoselect_weight", plrno);
4941 } else {
4943 "player%d.autoselect_weight", plrno);
4944 }
4945 }
4946}
4947
4948/************************************************************************/
4952 struct player *plr)
4953{
4954 int ncities, i, plrno = player_number(plr);
4955 bool tasks_handled;
4957
4958 /* Check status and return if not OK (sg_success FALSE). */
4959 sg_check_ret();
4960
4962 "player%d.ncities", plrno),
4963 "%s", secfile_error());
4964
4965 if (!plr->is_alive && ncities > 0) {
4966 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
4967 ncities = 0;
4968 }
4969
4971 "player%d.wl_max_length",
4972 plrno);
4974 "player%d.routes_max_length", plrno);
4975
4976 /* Load all cities of the player. */
4977 for (i = 0; i < ncities; i++) {
4978 char buf[32];
4979 struct city *pcity;
4980
4981 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
4982
4983 /* Create a dummy city. */
4984 pcity = create_city_virtual(plr, NULL, buf);
4985 adv_city_alloc(pcity);
4986 if (!sg_load_player_city(loading, plr, pcity, buf,
4988 adv_city_free(pcity);
4989 destroy_city_virtual(pcity);
4990 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
4991 }
4992
4994 idex_register_city(&wld, pcity);
4995
4996 /* Load the information about the nationality of citizens. This is done
4997 * here because the city sanity check called by citizens_update() requires
4998 * that the city is registered. */
5000
5001 /* After everything is loaded, but before vision. */
5002 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
5003
5004 /* adding the city contribution to fog-of-war */
5005 pcity->server.vision = vision_new(plr, city_tile(pcity));
5007 city_refresh_vision(pcity);
5008
5009 city_list_append(plr->cities, pcity);
5010 }
5011
5013 for (i = 0; !tasks_handled; i++) {
5014 int city_id;
5015 struct city *pcity = NULL;
5016
5017 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5018 plrno, i);
5019
5020 if (city_id != -1) {
5021 pcity = player_city_by_number(plr, city_id);
5022 }
5023
5024 if (pcity != NULL) {
5025 const char *str;
5026 int nat_x, nat_y;
5027 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5028
5029 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5030 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5031
5032 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5033
5034 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5036
5038 "Unknown workertask activity %s", str);
5039
5040 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5041
5042 if (strcmp("-", str)) {
5044
5045 sg_failure_ret(ptask->tgt != NULL,
5046 "Unknown workertask target %s", str);
5047 } else {
5048 ptask->tgt = NULL;
5049
5050 if (ptask->act == ACTIVITY_IRRIGATE) {
5052 } else if (ptask->act == ACTIVITY_MINE) {
5053 ptask->act = ACTIVITY_MINE;
5054 }
5055 }
5056
5057 ptask->want = secfile_lookup_int_default(loading->file, 1,
5058 "player%d.task%d.want", plrno, i);
5059
5061 } else {
5063 }
5064 }
5065}
5066
5067/************************************************************************/
5070static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5071 struct city *pcity, const char *citystr,
5073{
5074 struct player *past;
5075 const char *kind, *name, *str;
5076 int id, i, repair, sp_count = 0, workers = 0, value;
5077 int nat_x, nat_y;
5078 citizens size;
5079 const char *stylename;
5080 int partner;
5081 int want;
5082 int tmp_int;
5083 const struct civ_map *nmap = &(wld.map);
5084
5086 FALSE, "%s", secfile_error());
5088 FALSE, "%s", secfile_error());
5089 pcity->tile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5090 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5091 "%s has invalid center tile (%d, %d)",
5092 citystr, nat_x, nat_y);
5094 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5095
5096 /* Instead of dying, use 'citystr' string for damaged name. */
5098 "%s.name", citystr));
5099
5100 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5101 citystr), FALSE, "%s", secfile_error());
5102
5104 "%s.original", citystr);
5105 past = player_by_number(id);
5106 if (NULL != past) {
5107 pcity->original = past;
5108 }
5109
5110 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5111 citystr), FALSE, "%s", secfile_error());
5112 size = (citizens)value; /* set the correct type */
5113 sg_warn_ret_val(value == (int)size, FALSE,
5114 "Invalid city size: %d, set to %d", value, size);
5115 city_size_set(pcity, size);
5116
5117 for (i = 0; i < loading->specialist.size; i++) {
5118 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5119 citystr, i),
5120 FALSE, "%s", secfile_error());
5121 pcity->specialists[specialist_index(loading->specialist.order[i])]
5122 = (citizens)value;
5123 sp_count += value;
5124 }
5125
5126 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5127 for (i = 0; partner != 0; i++) {
5128 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5129 const char *dir;
5130 const char *good_str;
5131
5132 /* Append to routes list immediately, so the pointer can be found for freeing
5133 * even if we abort */
5135
5136 proute->partner = partner;
5137 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5139 "No traderoute direction found for %s", citystr);
5142 "Illegal route direction %s", dir);
5143 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5145 "No good found for %s", citystr);
5147 sg_warn_ret_val(proute->goods != NULL, FALSE,
5148 "Illegal good %s", good_str);
5149
5150 /* Next one */
5152 "%s.traderoute%d", citystr, i + 1);
5153 }
5154
5155 for (; i < routes_max; i++) {
5156 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5157 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5158 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5159 }
5160
5162 "%s.food_stock", citystr),
5163 FALSE, "%s", secfile_error());
5165 "%s.shield_stock", citystr),
5166 FALSE, "%s", secfile_error());
5167 pcity->history =
5168 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5169
5170 pcity->airlift =
5171 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5172 pcity->was_happy =
5173 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5174 citystr);
5175 pcity->had_famine =
5176 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5177 citystr);
5178
5179 pcity->turn_plague =
5180 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5181
5183 "%s.anarchy", citystr),
5184 FALSE, "%s", secfile_error());
5185 pcity->rapture =
5186 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5187 pcity->steal =
5188 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5189
5191 "%s.turn_founded", citystr),
5192 FALSE, "%s", secfile_error());
5194 "%s.acquire_t", citystr),
5195 FALSE, "%s", secfile_error());
5196 pcity->acquire_t = tmp_int;
5197 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5198 citystr), FALSE, "%s", secfile_error());
5199 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5200 citystr), FALSE, "%s", secfile_error());
5201
5203 "%s.turn_last_built", citystr),
5204 FALSE, "%s", secfile_error());
5205
5206 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5207 citystr);
5208 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5209 citystr);
5210 pcity->production = universal_by_rule_name(kind, name);
5212 "%s.currently_building: unknown \"%s\" \"%s\".",
5213 citystr, kind, name);
5214
5215 want = secfile_lookup_int_default(loading->file, 0,
5216 "%s.current_want", citystr);
5217 if (pcity->production.kind == VUT_IMPROVEMENT) {
5218 pcity->server.adv->
5219 building_want[improvement_index(pcity->production.value.building)]
5220 = want;
5221 }
5222
5223 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5224 citystr);
5225 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5226 citystr);
5229 "%s.changed_from: unknown \"%s\" \"%s\".",
5230 citystr, kind, name);
5231
5232 pcity->before_change_shields =
5234 "%s.before_change_shields", citystr);
5235 pcity->caravan_shields =
5237 "%s.caravan_shields", citystr);
5238 pcity->disbanded_shields =
5240 "%s.disbanded_shields", citystr);
5243 "%s.last_turns_shield_surplus",
5244 citystr);
5245
5247 "%s.style", citystr);
5248 if (stylename != NULL) {
5250 } else {
5251 pcity->style = 0;
5252 }
5253 if (pcity->style < 0) {
5254 pcity->style = city_style(pcity);
5255 }
5256
5257 pcity->server.synced = FALSE; /* Must re-sync with clients */
5258
5259 /* Initialise list of city improvements. */
5260 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5261 pcity->built[i].turn = I_NEVER;
5262 }
5263
5264 /* Load city improvements. */
5265 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5267 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5268 "Invalid length of '%s.improvements' ("
5269 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5270 citystr, strlen(str), loading->improvement.size);
5271 for (i = 0; i < loading->improvement.size; i++) {
5272 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5273 "Undefined value '%c' within '%s.improvements'.",
5274 str[i], citystr)
5275
5276 if (str[i] == '1') {
5277 struct impr_type *pimprove
5278 = improvement_by_rule_name(loading->improvement.order[i]);
5279
5280 if (pimprove) {
5281 city_add_improvement(pcity, pimprove);
5282 }
5283 }
5284 }
5285
5286 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5287 "No worked tiles map defined.");
5288
5289 city_freeze_workers(pcity);
5290
5291 /* Load new savegame with variable (squared) city radius and worked
5292 * tiles map */
5293
5294 int radius_sq
5295 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5296 citystr);
5297 city_map_radius_sq_set(pcity, radius_sq);
5298
5300 if (loading->worked_tiles[ptile->index] == pcity->id) {
5301 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5302 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5303 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5304 TILE_XY(pcity->tile), TILE_XY(ptile));
5306 sp_count++;
5307 } else {
5308 tile_set_worked(ptile, pcity);
5309 workers++;
5310 }
5311
5312#ifdef FREECIV_DEBUG
5313 /* Set this tile to unused; a check for not reset tiles is
5314 * included in game_load_internal() */
5315 loading->worked_tiles[ptile->index] = -1;
5316#endif /* FREECIV_DEBUG */
5317 }
5319
5320 if (tile_worked(city_tile(pcity)) != pcity) {
5321 struct city *pwork = tile_worked(city_tile(pcity));
5322
5323 if (NULL != pwork) {
5324 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5325 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5328
5329 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5330 pwork->specialists[DEFAULT_SPECIALIST]++;
5332 } else {
5333 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5334 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5335 city_size_get(pcity));
5336 }
5337
5338 /* Repair pcity */
5339 tile_set_worked(city_tile(pcity), pcity);
5340 city_repair_size(pcity, -1);
5341 }
5342
5343 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5344 if (0 != repair) {
5345 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5346 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5347 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5348 workers, FREE_WORKED_TILES, sp_count);
5349
5350 /* Repair pcity */
5351 city_repair_size(pcity, repair);
5352 }
5353
5354 /* worklist_init() done in create_city_virtual() */
5355 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5356
5357 /* Load city options. */
5358 BV_CLR_ALL(pcity->city_options);
5359 for (i = 0; i < loading->coptions.size; i++) {
5360 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5361 citystr, i)) {
5362 BV_SET(pcity->city_options, loading->coptions.order[i]);
5363 }
5364 }
5366 "%s.wlcb", citystr),
5367 FALSE, "%s", secfile_error());
5368 pcity->wlcb = tmp_int;
5369
5370 /* Load the city rally point. */
5371 {
5372 int len = secfile_lookup_int_default(loading->file, 0,
5373 "%s.rally_point_length", citystr);
5374 int unconverted;
5375
5376 pcity->rally_point.length = len;
5377 if (len > 0) {
5379
5380 pcity->rally_point.orders
5381 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5382 pcity->rally_point.persistent
5384 "%s.rally_point_persistent", citystr);
5385 pcity->rally_point.vigilant
5387 "%s.rally_point_vigilant", citystr);
5388
5391 "%s.rally_point_orders", citystr);
5394 "%s.rally_point_dirs", citystr);
5397 "%s.rally_point_activities", citystr);
5398
5399 for (i = 0; i < len; i++) {
5400 struct unit_order *order = &pcity->rally_point.orders[i];
5401
5402 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5403 || rally_activities[i] == '\0') {
5404 log_sg("Invalid rally point.");
5405 free(pcity->rally_point.orders);
5406 pcity->rally_point.orders = NULL;
5407 pcity->rally_point.length = 0;
5408 break;
5409 }
5410 order->order = char2order(rally_orders[i]);
5411 order->dir = char2dir(rally_dirs[i]);
5412 order->activity = char2activity(rally_activities[i]);
5413
5415 "%s.rally_point_action_vec,%d",
5416 citystr, i);
5417
5418 if (unconverted == -1) {
5419 order->action = ACTION_NONE;
5420 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5421 /* Look up what action id the unconverted number represents. */
5422 order->action = loading->action.order[unconverted];
5423 } else {
5424 if (order->order == ORDER_PERFORM_ACTION) {
5425 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5426 pcity->id);
5427 }
5428
5429 order->action = ACTION_NONE;
5430 }
5431
5432 order->target
5434 "%s.rally_point_tgt_vec,%d",
5435 citystr, i);
5436 order->sub_target
5438 "%s.rally_point_sub_tgt_vec,%d",
5439 citystr, i);
5440 }
5441 } else {
5442 pcity->rally_point.orders = NULL;
5443
5444 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5445 citystr);
5446 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5447 citystr);
5448 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5449 citystr);
5450 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5451 citystr);
5452 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5453 citystr);
5454 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5455 citystr);
5457 "%s.rally_point_tgt_vec", citystr);
5459 "%s.rally_point_sub_tgt_vec", citystr);
5460 }
5461 }
5462
5463 /* Load the city manager parameters. */
5464 {
5465 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5466 "%s.cma_enabled", citystr);
5467 if (enabled) {
5468 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5469
5470 for (i = 0; i < O_LAST; i++) {
5472 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5474 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5475 }
5476
5478 loading->file, FALSE, "%s.max_growth", citystr);
5480 loading->file, FALSE, "%s.require_happy", citystr);
5482 loading->file, FALSE, "%s.allow_disorder", citystr);
5484 loading->file, FALSE, "%s.allow_specialists", citystr);
5486 loading->file, 0, "%s.happy_factor", citystr);
5487 pcity->cm_parameter = param;
5488 } else {
5489 pcity->cm_parameter = NULL;
5490
5491 for (i = 0; i < O_LAST; i++) {
5493 "%s.cma_minimal_surplus,%d", citystr, i);
5495 "%s.cma_factor,%d", citystr, i);
5496 }
5497
5498 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5499 citystr);
5500 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5501 citystr);
5502 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5503 citystr);
5504 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5505 citystr);
5506 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5507 citystr);
5508 }
5509 }
5510
5511 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5512
5513 return TRUE;
5514}
5515
5516/************************************************************************/
5520 struct player *plr,
5521 struct city *pcity,
5522 const char *citystr)
5523{
5525 citizens size;
5526
5527 citizens_init(pcity);
5528 player_slots_iterate(pslot) {
5529 int nationality;
5530
5531 nationality = secfile_lookup_int_default(loading->file, -1,
5532 "%s.citizen%d", citystr,
5533 player_slot_index(pslot));
5534 if (nationality > 0 && !player_slot_is_used(pslot)) {
5535 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5536 city_name_get(pcity), player_slot_index(pslot));
5537 continue;
5538 }
5539
5540 if (nationality != -1 && player_slot_is_used(pslot)) {
5541 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5542 "Invalid value for citizens of player %d in %s: %d.",
5543 player_slot_index(pslot), city_name_get(pcity), nationality);
5544 citizens_nation_set(pcity, pslot, nationality);
5545 }
5547 /* Sanity check. */
5548 size = citizens_count(pcity);
5549 if (size != city_size_get(pcity)) {
5550 if (size != 0) {
5551 /* size == 0 can be result from the fact that ruleset had no
5552 * nationality enabled at saving time, so no citizens at all
5553 * were saved. But something more serious must be going on if
5554 * citizens have been saved partially - if some of them are there. */
5555 log_sg("City size and number of citizens does not match in %s "
5556 "(%d != %d)! Repairing ...", city_name_get(pcity),
5557 city_size_get(pcity), size);
5558 }
5559 citizens_update(pcity, NULL);
5560 }
5561 }
5562}
5563
5564/************************************************************************/
5568 struct player *plr)
5569{
5571 int i = 0;
5572 int plrno = player_number(plr);
5574
5575 /* Check status and return if not OK (sg_success FALSE). */
5576 sg_check_ret();
5577
5579 "player%d.ncities", plrno);
5580
5582 /* Initialise the nation list for the citizens information. */
5583 player_slots_iterate(pslot) {
5586 }
5587
5588 /* First determine length of longest worklist, rally point order, and the
5589 * nationalities we have. */
5590 city_list_iterate(plr->cities, pcity) {
5591 int routes;
5592
5593 /* Check the sanity of the city. */
5594 city_refresh(pcity);
5595 sanity_check_city(pcity);
5596
5597 if (pcity->worklist.length > wlist_max_length) {
5598 wlist_max_length = pcity->worklist.length;
5599 }
5600
5601 if (pcity->rally_point.length > rally_point_max_length) {
5602 rally_point_max_length = pcity->rally_point.length;
5603 }
5604
5605 routes = city_num_trade_routes(pcity);
5606 if (routes > routes_max) {
5607 routes_max = routes;
5608 }
5609
5611 /* Find all nations of the citizens,*/
5612 players_iterate(pplayer) {
5613 if (!nations[player_index(pplayer)]
5614 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5615 nations[player_index(pplayer)] = TRUE;
5616 }
5618 }
5620
5622 "player%d.wl_max_length", plrno);
5624 "player%d.routes_max_length", plrno);
5625
5626 city_list_iterate(plr->cities, pcity) {
5627 struct tile *pcenter = city_tile(pcity);
5628 char impr_buf[B_LAST + 1];
5629 char buf[32];
5630 int j, nat_x, nat_y;
5631
5632 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5633
5634
5636 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5637 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5638
5639 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5640
5641 if (pcity->original != NULL) {
5642 secfile_insert_int(saving->file, player_number(pcity->original),
5643 "%s.original", buf);
5644 } else {
5645 secfile_insert_int(saving->file, -1, "%s.original", buf);
5646 }
5647 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5648
5649 j = 0;
5651 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5652 buf, j++);
5654
5655 j = 0;
5657 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5658 buf, j);
5660 "%s.route_direction%d", buf, j);
5662 "%s.route_good%d", buf, j);
5663 j++;
5665
5666 /* Save dummy values to keep tabular format happy */
5667 for (; j < routes_max; j++) {
5668 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5670 "%s.route_direction%d", buf, j);
5672 "%s.route_good%d", buf, j);
5673 }
5674
5675 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5676 buf);
5677 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5678 buf);
5679 secfile_insert_int(saving->file, pcity->history, "%s.history",
5680 buf);
5681
5682 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5683 buf);
5684 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5685 buf);
5686 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5687 buf);
5688 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5689 buf);
5690
5691 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5692 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5693 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5694 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5695 buf);
5696 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5697 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5698 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5699 secfile_insert_int(saving->file, pcity->turn_last_built,
5700 "%s.turn_last_built", buf);
5701
5702 /* For visual debugging, variable length strings together here */
5703 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5704
5705 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5706 "%s.currently_building_kind", buf);
5707 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5708 "%s.currently_building_name", buf);
5709
5710 if (pcity->production.kind == VUT_IMPROVEMENT) {
5712 pcity->server.adv->
5713 building_want[improvement_index(pcity->production.value.building)],
5714 "%s.current_want", buf);
5715 } else {
5716 secfile_insert_int(saving->file, 0,
5717 "%s.current_want", buf);
5718 }
5719
5720 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5721 "%s.changed_from_kind", buf);
5722 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5723 "%s.changed_from_name", buf);
5724
5725 secfile_insert_int(saving->file, pcity->before_change_shields,
5726 "%s.before_change_shields", buf);
5727 secfile_insert_int(saving->file, pcity->caravan_shields,
5728 "%s.caravan_shields", buf);
5729 secfile_insert_int(saving->file, pcity->disbanded_shields,
5730 "%s.disbanded_shields", buf);
5731 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5732 "%s.last_turns_shield_surplus", buf);
5733
5734 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5735 "%s.style", buf);
5736
5737 /* Save the squared city radius and all tiles within the corresponding
5738 * city map. */
5739 secfile_insert_int(saving->file, pcity->city_radius_sq,
5740 "player%d.c%d.city_radius_sq", plrno, i);
5741 /* The tiles worked by the city are saved using the main map.
5742 * See also sg_save_map_worked(). */
5743
5744 /* Save improvement list as bytevector. Note that improvement order
5745 * is saved in savefile.improvement_order. */
5746 improvement_iterate(pimprove) {
5747 impr_buf[improvement_index(pimprove)]
5748 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5749 : '1';
5751 impr_buf[improvement_count()] = '\0';
5752
5754 "Invalid size of the improvement vector (%s.improvements: "
5755 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5756 strlen(impr_buf), sizeof(impr_buf));
5757 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5758
5759 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5760 buf);
5761
5762 for (j = 0; j < CITYO_LAST; j++) {
5763 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5764 "%s.option%d", buf, j);
5765 }
5766 secfile_insert_int(saving->file, pcity->wlcb,
5767 "%s.wlcb", buf);
5768
5769 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5770
5772 /* Save nationality of the citizens,*/
5773 players_iterate(pplayer) {
5774 if (nations[player_index(pplayer)]) {
5776 citizens_nation_get(pcity, pplayer->slot),
5777 "%s.citizen%d", buf, player_index(pplayer));
5778 }
5780 }
5781
5782 secfile_insert_int(saving->file, pcity->rally_point.length,
5783 "%s.rally_point_length", buf);
5784 if (pcity->rally_point.length) {
5785 int len = pcity->rally_point.length;
5786 char orders[len + 1], dirs[len + 1], activities[len + 1];
5787 int actions[len];
5788 int targets[len];
5789 int sub_targets[len];
5790
5791 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5792 "%s.rally_point_persistent", buf);
5793 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5794 "%s.rally_point_vigilant", buf);
5795
5796 for (j = 0; j < len; j++) {
5797 orders[j] = order2char(pcity->rally_point.orders[j].order);
5798 dirs[j] = '?';
5799 activities[j] = '?';
5800 targets[j] = NO_TARGET;
5801 sub_targets[j] = NO_TARGET;
5802 actions[j] = -1;
5803 switch (pcity->rally_point.orders[j].order) {
5804 case ORDER_MOVE:
5805 case ORDER_ACTION_MOVE:
5806 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5807 break;
5808 case ORDER_ACTIVITY:
5809 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5810 activities[j]
5811 = activity2char(pcity->rally_point.orders[j].activity);
5812 break;
5814 actions[j] = pcity->rally_point.orders[j].action;
5815 targets[j] = pcity->rally_point.orders[j].target;
5816 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5817 break;
5818 case ORDER_FULL_MP:
5819 case ORDER_LAST:
5820 break;
5821 }
5822
5823 if (actions[j] == ACTION_NONE) {
5824 actions[j] = -1;
5825 }
5826 }
5827 orders[len] = dirs[len] = activities[len] = '\0';
5828
5829 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5830 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5831 secfile_insert_str(saving->file, activities,
5832 "%s.rally_point_activities", buf);
5833
5835 "%s.rally_point_action_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++) {
5839 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5840 buf, j);
5841 }
5842
5843 secfile_insert_int_vec(saving->file, targets, len,
5844 "%s.rally_point_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++) {
5849 "%s.rally_point_tgt_vec,%d", buf, j);
5850 }
5851
5852 secfile_insert_int_vec(saving->file, sub_targets, len,
5853 "%s.rally_point_sub_tgt_vec", buf);
5854 /* Fill in dummy values for order targets so the registry will save
5855 * the unit table in a tabular format. */
5856 for (j = len; j < rally_point_max_length; j++) {
5857 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5858 buf, j);
5859 }
5860 } else {
5861 /* Put all the same fields into the savegame - otherwise the
5862 * registry code can't correctly use a tabular format and the
5863 * savegame will be bigger. */
5864 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5865 buf);
5866 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5867 buf);
5868 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5869 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5870 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5871 buf);
5872
5873 /* Fill in dummy values for order targets so the registry will save
5874 * the unit table in a tabular format. */
5875
5876 /* The start of a vector has no number. */
5877 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5878 buf);
5879 for (j = 1; j < rally_point_max_length; j++) {
5880 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5881 buf, j);
5882 }
5883
5884 /* The start of a vector has no number. */
5885 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5886 buf);
5887 for (j = 1; j < rally_point_max_length; j++) {
5889 "%s.rally_point_tgt_vec,%d", buf, j);
5890 }
5891
5892 /* The start of a vector has no number. */
5893 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5894 buf);
5895 for (j = 1; j < rally_point_max_length; j++) {
5896 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5897 buf, j);
5898 }
5899 }
5900
5901 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5902 "%s.cma_enabled", buf);
5903 if (pcity->cm_parameter) {
5905 pcity->cm_parameter->minimal_surplus, O_LAST,
5906 "%s.cma_minimal_surplus", buf);
5908 pcity->cm_parameter->factor, O_LAST,
5909 "%s.cma_factor", buf);
5910 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
5911 "%s.max_growth", buf);
5912 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
5913 "%s.require_happy", buf);
5914 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
5915 "%s.allow_disorder", buf);
5917 pcity->cm_parameter->allow_specialists,
5918 "%s.allow_specialists", buf);
5919 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
5920 "%s.happy_factor", buf);
5921 } else {
5922 int zeros[O_LAST];
5923
5924 memset(zeros, 0, sizeof(zeros));
5926 "%s.cma_minimal_surplus", buf);
5928 "%s.cma_factor", buf);
5929 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
5930 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
5931 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
5932 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
5933 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
5934 }
5935
5936 i++;
5938
5939 i = 0;
5940 city_list_iterate(plr->cities, pcity) {
5941 worker_task_list_iterate(pcity->task_reqs, ptask) {
5942 int nat_x, nat_y;
5943
5945 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
5946 plrno, i);
5947 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
5948 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
5950 "player%d.task%d.activity",
5951 plrno, i);
5952 if (ptask->tgt != NULL) {
5954 "player%d.task%d.target",
5955 plrno, i);
5956 } else {
5957 secfile_insert_str(saving->file, "-",
5958 "player%d.task%d.target",
5959 plrno, i);
5960 }
5961 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
5962
5963 i++;
5966}
5967
5968/************************************************************************/
5972 struct player *plr)
5973{
5974 int nunits, i, plrno = player_number(plr);
5975 size_t orders_max_length;
5976
5977 /* Check status and return if not OK (sg_success FALSE). */
5978 sg_check_ret();
5979
5981 "player%d.nunits", plrno),
5982 "%s", secfile_error());
5983 if (!plr->is_alive && nunits > 0) {
5984 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
5985 nunits = 0; /* Some old savegames may be buggy. */
5986 }
5987
5989 "player%d.orders_max_length",
5990 plrno);
5991
5992 for (i = 0; i < nunits; i++) {
5993 struct unit *punit;
5994 struct city *pcity;
5995 const char *name;
5996 char buf[32];
5997 struct unit_type *type;
5998 struct tile *ptile;
5999
6000 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6001
6002 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6004 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6005
6006 /* Create a dummy unit. */
6007 punit = unit_virtual_create(plr, NULL, type, 0);
6010 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6011 }
6012
6015
6016 if ((pcity = game_city_by_number(punit->homecity))) {
6018 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6019 log_sg("%s: bad home city %d.", buf, punit->homecity);
6021 }
6022
6023 ptile = unit_tile(punit);
6024
6025 /* allocate the unit's contribution to fog of war */
6028 /* NOTE: There used to be some map_set_known calls here. These were
6029 * unneeded since unfogging the tile when the unit sees it will
6030 * automatically reveal that tile. */
6031
6034 }
6035}
6036
6037/************************************************************************/
6041 struct player *plr, struct unit *punit,
6043 const char *unitstr)
6044{
6045 enum unit_activity activity;
6046 int nat_x, nat_y;
6047 struct extra_type *pextra = NULL;
6048 struct tile *ptile;
6049 int extra_id;
6050 int ei;
6051 const char *facing_str;
6052 int natnbr;
6053 int unconverted;
6054 const char *str;
6055
6057 unitstr), FALSE, "%s", secfile_error());
6059 FALSE, "%s", secfile_error());
6061 FALSE, "%s", secfile_error());
6062
6063 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6064 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6065 unitstr, nat_x, nat_y);
6066 unit_tile_set(punit, ptile);
6067
6070 "%s.facing", unitstr);
6071 if (facing_str[0] != 'x') {
6072 /* We don't touch punit->facing if savegame does not contain that
6073 * information. Initial orientation set by unit_virtual_create()
6074 * is as good as any. */
6075 enum direction8 facing = char2dir(facing_str[0]);
6076
6077 if (direction8_is_valid(facing)) {
6078 punit->facing = facing;
6079 } else {
6080 log_error("Illegal unit orientation '%s'", facing_str);
6081 }
6082 }
6083
6084 /* If savegame has unit nationality, it doesn't hurt to
6085 * internally set it even if nationality rules are disabled. */
6087 player_number(plr),
6088 "%s.nationality", unitstr);
6089
6091 if (punit->nationality == NULL) {
6092 punit->nationality = plr;
6093 }
6094
6096 "%s.homecity", unitstr), FALSE,
6097 "%s", secfile_error());
6099 "%s.moves", unitstr), FALSE,
6100 "%s", secfile_error());
6102 "%s.fuel", unitstr), FALSE,
6103 "%s", secfile_error());
6105 "%s.activity", unitstr), FALSE,
6106 "%s", secfile_error());
6107 activity = unit_activity_by_name(loading->activities.order[ei],
6109
6112 "%s.born", unitstr);
6115 "%s.current_form_turn", unitstr);
6116
6118 "%s.activity_tgt", unitstr);
6119
6120 if (extra_id != -2) {
6121 if (extra_id >= 0 && extra_id < loading->extra.size) {
6122 pextra = loading->extra.order[extra_id];
6123 set_unit_activity_targeted(punit, activity, pextra);
6124 } else if (activity == ACTIVITY_IRRIGATE) {
6128 punit);
6129 if (tgt != NULL) {
6131 } else {
6133 }
6134 } else if (activity == ACTIVITY_MINE) {
6136 EC_MINE,
6138 punit);
6139 if (tgt != NULL) {
6141 } else {
6143 }
6144 } else {
6145 set_unit_activity(punit, activity);
6146 }
6147 } else {
6149 } /* activity_tgt == NULL */
6150
6152 "%s.activity_count", unitstr), FALSE,
6153 "%s", secfile_error());
6154
6157 "%s.changed_from", unitstr);
6158
6160 "%s.changed_from_tgt", unitstr), FALSE,
6161 "%s", secfile_error());
6162
6163 if (extra_id >= 0 && extra_id < loading->extra.size) {
6164 punit->changed_from_target = loading->extra.order[extra_id];
6165 } else {
6167 }
6168
6171 "%s.changed_from_count", unitstr);
6172
6173 /* Special case: for a long time, we accidentally incremented
6174 * activity_count while a unit was sentried, so it could increase
6175 * without bound (bug #20641) and be saved in old savefiles.
6176 * We zero it to prevent potential trouble overflowing the range
6177 * in network packets, etc. */
6178 if (activity == ACTIVITY_SENTRY) {
6179 punit->activity_count = 0;
6180 }
6183 }
6184
6185 punit->veteran
6186 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6187 {
6188 /* Protect against change in veteran system in ruleset */
6189 const int levels = utype_veteran_levels(unit_type_get(punit));
6190
6191 if (punit->veteran >= levels) {
6192 fc_assert(levels >= 1);
6193 punit->veteran = levels - 1;
6194 }
6195 }
6198 "%s.done_moving", unitstr);
6201 "%s.battlegroup", unitstr);
6202
6204 "%s.go", unitstr)) {
6205 int gnat_x, gnat_y;
6206
6208 "%s.goto_x", unitstr), FALSE,
6209 "%s", secfile_error());
6211 "%s.goto_y", unitstr), FALSE,
6212 "%s", secfile_error());
6213
6215 } else {
6216 punit->goto_tile = NULL;
6217
6218 /* These variables are not used but needed for saving the unit table.
6219 * Load them to prevent unused variables errors. */
6220 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6221 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6222 }
6223
6224 /* Load AI data of the unit. */
6225 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6226
6229 "%s.server_side_agent",
6230 unitstr);
6231 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6232 /* Look up what server side agent the unconverted number represents. */
6233 punit->ssa_controller = loading->ssa.order[unconverted];
6234 } else {
6235 log_sg("Invalid server side agent %d for unit %d",
6236 unconverted, punit->id);
6237
6239 }
6240
6242 "%s.hp", unitstr), FALSE,
6243 "%s", secfile_error());
6244
6246 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6248 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6249 punit->moved
6250 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6253 "%s.paradropped", unitstr);
6254 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6255 if (str[0] != '\0') {
6257 }
6258
6259 /* The transport status (punit->transported_by) is loaded in
6260 * sg_player_units_transport(). */
6261
6262 /* Initialize upkeep values: these are hopefully initialized
6263 * elsewhere before use (specifically, in city_support(); but
6264 * fixme: check whether always correctly initialized?).
6265 * Below is mainly for units which don't have homecity --
6266 * otherwise these don't get initialized (and AI calculations
6267 * etc may use junk values). */
6271
6273 "%s.action_decision", unitstr),
6274 FALSE, "%s", secfile_error());
6275
6276 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6277 /* Look up what action decision want the unconverted number
6278 * represents. */
6279 punit->action_decision_want = loading->act_dec.order[unconverted];
6280 } else {
6281 log_sg("Invalid action decision want for unit %d", punit->id);
6282
6284 }
6285
6287 /* Load the tile to act against. */
6288 int adwt_x, adwt_y;
6289
6290 if (secfile_lookup_int(loading->file, &adwt_x,
6291 "%s.action_decision_tile_x", unitstr)
6293 "%s.action_decision_tile_y", unitstr)) {
6295 adwt_x, adwt_y);
6296 } else {
6299 log_sg("Bad action_decision_tile for unit %d", punit->id);
6300 }
6301 } else {
6302 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6303 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6305 }
6306
6308
6309 /* Load the unit orders */
6310 {
6311 int len = secfile_lookup_int_default(loading->file, 0,
6312 "%s.orders_length", unitstr);
6313
6314 if (len > 0) {
6315 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6316 int j;
6317
6318 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6322 "%s.orders_index", unitstr);
6325 "%s.orders_repeat", unitstr);
6328 "%s.orders_vigilant", unitstr);
6329
6332 "%s.orders_list", unitstr);
6335 "%s.dir_list", unitstr);
6338 "%s.activity_list", unitstr);
6339
6341
6342 for (j = 0; j < len; j++) {
6343 struct unit_order *order = &punit->orders.list[j];
6345 int order_sub_tgt;
6346
6347 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6348 || act_unitstr[j] == '\0') {
6349 log_sg("Invalid unit orders.");
6351 break;
6352 }
6353 order->order = char2order(orders_unitstr[j]);
6354 order->dir = char2dir(dir_unitstr[j]);
6355 order->activity = char2activity(act_unitstr[j]);
6356
6358 "%s.action_vec,%d",
6359 unitstr, j);
6360
6361 if (unconverted == -1) {
6362 order->action = ACTION_NONE;
6363 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6364 /* Look up what action id the unconverted number represents. */
6365 order->action = loading->action.order[unconverted];
6366 } else {
6367 if (order->order == ORDER_PERFORM_ACTION) {
6368 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6369 }
6370
6371 order->action = ACTION_NONE;
6372 }
6373
6374 if (order->order == ORDER_LAST
6375 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6376 || (order->order == ORDER_ACTION_MOVE
6377 && !direction8_is_valid(order->dir))
6378 || (order->order == ORDER_PERFORM_ACTION
6379 && !action_id_exists(order->action))
6380 || (order->order == ORDER_ACTIVITY
6381 && order->activity == ACTIVITY_LAST)) {
6382 /* An invalid order. Just drop the orders for this unit. */
6384 punit->orders.list = NULL;
6385 punit->orders.length = 0;
6387 punit->goto_tile = NULL;
6388 break;
6389 }
6390
6392 "%s.tgt_vec,%d",
6393 unitstr, j);
6395 "%s.sub_tgt_vec,%d",
6396 unitstr, j);
6397
6398 if (order->order == ORDER_PERFORM_ACTION) {
6399 /* Validate sub target */
6400 switch (action_id_get_sub_target_kind(order->action)) {
6401 case ASTK_BUILDING:
6402 /* Sub target is a building. */
6404 /* Sub target is invalid. */
6405 log_sg("Cannot find building %d for %s to %s",
6408 order->sub_target = B_LAST;
6409 } else {
6410 order->sub_target = order_sub_tgt;
6411 }
6412 break;
6413 case ASTK_TECH:
6414 /* Sub target is a technology. */
6415 if (order_sub_tgt == A_NONE
6417 && order_sub_tgt != A_FUTURE)) {
6418 /* Target tech is invalid. */
6419 log_sg("Cannot find tech %d for %s to steal",
6421 order->sub_target = A_NONE;
6422 } else {
6423 order->sub_target = order_sub_tgt;
6424 }
6425 break;
6426 case ASTK_EXTRA:
6428 /* These take an extra. */
6430 break;
6431 case ASTK_NONE:
6432 /* None of these can take a sub target. */
6434 "Specified sub target for action %d unsupported.",
6435 order->action);
6436 order->sub_target = NO_TARGET;
6437 break;
6438 case ASTK_COUNT:
6440 "Bad action action %d.",
6441 order->action);
6442 order->sub_target = NO_TARGET;
6443 break;
6444 }
6445 }
6446
6447 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6448 enum unit_activity act;
6449
6451 if (order_sub_tgt != EXTRA_NONE) {
6452 log_sg("Cannot find extra %d for %s to build",
6454 }
6455
6456 order->sub_target = EXTRA_NONE;
6457 } else {
6458 order->sub_target = order_sub_tgt;
6459 }
6460
6461 /* An action or an activity may require an extra target. */
6462 if (action_wants_extra) {
6463 act = action_id_get_activity(order->action);
6464 } else {
6465 act = order->activity;
6466 }
6467
6468 if (unit_activity_is_valid(act)
6470 && order->sub_target == EXTRA_NONE) {
6471 /* Missing required action extra target. */
6473 punit->orders.list = NULL;
6474 punit->orders.length = 0;
6476 punit->goto_tile = NULL;
6477 break;
6478 }
6479 } else if (order->order != ORDER_PERFORM_ACTION) {
6480 if (order_sub_tgt != -1) {
6481 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6482 order_sub_tgt, -1, order->order);
6483 }
6484 order->sub_target = NO_TARGET;
6485 }
6486 }
6487
6488 for (; j < orders_max_length; j++) {
6490 "%s.action_vec,%d", unitstr, j);
6492 "%s.tgt_vec,%d", unitstr, j);
6494 "%s.sub_tgt_vec,%d", unitstr, j);
6495 }
6496 } else {
6497 int j;
6498
6500 punit->goto_tile = NULL;
6501 punit->orders.list = NULL;
6502 punit->orders.length = 0;
6503
6504 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6505 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6506 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6507 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6508 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6509 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6510 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6511 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6512 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6513
6514 for (j = 1; j < orders_max_length; j++) {
6516 "%s.action_vec,%d", unitstr, j);
6518 "%s.tgt_vec,%d", unitstr, j);
6520 "%s.sub_tgt_vec,%d", unitstr, j);
6521 }
6522 }
6523 }
6524
6525 return TRUE;
6526}
6527
6528/************************************************************************/
6533 struct player *plr)
6534{
6535 int nunits, i, plrno = player_number(plr);
6536
6537 /* Check status and return if not OK (sg_success FALSE). */
6538 sg_check_ret();
6539
6540 /* Recheck the number of units for the player. This is a copied from
6541 * sg_load_player_units(). */
6543 "player%d.nunits", plrno),
6544 "%s", secfile_error());
6545 if (!plr->is_alive && nunits > 0) {
6546 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6547 nunits = 0; /* Some old savegames may be buggy. */
6548 }
6549
6550 for (i = 0; i < nunits; i++) {
6551 int id_unit, id_trans;
6552 struct unit *punit, *ptrans;
6553
6555 "player%d.u%d.id",
6556 plrno, i);
6558 fc_assert_action(punit != NULL, continue);
6559
6561 "player%d.u%d.transported_by",
6562 plrno, i);
6563 if (id_trans == -1) {
6564 /* Not transported. */
6565 continue;
6566 }
6567
6569 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6570
6571 if (ptrans) {
6572#ifndef FREECIV_NDEBUG
6573 bool load_success =
6574#endif
6576
6577 fc_assert_action(load_success, continue);
6578 }
6579 }
6580}
6581
6582/************************************************************************/
6586 struct player *plr)
6587{
6588 int i = 0;
6589 int longest_order = 0;
6590 int plrno = player_number(plr);
6591
6592 /* Check status and return if not OK (sg_success FALSE). */
6593 sg_check_ret();
6594
6596 "player%d.nunits", plrno);
6597
6598 /* Find the longest unit order so different order length won't break
6599 * storing units in the tabular format. */
6601 if (punit->has_orders) {
6602 if (longest_order < punit->orders.length) {
6604 }
6605 }
6607
6609 "player%d.orders_max_length", plrno);
6610
6612 char buf[32];
6613 char dirbuf[2] = " ";
6614 int nat_x, nat_y;
6615 int last_order, j;
6616
6617 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6618 dirbuf[0] = dir2char(punit->facing);
6619 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6620
6622 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6623 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6624
6625 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6628 "%s.nationality", buf);
6629 }
6630 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6631 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6632 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6634 "%s.type_by_name", buf);
6635
6636 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6638 "%s.activity_count", buf);
6639 if (punit->activity_target == NULL) {
6640 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6641 } else {
6643 "%s.activity_tgt", buf);
6644 }
6645
6647 "%s.changed_from", buf);
6649 "%s.changed_from_count", buf);
6650 if (punit->changed_from_target == NULL) {
6651 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6652 } else {
6654 "%s.changed_from_tgt", buf);
6655 }
6656
6658 "%s.done_moving", buf);
6659 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6660 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6662 "%s.born", buf);
6664 "%s.current_form_turn", buf);
6666 "%s.battlegroup", buf);
6667
6668 if (punit->goto_tile) {
6670 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6671 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6672 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6673 } else {
6674 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6675 /* Set this values to allow saving it as table. */
6676 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6677 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6678 }
6679
6681 "%s.server_side_agent", buf);
6682
6683 /* Save AI data of the unit. */
6684 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6685
6687 "%s.ord_map", buf);
6689 "%s.ord_city", buf);
6690 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6692 "%s.paradropped", buf);
6694 ? unit_transport_get(punit)->id : -1,
6695 "%s.transported_by", buf);
6696 if (punit->carrying != NULL) {
6698 "%s.carrying", buf);
6699 } else {
6700 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6701 }
6702
6704 "%s.action_decision", buf);
6705
6706 /* Stored as tile rather than direction to make sure the target tile is
6707 * sane. */
6712 "%s.action_decision_tile_x", buf);
6714 "%s.action_decision_tile_y", buf);
6715 } else {
6716 /* Dummy values to get tabular format. */
6717 secfile_insert_int(saving->file, -1,
6718 "%s.action_decision_tile_x", buf);
6719 secfile_insert_int(saving->file, -1,
6720 "%s.action_decision_tile_y", buf);
6721 }
6722
6724 "%s.stay", buf);
6725
6726 if (punit->has_orders) {
6727 int len = punit->orders.length;
6728 char orders_buf[len + 1], dir_buf[len + 1];
6729 char act_buf[len + 1];
6730 int action_buf[len];
6731 int tgt_vec[len];
6732 int sub_tgt_vec[len];
6733
6734 last_order = len;
6735
6736 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6738 "%s.orders_index", buf);
6740 "%s.orders_repeat", buf);
6742 "%s.orders_vigilant", buf);
6743
6744 for (j = 0; j < len; j++) {
6746 dir_buf[j] = '?';
6747 act_buf[j] = '?';
6748 tgt_vec[j] = NO_TARGET;
6749 sub_tgt_vec[j] = -1;
6750 action_buf[j] = -1;
6751 switch (punit->orders.list[j].order) {
6752 case ORDER_MOVE:
6753 case ORDER_ACTION_MOVE:
6754 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6755 break;
6756 case ORDER_ACTIVITY:
6759 break;
6762 tgt_vec[j] = punit->orders.list[j].target;
6764 break;
6765 case ORDER_FULL_MP:
6766 case ORDER_LAST:
6767 break;
6768 }
6769
6770 if (action_buf[j] == ACTION_NONE) {
6771 action_buf[j] = -1;
6772 }
6773 }
6774 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6775
6776 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6777 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6778 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6779
6781 "%s.action_vec", buf);
6782 /* Fill in dummy values for order targets so the registry will save
6783 * the unit table in a tabular format. */
6784 for (j = last_order; j < longest_order; j++) {
6785 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6786 }
6787
6789 "%s.tgt_vec", buf);
6790 /* Fill in dummy values for order targets so the registry will save
6791 * the unit table in a tabular format. */
6792 for (j = last_order; j < longest_order; j++) {
6793 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6794 }
6795
6797 "%s.sub_tgt_vec", buf);
6798 /* Fill in dummy values for order targets so the registry will save
6799 * the unit table in a tabular format. */
6800 for (j = last_order; j < longest_order; j++) {
6801 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6802 }
6803 } else {
6804
6805 /* Put all the same fields into the savegame - otherwise the
6806 * registry code can't correctly use a tabular format and the
6807 * savegame will be bigger. */
6808 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6809 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6810 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6811 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6812 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6813 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6814 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6815
6816 /* Fill in dummy values for order targets so the registry will save
6817 * the unit table in a tabular format. */
6818
6819 /* The start of a vector has no number. */
6820 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6821 for (j = 1; j < longest_order; j++) {
6822 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6823 }
6824
6825 /* The start of a vector has no number. */
6826 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6827 for (j = 1; j < longest_order; j++) {
6828 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6829 }
6830
6831 /* The start of a vector has no number. */
6832 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6833 for (j = 1; j < longest_order; j++) {
6834 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6835 }
6836 }
6837
6838 i++;
6840}
6841
6842/************************************************************************/
6846 struct player *plr)
6847{
6848 int plrno = player_number(plr);
6849
6850 /* Check status and return if not OK (sg_success FALSE). */
6851 sg_check_ret();
6852
6853 /* Toss any existing attribute_block (should not exist) */
6854 if (plr->attribute_block.data) {
6856 plr->attribute_block.data = NULL;
6857 }
6858
6859 /* This is a big heap of opaque data for the client, check everything! */
6861 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6862
6863 if (0 > plr->attribute_block.length) {
6864 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6865 plr->attribute_block.length);
6866 plr->attribute_block.length = 0;
6867 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6868 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6870 plr->attribute_block.length = 0;
6871 } else if (0 < plr->attribute_block.length) {
6872 int part_nr, parts;
6873 int quoted_length;
6874 char *quoted;
6875#ifndef FREECIV_NDEBUG
6876 size_t actual_length;
6877#endif
6878
6881 "player%d.attribute_v2_block_length_quoted",
6882 plrno), "%s", secfile_error());
6885 "player%d.attribute_v2_block_parts", plrno),
6886 "%s", secfile_error());
6887
6889 quoted[0] = '\0';
6891 for (part_nr = 0; part_nr < parts; part_nr++) {
6892 const char *current =
6894 "player%d.attribute_v2_block_data.part%d",
6895 plrno, part_nr);
6896 if (!current) {
6897 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6898 break;
6899 }
6900 log_debug("attribute_v2_block_length_quoted=%d"
6901 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
6902 quoted_length, strlen(quoted), strlen(current));
6903 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6904 strcat(quoted, current);
6905 }
6907 "attribute_v2_block_length_quoted=%d"
6908 " actual=" SIZE_T_PRINTF,
6910
6911#ifndef FREECIV_NDEBUG
6913#endif
6915 plr->attribute_block.data,
6916 plr->attribute_block.length);
6918 free(quoted);
6919 }
6920}
6921
6922/************************************************************************/
6926 struct player *plr)
6927{
6928 int plrno = player_number(plr);
6929
6930 /* Check status and return if not OK (sg_success FALSE). */
6931 sg_check_ret();
6932
6933 /* This is a big heap of opaque data from the client. Although the binary
6934 * format is not user editable, keep the lines short enough for debugging,
6935 * and hope that data compression will keep the file a reasonable size.
6936 * Note that the "quoted" format is a multiple of 3.
6937 */
6938#define PART_SIZE (3*256)
6939#define PART_ADJUST (3)
6940 if (plr->attribute_block.data) {
6941 char part[PART_SIZE + PART_ADJUST];
6942 int parts;
6943 int current_part_nr;
6945 plr->attribute_block.length);
6946 char *quoted_at = strchr(quoted, ':');
6947 size_t bytes_left = strlen(quoted);
6948 size_t bytes_at_colon = 1 + (quoted_at - quoted);
6950
6952 "player%d.attribute_v2_block_length", plrno);
6954 "player%d.attribute_v2_block_length_quoted", plrno);
6955
6956 /* Try to wring some compression efficiencies out of the "quoted" format.
6957 * The first line has a variable length decimal, mis-aligning triples.
6958 */
6959 if ((bytes_left - bytes_adjust) > PART_SIZE) {
6960 /* first line can be longer */
6961 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
6962 } else {
6963 parts = 1;
6964 }
6965
6967 "player%d.attribute_v2_block_parts", plrno);
6968
6969 if (parts > 1) {
6971
6972 /* first line can be longer */
6974 part[size_of_current_part] = '\0';
6976 "player%d.attribute_v2_block_data.part%d",
6977 plrno, 0);
6980 current_part_nr = 1;
6981 } else {
6982 quoted_at = quoted;
6983 current_part_nr = 0;
6984 }
6985
6988
6990 part[size_of_current_part] = '\0';
6992 "player%d.attribute_v2_block_data.part%d",
6993 plrno,
6997 }
6998 fc_assert(bytes_left == 0);
6999 free(quoted);
7000 }
7001#undef PART_ADJUST
7002#undef PART_SIZE
7003}
7004
7005/************************************************************************/
7009 struct player *plr)
7010{
7011 int plrno = player_number(plr);
7012 int total_ncities
7014 "player%d.dc_total", plrno);
7015 int i;
7016 bool someone_alive = FALSE;
7017
7018 /* Check status and return if not OK (sg_success FALSE). */
7019 sg_check_ret();
7020
7023 if (pteam_member->is_alive) {
7025 break;
7026 }
7028
7029 if (!someone_alive) {
7030 /* Reveal all for completely dead teams. */
7032 }
7033 }
7034
7035 if (-1 == total_ncities
7036 || !game.info.fogofwar
7038 "game.save_private_map")) {
7039 /* We have:
7040 * - a dead player;
7041 * - fogged cities are not saved for any reason;
7042 * - a savegame with fog of war turned off;
7043 * - or game.save_private_map is not set to FALSE in the scenario /
7044 * savegame. The players private knowledge is set to be what they could
7045 * see without fog of war. */
7046 whole_map_iterate(&(wld.map), ptile) {
7047 if (map_is_known(ptile, plr)) {
7048 struct city *pcity = tile_city(ptile);
7049
7050 update_player_tile_last_seen(plr, ptile);
7051 update_player_tile_knowledge(plr, ptile);
7052
7053 if (NULL != pcity) {
7054 update_dumb_city(plr, pcity);
7055 }
7056 }
7058
7059 /* Nothing more to do; */
7060 return;
7061 }
7062
7063 /* Load player map (terrain). */
7064 LOAD_MAP_CHAR(ch, ptile,
7065 map_get_player_tile(ptile, plr)->terrain
7066 = char2terrain(ch), loading->file,
7067 "player%d.map_t%04d", plrno);
7068
7069 /* Load player map (extras). */
7070 halfbyte_iterate_extras(j, loading->extra.size) {
7071 LOAD_MAP_CHAR(ch, ptile,
7073 ch, loading->extra.order + 4 * j),
7074 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7076
7077 whole_map_iterate(&(wld.map), ptile) {
7078 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7079 bool regr_warn = FALSE;
7080
7082 int pres_id = extra_number(pres);
7083
7084 if (BV_ISSET(plrtile->extras, pres_id)) {
7085 if (plrtile->terrain == NULL) {
7086 if (!regr_warn) {
7087 log_sgfix("FoW tile (%d, %d) has extras, though it's on unknown.",
7088 TILE_XY(ptile));
7089 regr_warn = TRUE;
7090 }
7091 BV_CLR(plrtile->extras, pres_id);
7092 } else {
7093 plrtile->resource = pres;
7094 if (!terrain_has_resource(plrtile->terrain, pres)) {
7095 BV_CLR(plrtile->extras, pres_id);
7096 }
7097 }
7098 }
7101
7103 /* Load player map (border). */
7104 int x, y;
7105
7106 for (y = 0; y < wld.map.ysize; y++) {
7107 const char *buffer
7108 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7109 plrno, y);
7110 const char *buffer2
7111 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7112 plrno, y);
7113 const char *ptr = buffer;
7114 const char *ptr2 = buffer2;
7115
7116 sg_failure_ret(NULL != buffer,
7117 "Savegame corrupt - map line %d not found.", y);
7118 for (x = 0; x < wld.map.xsize; x++) {
7119 char token[TOKEN_SIZE];
7120 char token2[TOKEN_SIZE];
7121 int number;
7122 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7123
7124 scanin(&ptr, ",", token, sizeof(token));
7125 sg_failure_ret('\0' != token[0],
7126 "Savegame corrupt - map size not correct.");
7127 if (strcmp(token, "-") == 0) {
7128 map_get_player_tile(ptile, plr)->owner = NULL;
7129 } else {
7130 sg_failure_ret(str_to_int(token, &number),
7131 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7132 token, x, y);
7133 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7134 }
7135
7136 scanin(&ptr2, ",", token2, sizeof(token2));
7137 sg_failure_ret('\0' != token2[0],
7138 "Savegame corrupt - map size not correct.");
7139 if (strcmp(token2, "-") == 0) {
7140 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7141 } else {
7143 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7144 token, x, y);
7145 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7146 }
7147 }
7148 }
7149 }
7150
7151 /* Load player map (update time). */
7152 for (i = 0; i < 4; i++) {
7153 /* put 4-bit segments of 16-bit "updated" field */
7154 if (i == 0) {
7155 LOAD_MAP_CHAR(ch, ptile,
7156 map_get_player_tile(ptile, plr)->last_updated
7157 = ascii_hex2bin(ch, i),
7158 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7159 } else {
7160 LOAD_MAP_CHAR(ch, ptile,
7161 map_get_player_tile(ptile, plr)->last_updated
7162 |= ascii_hex2bin(ch, i),
7163 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7164 }
7165 }
7166
7167 /* Load player map known cities. */
7168 for (i = 0; i < total_ncities; i++) {
7169 struct vision_site *pdcity;
7170 char buf[32];
7171 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7172
7176 pdcity);
7178 } else {
7179 /* Error loading the data. */
7180 log_sg("Skipping seen city %d for player %d.", i, plrno);
7181 if (pdcity != NULL) {
7183 }
7184 }
7185 }
7186
7187 /* Repair inconsistent player maps. */
7188 whole_map_iterate(&(wld.map), ptile) {
7189 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7190 struct city *pcity = tile_city(ptile);
7191
7192 update_player_tile_knowledge(plr, ptile);
7193 reality_check_city(plr, ptile);
7194
7195 if (NULL != pcity) {
7196 update_dumb_city(plr, pcity);
7197 }
7198 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7199 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7200 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7201
7202 plrtile->owner = tile_owner(ptile);
7203 }
7205}
7206
7207/************************************************************************/
7211 struct player *plr,
7212 struct vision_site *pdcity,
7213 const char *citystr)
7214{
7215 const char *str;
7216 int i, id, size;
7217 citizens city_size;
7218 int nat_x, nat_y;
7219 const char *stylename;
7220 enum capital_type cap;
7221 const char *vname;
7222
7224 citystr),
7225 FALSE, "%s", secfile_error());
7227 citystr),
7228 FALSE, "%s", secfile_error());
7229 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7230 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7231 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7232
7233 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7234 citystr),
7235 FALSE, "%s", secfile_error());
7236 pdcity->owner = player_by_number(id);
7237 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7238 "%s has invalid owner (%d); skipping.", citystr, id);
7239
7241 "%s.id", citystr),
7242 FALSE, "%s", secfile_error());
7244 "%s has invalid id (%d); skipping.", citystr, id);
7245
7247 "%s.size", citystr),
7248 FALSE, "%s", secfile_error());
7249 city_size = (citizens)size; /* set the correct type */
7250 sg_warn_ret_val(size == (int)city_size, FALSE,
7251 "Invalid city size: %d; set to %d.", size, city_size);
7252 vision_site_size_set(pdcity, city_size);
7253
7254 /* Initialise list of improvements */
7255 BV_CLR_ALL(pdcity->improvements);
7256 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7258 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7259 "Invalid length of '%s.improvements' ("
7260 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7261 citystr, strlen(str), loading->improvement.size);
7262 for (i = 0; i < loading->improvement.size; i++) {
7263 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7264 "Undefined value '%c' within '%s.improvements'.",
7265 str[i], citystr)
7266
7267 if (str[i] == '1') {
7268 struct impr_type *pimprove =
7269 improvement_by_rule_name(loading->improvement.order[i]);
7270 if (pimprove) {
7271 BV_SET(pdcity->improvements, improvement_index(pimprove));
7272 }
7273 }
7274 }
7275
7277 "%s.name", citystr);
7278
7279 if (vname != NULL) {
7280 pdcity->name = fc_strdup(vname);
7281 }
7282
7284 "%s.occupied", citystr);
7286 "%s.walls", citystr);
7288 "%s.happy", citystr);
7290 "%s.unhappy", citystr);
7292 "%s.style", citystr);
7293 if (stylename != NULL) {
7295 } else {
7296 pdcity->style = 0;
7297 }
7298 if (pdcity->style < 0) {
7299 pdcity->style = 0;
7300 }
7301
7302 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7303 "%s.city_image", citystr);
7304
7306 "%s.capital", citystr),
7308
7310 pdcity->capital = cap;
7311 } else {
7312 pdcity->capital = CAPITAL_NOT;
7313 }
7314
7315 return TRUE;
7316}
7317
7318/************************************************************************/
7322 struct player *plr)
7323{
7324 int i, plrno = player_number(plr);
7325
7326 /* Check status and return if not OK (sg_success FALSE). */
7327 sg_check_ret();
7328
7330 /* The player can see all, there's no reason to save the private map. */
7331 return;
7332 }
7333
7334 /* Save the map (terrain). */
7335 SAVE_MAP_CHAR(ptile,
7337 saving->file, "player%d.map_t%04d", plrno);
7338
7340 /* Save the map (borders). */
7341 int x, y;
7342
7343 for (y = 0; y < wld.map.ysize; y++) {
7344 char line[wld.map.xsize * TOKEN_SIZE];
7345
7346 line[0] = '\0';
7347 for (x = 0; x < wld.map.xsize; x++) {
7348 char token[TOKEN_SIZE];
7349 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7350 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7351
7352 if (plrtile == NULL || plrtile->owner == NULL) {
7353 strcpy(token, "-");
7354 } else {
7355 fc_snprintf(token, sizeof(token), "%d",
7356 player_number(plrtile->owner));
7357 }
7358 strcat(line, token);
7359 if (x < wld.map.xsize) {
7360 strcat(line, ",");
7361 }
7362 }
7363 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7364 plrno, y);
7365 }
7366
7367 for (y = 0; y < wld.map.ysize; y++) {
7368 char line[wld.map.xsize * TOKEN_SIZE];
7369
7370 line[0] = '\0';
7371 for (x = 0; x < wld.map.xsize; x++) {
7372 char token[TOKEN_SIZE];
7373 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7374 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7375
7376 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7377 strcpy(token, "-");
7378 } else {
7379 fc_snprintf(token, sizeof(token), "%d",
7380 player_number(plrtile->extras_owner));
7381 }
7382 strcat(line, token);
7383 if (x < wld.map.xsize) {
7384 strcat(line, ",");
7385 }
7386 }
7387 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7388 plrno, y);
7389 }
7390 }
7391
7392 /* Save the map (extras). */
7394 int mod[4];
7395 int l;
7396
7397 for (l = 0; l < 4; l++) {
7398 if (4 * j + 1 > game.control.num_extra_types) {
7399 mod[l] = -1;
7400 } else {
7401 mod[l] = 4 * j + l;
7402 }
7403 }
7404
7405 SAVE_MAP_CHAR(ptile,
7407 map_get_player_tile(ptile, plr)->resource,
7408 mod),
7409 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7411
7412 /* Save the map (update time). */
7413 for (i = 0; i < 4; i++) {
7414 /* put 4-bit segments of 16-bit "updated" field */
7415 SAVE_MAP_CHAR(ptile,
7417 map_get_player_tile(ptile, plr)->last_updated, i),
7418 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7419 }
7420
7421 /* Save known cities. */
7422 i = 0;
7423 whole_map_iterate(&(wld.map), ptile) {
7424 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7425 char impr_buf[B_LAST + 1];
7426 char buf[32];
7427
7428 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7429
7430 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7431 int nat_x, nat_y;
7432
7434 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7435 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7436
7437 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7439 "%s.owner", buf);
7440
7442 "%s.size", buf);
7443 secfile_insert_bool(saving->file, pdcity->occupied,
7444 "%s.occupied", buf);
7445 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7446 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7447 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7449 "%s.style", buf);
7450 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7452 "%s.capital", buf);
7453
7454 /* Save improvement list as bitvector. Note that improvement order
7455 * is saved in savefile.improvement.order. */
7456 improvement_iterate(pimprove) {
7457 impr_buf[improvement_index(pimprove)]
7458 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7459 ? '1' : '0';
7461 impr_buf[improvement_count()] = '\0';
7463 "Invalid size of the improvement vector (%s.improvements: "
7464 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7465 buf, strlen(impr_buf), sizeof(impr_buf));
7466 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7467 if (pdcity->name != NULL) {
7468 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7469 }
7470
7471 i++;
7472 }
7474
7475 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7476}
7477
7478/* =======================================================================
7479 * Load / save the researches.
7480 * ======================================================================= */
7481
7482/************************************************************************/
7486{
7487 struct research *presearch;
7488 int count;
7489 int number;
7490 const char *str;
7491 int i, j;
7492 int *vlist_research;
7493
7495 /* Check status and return if not OK (sg_success FALSE). */
7496 sg_check_ret();
7497
7498 /* Initialize all researches. */
7502
7503 /* May be unsaved (e.g. scenario case). */
7504 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7505 for (i = 0; i < count; i++) {
7507 "research.r%d.number", i),
7508 "%s", secfile_error());
7509 presearch = research_by_number(number);
7511 "Invalid research number %d in 'research.r%d.number'",
7512 number, i);
7513
7514 presearch->tech_goal = technology_load(loading->file,
7515 "research.r%d.goal", i);
7517 &presearch->techs_researched,
7518 "research.r%d.techs", i),
7519 "%s", secfile_error());
7521 &presearch->future_tech,
7522 "research.r%d.futuretech", i),
7523 "%s", secfile_error());
7525 &presearch->bulbs_researched,
7526 "research.r%d.bulbs", i),
7527 "%s", secfile_error());
7529 &presearch->bulbs_researching_saved,
7530 "research.r%d.bulbs_before", i),
7531 "%s", secfile_error());
7532 presearch->researching_saved = technology_load(loading->file,
7533 "research.r%d.saved", i);
7534 presearch->researching = technology_load(loading->file,
7535 "research.r%d.now", i);
7537 &presearch->free_bulbs,
7538 "research.r%d.free_bulbs", i),
7539 "%s", secfile_error());
7540
7541 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7542 sg_failure_ret(str != NULL, "%s", secfile_error());
7543 sg_failure_ret(strlen(str) == loading->technology.size,
7544 "Invalid length of 'research.r%d.done' ("
7545 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7546 i, strlen(str), loading->technology.size);
7547 for (j = 0; j < loading->technology.size; j++) {
7548 sg_failure_ret(str[j] == '1' || str[j] == '0',
7549 "Undefined value '%c' within 'research.r%d.done'.",
7550 str[j], i);
7551
7552 if (str[j] == '1') {
7553 struct advance *padvance =
7554 advance_by_rule_name(loading->technology.order[j]);
7555
7556 if (padvance) {
7558 TECH_KNOWN);
7559 }
7560 }
7561 }
7562
7564 size_t count_res;
7565 int tn;
7566
7568 "research.r%d.vbs", i);
7569
7570 for (tn = 0; tn < count_res; tn++) {
7571 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7572
7573 if (padvance != NULL) {
7574 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7575 = vlist_research[tn];
7576 }
7577 }
7578 }
7579 }
7580
7581 /* In case of tech_leakage, we can update research only after all the
7582 * researches have been loaded */
7586}
7587
7588/************************************************************************/
7592{
7593 char invs[A_LAST];
7594 int i = 0;
7595 int *vlist_research;
7596
7598 /* Check status and return if not OK (sg_success FALSE). */
7599 sg_check_ret();
7600
7601 if (saving->save_players) {
7604 "research.r%d.number", i);
7605 technology_save(saving->file, "research.r%d.goal",
7606 i, presearch->tech_goal);
7607 secfile_insert_int(saving->file, presearch->techs_researched,
7608 "research.r%d.techs", i);
7609 secfile_insert_int(saving->file, presearch->future_tech,
7610 "research.r%d.futuretech", i);
7611 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7612 "research.r%d.bulbs_before", i);
7616 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7620 "research.r%d.vbs", i);
7621 if (vlist_research) {
7623 }
7624 }
7625 technology_save(saving->file, "research.r%d.saved",
7626 i, presearch->researching_saved);
7627 secfile_insert_int(saving->file, presearch->bulbs_researched,
7628 "research.r%d.bulbs", i);
7629 technology_save(saving->file, "research.r%d.now",
7630 i, presearch->researching);
7631 secfile_insert_int(saving->file, presearch->free_bulbs,
7632 "research.r%d.free_bulbs", i);
7633 /* Save technology lists as bytevector. Note that technology order is
7634 * saved in savefile.technology.order */
7635 advance_index_iterate(A_NONE, tech_id) {
7636 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7638 == TECH_KNOWN ? '1' : '0');
7641 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7642 i++;
7644 secfile_insert_int(saving->file, i, "research.count");
7645 }
7646}
7647
7648/* =======================================================================
7649 * Load / save the event cache. Should be the last thing to do.
7650 * ======================================================================= */
7651
7652/************************************************************************/
7656{
7657 /* Check status and return if not OK (sg_success FALSE). */
7658 sg_check_ret();
7659
7660 event_cache_load(loading->file, "event_cache");
7661}
7662
7663/************************************************************************/
7667{
7668 /* Check status and return if not OK (sg_success FALSE). */
7669 sg_check_ret();
7670
7671 if (saving->scenario) {
7672 /* Do _not_ save events in a scenario. */
7673 return;
7674 }
7675
7676 event_cache_save(saving->file, "event_cache");
7677}
7678
7679/* =======================================================================
7680 * Load / save the open treaties
7681 * ======================================================================= */
7682
7683/************************************************************************/
7687{
7688 int tidx;
7689 const char *plr0;
7690
7691 /* Check status and return if not OK (sg_success FALSE). */
7692 sg_check_ret();
7693
7694 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7695 "treaty%d.plr0", tidx)) != NULL ;
7696 tidx++) {
7697 const char *plr1;
7698 const char *ct;
7699 int cidx;
7700 struct player *p0, *p1;
7701
7702 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7703
7704 p0 = player_by_name(plr0);
7705 p1 = player_by_name(plr1);
7706
7707 if (p0 == NULL || p1 == NULL) {
7708 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7709 } else {
7710 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7711
7714
7715 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7716 "treaty%d.clause%d.type",
7717 tidx, cidx)) != NULL ;
7718 cidx++ ) {
7720 const char *plrx;
7721
7722 if (!clause_type_is_valid(type)) {
7723 log_error("Invalid clause type \"%s\"", ct);
7724 } else {
7725 struct player *pgiver = NULL;
7726
7727 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7728 tidx, cidx);
7729
7730 if (!fc_strcasecmp(plrx, plr0)) {
7731 pgiver = p0;
7732 } else if (!fc_strcasecmp(plrx, plr1)) {
7733 pgiver = p1;
7734 } else {
7735 log_error("Clause giver %s is not participant of the treaty"
7736 "between %s and %s", plrx, plr0, plr1);
7737 }
7738
7739 if (pgiver != NULL) {
7740 int value;
7741
7742 value = secfile_lookup_int_default(loading->file, 0,
7743 "treaty%d.clause%d.value",
7744 tidx, cidx);
7745
7746 add_clause(ptreaty, pgiver, type, value, NULL);
7747 }
7748 }
7749 }
7750
7751 /* These must be after clauses have been added so that acceptance
7752 * does not get cleared by what seems like changes to the treaty. */
7754 "treaty%d.accept0", tidx);
7756 "treaty%d.accept1", tidx);
7757 }
7758 }
7759}
7760
7761typedef struct {
7762 int tidx;
7765
7766/************************************************************************/
7769static void treaty_save(struct Treaty *ptr, void *data_in)
7770{
7771 char tpath[512];
7772 int cidx = 0;
7774
7775 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7776
7777 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7778 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7779 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7780 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7781
7783 char cpath[512];
7784
7785 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7786
7787 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7788 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7789 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7791}
7792
7793/************************************************************************/
7797{
7798 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7799
7801}
7802
7803/* =======================================================================
7804 * Load / save the history report
7805 * ======================================================================= */
7806
7807/************************************************************************/
7811{
7813 int turn;
7814
7815 /* Check status and return if not OK (sg_success FALSE). */
7816 sg_check_ret();
7817
7818 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7819
7820 if (turn != -2) {
7821 hist->turn = turn;
7822 }
7823
7824 if (turn + 1 >= game.info.turn) {
7825 const char *str;
7826
7827 str = secfile_lookup_str(loading->file, "history.title");
7828 sg_failure_ret(str != NULL, "%s", secfile_error());
7829 sz_strlcpy(hist->title, str);
7830 str = secfile_lookup_str(loading->file, "history.body");
7831 sg_failure_ret(str != NULL, "%s", secfile_error());
7832 sz_strlcpy(hist->body, str);
7833 }
7834}
7835
7836/************************************************************************/
7839static void sg_save_history(struct savedata *saving)
7840{
7842
7843 secfile_insert_int(saving->file, hist->turn, "history.turn");
7844
7845 if (hist->turn + 1 >= game.info.turn) {
7846 secfile_insert_str(saving->file, hist->title, "history.title");
7847 secfile_insert_str(saving->file, hist->body, "history.body");
7848 }
7849}
7850
7851/* =======================================================================
7852 * Load / save the mapimg definitions.
7853 * ======================================================================= */
7854
7855/************************************************************************/
7858static void sg_load_mapimg(struct loaddata *loading)
7859{
7860 int mapdef_count, i;
7861
7862 /* Check status and return if not OK (sg_success FALSE). */
7863 sg_check_ret();
7864
7865 /* Clear all defined map images. */
7866 while (mapimg_count() > 0) {
7867 mapimg_delete(0);
7868 }
7869
7871 "mapimg.count");
7872 log_verbose("Saved map image definitions: %d.", mapdef_count);
7873
7874 if (0 >= mapdef_count) {
7875 return;
7876 }
7877
7878 for (i = 0; i < mapdef_count; i++) {
7879 const char *p;
7880
7881 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7882 if (NULL == p) {
7883 log_verbose("[Mapimg %4d] Missing definition.", i);
7884 continue;
7885 }
7886
7887 if (!mapimg_define(p, FALSE)) {
7888 log_error("Invalid map image definition %4d: %s.", i, p);
7889 }
7890
7891 log_verbose("Mapimg %4d loaded.", i);
7892 }
7893}
7894
7895/************************************************************************/
7898static void sg_save_mapimg(struct savedata *saving)
7899{
7900 /* Check status and return if not OK (sg_success FALSE). */
7901 sg_check_ret();
7902
7903 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7904 if (mapimg_count() > 0) {
7905 int i;
7906
7907 for (i = 0; i < mapimg_count(); i++) {
7908 char buf[MAX_LEN_MAPDEF];
7909
7910 mapimg_id2str(i, buf, sizeof(buf));
7911 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7912 }
7913 }
7914}
7915
7916/* =======================================================================
7917 * Sanity checks for loading / saving a game.
7918 * ======================================================================= */
7919
7920/************************************************************************/
7924{
7925 int players;
7926
7927 /* Check status and return if not OK (sg_success FALSE). */
7928 sg_check_ret();
7929
7930 if (game.info.is_new_game) {
7931 /* Nothing to do for new games (or not started scenarios). */
7932 return;
7933 }
7934
7935 /* Old savegames may have maxplayers lower than current player count,
7936 * fix. */
7937 players = normal_player_count();
7938 if (game.server.max_players < players) {
7939 log_verbose("Max players lower than current players, fixing");
7940 game.server.max_players = players;
7941 }
7942
7943 /* Fix ferrying sanity */
7944 players_iterate(pplayer) {
7945 unit_list_iterate_safe(pplayer->units, punit) {
7948 log_sg("Removing %s unferried %s in %s at (%d, %d)",
7954 }
7957
7958 /* Fix stacking issues. We don't rely on the savegame preserving
7959 * alliance invariants (old savegames often did not) so if there are any
7960 * unallied units on the same tile we just bounce them. */
7961 players_iterate(pplayer) {
7963 resolve_unit_stacks(pplayer, aplayer, TRUE);
7966
7967 /* Recalculate the potential buildings for each city. Has caused some
7968 * problems with game random state.
7969 * This also changes the game state if you save the game directly after
7970 * loading it and compare the results. */
7971 players_iterate(pplayer) {
7972 /* Building advisor needs data phase open in order to work */
7973 adv_data_phase_init(pplayer, FALSE);
7974 building_advisor(pplayer);
7975 /* Close data phase again so it can be opened again when game starts. */
7976 adv_data_phase_done(pplayer);
7978
7979 /* Prevent a buggy or intentionally crafted save game from crashing
7980 * Freeciv. See hrm Bug #887748 */
7981 players_iterate(pplayer) {
7982 city_list_iterate(pplayer->cities, pcity) {
7983 worker_task_list_iterate(pcity->task_reqs, ptask) {
7984 if (!worker_task_is_sane(ptask)) {
7985 log_error("[city id: %d] Bad worker task %d.",
7986 pcity->id, ptask->act);
7987 worker_task_list_remove(pcity->task_reqs, ptask);
7988 free(ptask);
7989 ptask = NULL;
7990 }
7994
7995 /* Check worked tiles map */
7996#ifdef FREECIV_DEBUG
7997 if (loading->worked_tiles != NULL) {
7998 /* check the entire map for unused worked tiles */
7999 whole_map_iterate(&(wld.map), ptile) {
8000 if (loading->worked_tiles[ptile->index] != -1) {
8001 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8002 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8003 }
8005 }
8006#endif /* FREECIV_DEBUG */
8007
8008 /* Check researching technologies and goals. */
8010 int techs;
8011
8012 if (presearch->researching != A_UNSET
8013 && !is_future_tech(presearch->researching)
8014 && (valid_advance_by_number(presearch->researching) == NULL
8016 != TECH_PREREQS_KNOWN))) {
8017 log_sg(_("%s had invalid researching technology."),
8019 presearch->researching = A_UNSET;
8020 }
8021 if (presearch->tech_goal != A_UNSET
8022 && !is_future_tech(presearch->tech_goal)
8023 && (valid_advance_by_number(presearch->tech_goal) == NULL
8026 == TECH_KNOWN))) {
8027 log_sg(_("%s had invalid technology goal."),
8029 presearch->tech_goal = A_UNSET;
8030 }
8031
8033
8034 if (presearch->techs_researched != techs) {
8035 sg_regr(3000300,
8036 _("%s had finished researches count wrong."),
8038 presearch->techs_researched = techs;
8039 }
8041
8042 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8043 players_iterate(pplayer) {
8044 int unique_count[U_LAST];
8045
8046 memset(unique_count, 0, sizeof(unique_count));
8047
8048 unit_list_iterate(pplayer->units, punit) {
8051
8054 log_sg(_("%s has multiple units of type %s though it should be possible "
8055 "to have only one."),
8057 }
8060
8061 players_iterate(pplayer) {
8062 unit_list_iterate_safe(pplayer->units, punit) {
8063 if (punit->has_orders
8065 punit->orders.list)) {
8066 log_sg("Invalid unit orders for unit %d.", punit->id);
8068 }
8071
8072 /* Check max rates (rules may have changed since saving) */
8073 players_iterate(pplayer) {
8076
8077 if (0 == strlen(server.game_identifier)
8078 || !is_base64url(server.game_identifier)) {
8079 /* This uses fc_rand(), so random state has to be initialized before. */
8080 randomize_base64url_string(server.game_identifier,
8081 sizeof(server.game_identifier));
8082 }
8083
8084 /* Restore game random state, just in case various initialization code
8085 * inexplicably altered the previously existing state. */
8086 if (!game.info.is_new_game) {
8087 fc_rand_set_state(loading->rstate);
8088 }
8089
8090 /* At the end do the default sanity checks. */
8091 sanity_check();
8092}
8093
8094/************************************************************************/
8098{
8099 /* Check status and return if not OK (sg_success FALSE). */
8100 sg_check_ret();
8101}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
static struct action * actions[MAX_NUM_ACTIONS]
Definition actions.c:97
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2011
struct action * action_by_rule_name(const char *name)
Definition actions.c:1840
const char * action_id_rule_name(action_id act_id)
Definition actions.c:2000
bool action_id_exists(const action_id act_id)
Definition actions.c:1829
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:656
#define NUM_ACTIONS
Definition actions.h:315
#define action_id_get_activity(act_id)
Definition actions.h:701
#define ACTION_NONE
Definition actions.h:311
void building_advisor(struct player *pplayer)
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:263
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:565
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
int ai_type_get_count(void)
Definition ai.c:327
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define ai_type_iterate_end
Definition ai.h:372
#define ai_type_iterate(NAME_ai)
Definition ai.h:365
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:179
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool has_capabilities(const char *us, const char *them)
Definition capability.c:86
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
void citizens_init(struct city *pcity)
Definition citizens.c:32
void citizens_update(struct city *pcity, struct player *plr)
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:148
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c:1145
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
const char * city_style_rule_name(const int style)
Definition city.c:1765
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3430
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2870
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1180
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3357
void destroy_city_virtual(struct city *pcity)
Definition city.c:3516
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:517
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define cities_iterate(pcity)
Definition city.h:512
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:86
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define output_type_iterate(output)
Definition city.h:845
#define FREE_WORKED_TILES
Definition city.h:882
#define MAX_CITY_SIZE
Definition city.h:106
#define city_list_iterate_end
Definition city.h:510
#define I_NEVER
Definition city.h:247
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
#define output_type_iterate_end
Definition city.h:851
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2769
bool send_city_suppression(bool now)
Definition citytools.c:2166
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:137
void city_thaw_workers(struct city *pcity)
Definition citytools.c:147
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2840
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3442
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:367
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:852
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
char * techs
Definition comments.c:31
char * incite_cost
Definition comments.c:75
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
int counter_index(const struct counter *pcount)
Definition counters.c:174
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
int counters_get_city_counters_count(void)
Definition counters.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:111
struct Treaty * ptreaty
Definition diplodlg_g.h:28
void init_treaty(struct Treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:380
bool add_clause(struct Treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaty_add(struct Treaty *ptreaty)
Definition diptreaty.c:361
#define clause_list_iterate_end
Definition diptreaty.h:70
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:68
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1114
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h:354
int Tech_type_id
Definition fc_types.h:377
unsigned char citizens
Definition fc_types.h:388
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:126
#define MAX_LEN_NAME
Definition fc_types.h:66
@ O_LAST
Definition fc_types.h:101
int Multiplier_type_id
Definition fc_types.h:386
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
void initialize_globals(void)
Definition game.c:683
struct city * game_city_by_number(int id)
Definition game.c:107
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:598
#define GAME_DEFAULT_SCORETURN
Definition game.h:582
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:597
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:600
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:599
#define GAME_DEFAULT_RULESETDIR
Definition game.h:676
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:602
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:617
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c:501
void adv_city_alloc(struct city *pcity)
Definition infracache.c:488
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_fatal(message,...)
Definition log.h:100
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1660
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:641
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:1866
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1676
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1696
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1765
void map_init_topology(struct civ_map *nmap)
Definition map.c:303
void main_map_allocate(void)
Definition map.c:519
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
int map_startpos_count(void)
Definition map.c:1853
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:443
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1753
bool map_is_empty(void)
Definition map.c:149
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1643
#define map_startpos_iterate(NAME_psp)
Definition map.h:130
#define MAP_INDEX_SIZE
Definition map.h:137
#define map_startpos_iterate_end
Definition map.h:133
#define whole_map_iterate(_map, _tile)
Definition map.h:545
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:157
#define whole_map_iterate_end
Definition map.h:554
map_generator
Definition map_types.h:46
@ MAPGEN_SCENARIO
Definition map_types.h:47
void assign_continent_numbers(void)
void player_map_init(struct player *pplayer)
Definition maphand.c:1221
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1467
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2207
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:894
bool send_tile_suppression(bool now)
Definition maphand.c:475
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:345
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1196
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1398
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1367
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2220
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1178
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1159
void map_calculate_borders(void)
Definition maphand.c:2373
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1632
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1382
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1311
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1204
int mapimg_count(void)
Definition mapimg.c:573
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
void set_meta_patches_string(const char *string)
Definition meta.c:172
char * meta_addr_port(void)
Definition meta.c:203
const char * default_meta_patches_string(void)
Definition meta.c:83
const char * get_meta_patches_string(void)
Definition meta.c:107
#define DEFAULT_META_SERVER_ADDR
Definition meta.h:21
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:351
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
static struct nation_type * nations
Definition nation.c:46
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nation_hash_iterate_end
Definition nation.h:95
#define NO_NATION_SELECTED
Definition nation.h:30
void event_cache_load(struct section_file *file, const char *section)
Definition notify.c:783
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:903
int parts
Definition packhand.c:132
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
int player_count(void)
Definition player.c:817
int player_slot_count(void)
Definition player.c:418
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:463
int player_number(const struct player *pplayer)
Definition player.c:837
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:159
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_max_used_number(void)
Definition player.c:476
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
struct player * player_by_name(const char *name)
Definition player.c:881
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:240
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
int player_index(const struct player *pplayer)
Definition player.c:829
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:861
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1493
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1485
#define players_iterate_end
Definition player.h:537
dipl_reason
Definition player.h:190
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:192
#define players_iterate(_pplayer)
Definition player.h:532
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:221
#define player_list_iterate(playerlist, pplayer)
Definition player.h:555
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define player_slots_iterate(_pslot)
Definition player.h:523
#define is_ai(plr)
Definition player.h:230
#define player_list_iterate_end
Definition player.h:557
#define players_iterate_alive_end
Definition player.h:547
#define player_slots_iterate_end
Definition player.h:527
#define players_iterate_alive(_pplayer)
Definition player.h:542
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2268
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1894
int normal_player_count(void)
Definition plrhand.c:3205
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2057
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:2453
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2403
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3251
void shuffle_players(void)
Definition plrhand.c:2378
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1943
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1619
void assign_player_colors(void)
Definition plrhand.c:1734
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3238
void fit_nationset_to_players(void)
Definition plrhand.c:2659
#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_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
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:9362
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:205
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:215
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:138
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:227
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:183
#define sg_check_ret(...)
Definition savecompat.h:150
#define sg_warn(condition, message,...)
Definition savecompat.h:160
#define hex_chars
Definition savecompat.h:205
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
#define sg_regr(fixversion, message,...)
Definition savecompat.h:193
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:146
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:171
#define log_sgfix
Definition savecompat.h:148
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:7839
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:2749
static void unit_ordering_apply(void)
Definition savegame3.c:1077
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3619
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:3499
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3169
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:2808
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:3001
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3460
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4074
#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:5567
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5519
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4951
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2901
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:6040
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:1333
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:2658
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5971
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1248
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2429
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3114
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7485
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3416
#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:2038
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2388
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1772
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6532
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7810
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7796
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3290
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7591
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:2467
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2493
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2085
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:4135
static char order2char(enum unit_orders order)
Definition savegame3.c:735
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7686
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2581
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:6585
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2238
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:1260
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7321
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:5070
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1225
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8097
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7858
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6845
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:6925
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2061
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2861
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7008
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2941
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:7898
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:7210
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2696
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3027
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:621
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3879
#define PART_ADJUST
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1296
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7666
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:2969
static void treaty_save(struct Treaty *ptr, void *data_in)
Definition savegame3.c:7769
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:7923
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7655
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:2258
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4625
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2478
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2674
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3556
void script_server_state_save(struct section_file *file)
void script_server_state_load(struct section_file *file)
void settings_game_load(struct section_file *file, const char *section)
Definition settings.c:4946
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4858
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
sex_t sex_by_name(const char *name)
Definition sex.c:27
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1101
bool str_to_int(const char *str, int *pint)
Definition shared.c:517
const struct strvec * get_scenario_dirs(void)
Definition shared.c:978
bool is_base64url(const char *s)
Definition shared.c:318
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1922
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:339
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX_LEN_PATH
Definition shared.h:32
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
@ SSHIP_LAUNCHED
Definition spaceship.h:85
@ SSHIP_NONE
Definition spaceship.h:84
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
void server_game_init(bool keep_ruleset_value)
Definition srv_main.c:3464
const char * aifill(int amount)
Definition srv_main.c:2466
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:2271
enum server_states server_state(void)
Definition srv_main.c:333
void server_game_free(void)
Definition srv_main.c:3488
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * plr0
Definition diptreaty.h:79
bool accept0
Definition diptreaty.h:80
bool accept1
Definition diptreaty.h:80
struct clause_list * clauses
Definition diptreaty.h:81
struct player * plr1
Definition diptreaty.h:79
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
int turn
Definition city.h:246
Definition city.h:320
struct worker_task_list * task_reqs
Definition city.h:412
int turn_last_built
Definition city.h:387
enum city_wl_cancel_behavior wlcb
Definition city.h:404
int food_stock
Definition city.h:367
struct built_status built[B_LAST]
Definition city.h:394
struct player * original
Definition city.h:324
int history
Definition city.h:410
int * counter_values
Definition city.h:408
bool did_sell
Definition city.h:380
int id
Definition city.h:326
int last_turns_shield_surplus
Definition city.h:392
int disbanded_shields
Definition city.h:391
int turn_plague
Definition city.h:374
bv_city_options city_options
Definition city.h:403
bool was_happy
Definition city.h:381
enum city_acquire_type acquire_t
Definition city.h:329
int turn_founded
Definition city.h:386
int airlift
Definition city.h:378
int caravan_shields
Definition city.h:390
bool did_buy
Definition city.h:379
struct trade_route_list * routes
Definition city.h:344
int anarchy
Definition city.h:384
struct worklist worklist
Definition city.h:401
struct universal production
Definition city.h:396
struct unit_order * orders
Definition city.h:422
struct city::@16 rally_point
struct adv_city * adv
Definition city.h:452
bool vigilant
Definition city.h:421
int steal
Definition city.h:414
int before_change_shields
Definition city.h:389
int style
Definition city.h:327
bool had_famine
Definition city.h:382
size_t length
Definition city.h:417
bool synced
Definition city.h:448
citizens specialists[SP_MAX]
Definition city.h:336
struct tile * tile
Definition city.h:322
int shield_stock
Definition city.h:368
struct vision * vision
Definition city.h:455
struct city::@17::@19 server
struct cm_parameter * cm_parameter
Definition city.h:425
struct universal changed_from
Definition city.h:399
struct unit_list * units_supported
Definition city.h:406
bool persistent
Definition city.h:419
int rapture
Definition city.h:385
bool multiresearch
Definition game.h:167
bool last_updated_year
Definition game.h:240
float turn_change_time
Definition game.h:222
bool vision_reveal_tiles
Definition game.h:204
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:265
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:238
struct civ_game::@31::@35::@37 save_options
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:211
char rulesetdir[MAX_LEN_NAME]
Definition game.h:242
int additional_phase_seconds
Definition game.h:216
struct section_file * luadata
Definition game.h:250
int scoreturn
Definition game.h:229
randseed seed
Definition game.h:231
int dbid
Definition game.h:251
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:207
struct timer * phase_timer
Definition game.h:215
unsigned revealmap
Definition game.h:181
char orig_game_version[MAX_LEN_NAME]
Definition game.h:225
bool save_known
Definition game.h:262
bool foggedborders
Definition game.h:151
struct civ_game::@31::@35 server
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:209
int timeoutinc
Definition game.h:208
int phase_mode_stored
Definition game.h:220
int max_players
Definition game.h:160
bool save_starts
Definition game.h:264
int timeoutintinc
Definition game.h:210
int xsize
Definition map_types.h:78
randseed seed
Definition map_types.h:92
int ysize
Definition map_types.h:78
bool have_resources
Definition map_types.h:108
struct civ_map::@42::@44 server
bool have_huts
Definition map_types.h:107
enum map_generator generator
Definition map_types.h:98
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
int changed_to_times
Definition government.h:64
struct section_file * file
Definition savecompat.h:48
int great_wonder_owners[B_LAST]
bool global_advances[A_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char version[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char datafile[MAX_LEN_NAME]
char authors[MAX_LEN_PACKET/3]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:114
struct ai_trait * traits
Definition player.h:124
enum barbarian_type barbarian_type
Definition player.h:120
int science_cost
Definition player.h:117
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:122
int expand
Definition player.h:116
int fuzzy
Definition player.h:115
enum diplstate_type type
Definition player.h:197
int infra_points
Definition player.h:65
int units_killed
Definition player.h:103
int landarea
Definition player.h:92
int population
Definition player.h:94
int pollution
Definition player.h:97
int wonders
Definition player.h:89
int settledarea
Definition player.h:93
int units_used
Definition player.h:106
int specialists[SP_MAX]
Definition player.h:88
int units_lost
Definition player.h:104
int angry
Definition player.h:87
int techout
Definition player.h:91
int units
Definition player.h:96
int units_built
Definition player.h:102
int content
Definition player.h:85
int happy
Definition player.h:84
int spaceship
Definition player.h:101
int culture
Definition player.h:107
int unhappy
Definition player.h:86
int cities
Definition player.h:95
int literacy
Definition player.h:98
int techs
Definition player.h:90
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:279
int bulbs_last_turn
Definition player.h:349
struct player_ai ai_common
Definition player.h:286
bv_plr_flags flags
Definition player.h:290
bool is_male
Definition player.h:255
int wonders[B_LAST]
Definition player.h:303
bool unassigned_ranked
Definition player.h:253
struct government * target_government
Definition player.h:257
int autoselect_weight
Definition player.h:297
char username[MAX_LEN_NAME]
Definition player.h:250
int revolution_finishes
Definition player.h:271
int nturns_idle
Definition player.h:263
struct government * government
Definition player.h:256
struct team * team
Definition player.h:259
int turns_alive
Definition player.h:264
const struct ai_type * ai
Definition player.h:287
struct unit_list * units
Definition player.h:280
char ranked_username[MAX_LEN_NAME]
Definition player.h:252
int huts
Definition player.h:347
bool is_alive
Definition player.h:266
bv_player real_embassy
Definition player.h:275
struct player_economic economic
Definition player.h:282
struct player_spaceship spaceship
Definition player.h:284
struct attribute_block_s attribute_block
Definition player.h:305
struct player_score score
Definition player.h:281
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:312
struct nation_type * nation
Definition player.h:258
struct nation_style * style
Definition player.h:277
bool border_vision
Definition player.h:325
bool phase_done
Definition player.h:261
struct adv_data * adv
Definition player.h:332
struct player::@70::@72 server
int history
Definition player.h:314
char orig_username[MAX_LEN_NAME]
Definition player.h:345
int last_war_action
Definition player.h:268
struct rgbcolor * rgb
Definition player.h:310
bool unassigned_user
Definition player.h:251
const char * save_reason
Definition savegame3.c:269
struct section_file * file
Definition savegame3.c:265
bool scenario
Definition savegame3.c:270
bool save_players
Definition savegame3.c:273
char secfile_options[512]
Definition savegame3.c:266
char metaserver_addr[256]
Definition srv_main.h:29
char serverid[256]
Definition srv_main.h:49
Definition map.c:41
Definition team.c:40
char identifier
Definition terrain.h:191
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int infra_turns
Definition tile.h:62
struct extra_type * placing
Definition tile.h:61
struct tile * claimer
Definition tile.h:64
Definition timing.c:81
enum route_direction dir
Definition traderoutes.h:86
struct section_file * file
Definition savegame3.c:7763
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:138
int length
Definition unit.h:195
int upkeep[O_LAST]
Definition unit.h:148
bool has_orders
Definition unit.h:193
struct unit::@80 orders
enum action_decision action_decision_want
Definition unit.h:202
int battlegroup
Definition unit.h:191
enum unit_activity activity
Definition unit.h:157
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
int ord_city
Definition unit.h:242
bool moved
Definition unit.h:173
int ord_map
Definition unit.h:241
int index
Definition unit.h:195
struct vision * vision
Definition unit.h:244
bool vigilant
Definition unit.h:197
int hp
Definition unit.h:151
int fuel
Definition unit.h:153
struct extra_type * changed_from_target
Definition unit.h:170
int current_form_turn
Definition unit.h:208
bool stay
Definition unit.h:205
enum direction8 facing
Definition unit.h:142
struct unit::@81::@84 server
struct extra_type * activity_target
Definition unit.h:164
int activity_count
Definition unit.h:162
struct unit_order * list
Definition unit.h:198
enum unit_activity changed_from
Definition unit.h:168
struct player * nationality
Definition unit.h:144
bool repeat
Definition unit.h:196
int homecity
Definition unit.h:146
bool paradropped
Definition unit.h:174
bool done_moving
Definition unit.h:181
int birth_turn
Definition unit.h:207
struct goods_type * carrying
Definition unit.h:186
struct tile * goto_tile
Definition unit.h:155
struct tile * action_decision_tile
Definition unit.h:203
int veteran
Definition unit.h:152
int changed_from_count
Definition unit.h:169
enum server_side_agent ssa_controller
Definition unit.h:172
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct civ_map map
int city_style(struct city *pcity)
Definition style.c:241
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
int team_index(const struct team *pteam)
Definition team.c:383
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
bool team_add_player(struct player *pplayer, struct team *pteam)
Definition team.c:467
struct team * team_new(struct team_slot *tslot)
Definition team.c:317
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:248
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:275
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:276
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:244
void init_tech(struct research *research, bool update)
Definition techtools.c:1094
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:255
#define terrain_type_iterate(_p)
Definition terrain.h:373
#define T_UNKNOWN
Definition terrain.h:57
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:195
#define terrain_type_iterate_end
Definition terrain.h:379
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1095
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
void tile_set_worked(struct tile *ptile, struct city *pcity)
Definition tile.c:106
#define tile_index(_pt_)
Definition tile.h:88
#define tile_worked(_tile)
Definition tile.h:118
#define tile_terrain(_tile)
Definition tile.h:114
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:151
#define tile_owner(_tile)
Definition tile.h:96
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:264
void timer_stop(struct timer *t)
Definition timing.c:308
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:384
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
const struct impr_type * building
Definition fc_types.h:714
void free_unit_orders(struct unit *punit)
Definition unit.c:1777
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2378
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1096
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1253
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2449
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:849
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target)
Definition unit.c:1113
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1632
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2657
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1737
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1263
#define unit_tile(_pu)
Definition unit.h:397
#define BATTLEGROUP_NONE
Definition unit.h:190
unit_orders
Definition unit.h:37
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_owner(_pu)
Definition unit.h:396
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1395
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4841
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1222
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1059
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2625
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
#define unit_type_iterate(_p)
Definition unittype.h:855
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:862
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:129
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24