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 "score.h"
123#include "settings.h"
124#include "spacerace.h"
125#include "srv_main.h"
126#include "stdinhand.h"
127#include "techtools.h"
128#include "unittools.h"
129
130/* server/advisors */
131#include "advdata.h"
132#include "advbuilding.h"
133#include "infracache.h"
134
135/* server/generator */
136#include "mapgen.h"
137#include "mapgen_utils.h"
138
139/* server/scripting */
140#include "script_server.h"
141
142/* server/savegame */
143#include "savecompat.h"
144#include "savemain.h"
145
146/* ai */
147#include "aitraits.h"
148#include "difficulty.h"
149
150#include "savegame3.h"
151
152extern bool sg_success;
153
154#define ACTIVITY_OLD_POLLUTION_SG3 (ACTIVITY_LAST + 1)
155#define ACTIVITY_OLD_FALLOUT_SG3 (ACTIVITY_OLD_POLLUTION_SG3 + 1)
156#define ACTIVITY_LAST_SAVEGAME3 (ACTIVITY_OLD_FALLOUT_SG3 + 1)
157
158#ifdef FREECIV_TESTMATIC
159#define SAVE_DUMMY_TURN_CHANGE_TIME 1
160#endif
161
162/*
163 * This loops over the entire map to save data. It collects all the data of
164 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
165 *
166 * Parameters:
167 * ptile: current tile within the line (used by GET_XY_CHAR)
168 * GET_XY_CHAR: macro returning the map character for each position
169 * secfile: a secfile struct
170 * secpath, ...: path as used for sprintf() with arguments; the last item
171 * will be the y coordinate
172 * Example:
173 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
174 */
175#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
176{ \
177 char _line[wld.map.xsize + 1]; \
178 int _nat_x, _nat_y; \
179 \
180 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
181 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
182 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
183 fc_assert_action(ptile != NULL, continue); \
184 _line[_nat_x] = (GET_XY_CHAR); \
185 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
186 "Trying to write invalid map data at position " \
187 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
188 secpath, _line[_nat_x], _line[_nat_x]); \
189 } \
190 _line[wld.map.xsize] = '\0'; \
191 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
192 } \
193}
194
195/*
196 * This loops over the entire map to load data. It inputs a line of data
197 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
198 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
199 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
200 * macro but definable by the caller.
201 *
202 * Parameters:
203 * ch: a variable to hold a char (data for a single position,
204 * used by SET_XY_CHAR)
205 * ptile: current tile within the line (used by SET_XY_CHAR)
206 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
207 * secfile: a secfile struct
208 * secpath, ...: path as used for sprintf() with arguments; the last item
209 * will be the y coordinate
210 * Example:
211 * LOAD_MAP_CHAR(ch, ptile,
212 * map_get_player_tile(ptile, plr)->terrain
213 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
214 *
215 * Note: some (but not all) of the code this is replacing used to skip over
216 * lines that did not exist. This allowed for backward-compatibility.
217 * We could add another parameter that specified whether it was OK to
218 * skip the data, but there's not really much advantage to exiting
219 * early in this case. Instead, we let any map data type to be empty,
220 * and just print an informative warning message about it.
221 */
222#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
223{ \
224 int _nat_x, _nat_y; \
225 bool _printed_warning = FALSE; \
226 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
227 const char *_line = secfile_lookup_str(secfile, secpath, \
228 ## __VA_ARGS__, _nat_y); \
229 if (NULL == _line) { \
230 char buf[64]; \
231 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
232 log_verbose("Line not found='%s'", buf); \
233 _printed_warning = TRUE; \
234 continue; \
235 } else if (strlen(_line) != wld.map.xsize) { \
236 char buf[64]; \
237 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
238 log_verbose("Line too short (expected %d got " SIZE_T_PRINTF \
239 ")='%s'", wld.map.xsize, strlen(_line), buf); \
240 _printed_warning = TRUE; \
241 continue; \
242 } \
243 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
244 const char ch = _line[_nat_x]; \
245 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
246 (SET_XY_CHAR); \
247 } \
248 } \
249 if (_printed_warning) { \
250 /* TRANS: Minor error message. */ \
251 log_sg(_("Saved game contains incomplete map data. This can" \
252 " happen with old saved games, or it may indicate an" \
253 " invalid saved game file. Proceed at your own risk.")); \
254 } \
255}
256
257/* Iterate on the extras half-bytes */
258#define halfbyte_iterate_extras(e, num_extras_types) \
259{ \
260 int e; \
261 for (e = 0; 4 * e < (num_extras_types); e++) {
262
263#define halfbyte_iterate_extras_end \
264 } \
265}
266
267struct savedata {
270
271 /* set by the caller */
272 const char *save_reason;
274
275 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
277};
278
279#define TOKEN_SIZE 10
280
281static const char savefile_options_default[] =
282 " +version3";
283/* The following savefile option are added if needed:
284 * - nothing at current version
285 * See also calls to sg_save_savefile_options(). */
286
287static void savegame3_save_real(struct section_file *file,
288 const char *save_reason,
289 bool scenario);
290static struct loaddata *loaddata_new(struct section_file *file);
291static void loaddata_destroy(struct loaddata *loading);
292
293static struct savedata *savedata_new(struct section_file *file,
294 const char *save_reason,
295 bool scenario);
296static void savedata_destroy(struct savedata *saving);
297
298static enum unit_orders char2order(char order);
299static char order2char(enum unit_orders order);
300static enum direction8 char2dir(char dir);
301static char dir2char(enum direction8 dir);
302static char activity2char(int activity);
303static enum unit_activity char2activity(char activity);
304static char *quote_block(const void *const data, int length);
305static int unquote_block(const char *const quoted_, void *dest,
306 int dest_length);
307static void worklist_load(struct section_file *file, int wlist_max_length,
308 struct worklist *pwl, const char *path, ...);
309static void worklist_save(struct section_file *file,
310 const struct worklist *pwl,
311 int max_length, const char *path, ...);
312static void unit_ordering_calc(void);
313static void unit_ordering_apply(void);
314static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx);
315static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx);
316static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
317 const int *idx);
318static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
319 const int *idx);
320static struct terrain *char2terrain(char ch);
321static char terrain2char(const struct terrain *pterrain);
322static Tech_type_id technology_load(struct section_file *file,
323 const char *path, int plrno);
324static void technology_save(struct section_file *file,
325 const char *path, int plrno, Tech_type_id tech);
326
327static void sg_load_savefile(struct loaddata *loading);
328static void sg_save_savefile(struct savedata *saving);
329static void sg_save_savefile_options(struct savedata *saving,
330 const char *option);
331
332static void sg_load_game(struct loaddata *loading);
333static void sg_save_game(struct savedata *saving);
334
335static void sg_load_ruledata(struct loaddata *loading);
336static void sg_save_ruledata(struct savedata *saving);
337
338static void sg_load_random(struct loaddata *loading);
339static void sg_save_random(struct savedata *saving);
340
341static void sg_load_script(struct loaddata *loading);
342static void sg_save_script(struct savedata *saving);
343
344static void sg_load_scenario(struct loaddata *loading);
345static void sg_save_scenario(struct savedata *saving);
346
347static void sg_load_settings(struct loaddata *loading);
348static void sg_save_settings(struct savedata *saving);
349
350static void sg_load_counters (struct loaddata * loading);
351static void sg_save_counters (struct savedata * saving);
352
353static void sg_load_map(struct loaddata *loading);
354static void sg_save_map(struct savedata *saving);
355static void sg_load_map_tiles(struct loaddata *loading);
356static void sg_save_map_tiles(struct savedata *saving);
357static void sg_load_map_tiles_extras(struct loaddata *loading);
358static void sg_save_map_tiles_extras(struct savedata *saving);
359
360static void sg_load_map_startpos(struct loaddata *loading);
361static void sg_save_map_startpos(struct savedata *saving);
362static void sg_load_map_owner(struct loaddata *loading);
363static void sg_save_map_owner(struct savedata *saving);
364static void sg_load_map_worked(struct loaddata *loading);
365static void sg_save_map_worked(struct savedata *saving);
366static void sg_load_map_known(struct loaddata *loading);
367static void sg_save_map_known(struct savedata *saving);
368
369static void sg_load_players_basic(struct loaddata *loading);
370static void sg_load_players(struct loaddata *loading);
371static void sg_load_player_main(struct loaddata *loading,
372 struct player *plr);
373static void sg_load_player_cities(struct loaddata *loading,
374 struct player *plr);
375static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
376 struct city *pcity, const char *citystr,
379 struct player *plr,
380 struct city *pcity,
381 const char *citystr);
382static void sg_load_player_units(struct loaddata *loading,
383 struct player *plr);
384static bool sg_load_player_unit(struct loaddata *loading,
385 struct player *plr, struct unit *punit,
387 const char *unitstr);
389 struct player *plr);
390static void sg_load_player_attributes(struct loaddata *loading,
391 struct player *plr);
392static void sg_load_player_vision(struct loaddata *loading,
393 struct player *plr);
395 struct player *plr,
396 struct vision_site *pdcity,
397 const char *citystr);
398static void sg_save_players(struct savedata *saving);
399static void sg_save_player_main(struct savedata *saving,
400 struct player *plr);
401static void sg_save_player_cities(struct savedata *saving,
402 struct player *plr);
403static void sg_save_player_units(struct savedata *saving,
404 struct player *plr);
405static void sg_save_player_attributes(struct savedata *saving,
406 struct player *plr);
407static void sg_save_player_vision(struct savedata *saving,
408 struct player *plr);
409
410static void sg_load_researches(struct loaddata *loading);
411static void sg_save_researches(struct savedata *saving);
412
413static void sg_load_event_cache(struct loaddata *loading);
414static void sg_save_event_cache(struct savedata *saving);
415
416static void sg_load_treaties(struct loaddata *loading);
417static void sg_save_treaties(struct savedata *saving);
418
419static void sg_load_history(struct loaddata *loading);
420static void sg_save_history(struct savedata *saving);
421
422static void sg_load_mapimg(struct loaddata *loading);
423static void sg_save_mapimg(struct savedata *saving);
424
425static void sg_load_sanitycheck(struct loaddata *loading);
426static void sg_save_sanitycheck(struct savedata *saving);
427
428
429/************************************************************************/
432void savegame3_save(struct section_file *sfile, const char *save_reason,
433 bool scenario)
434{
435 fc_assert_ret(sfile != NULL);
436
437#ifdef DEBUG_TIMERS
438 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
440#endif
441
442 log_verbose("saving game in new format ...");
443 savegame3_save_real(sfile, save_reason, scenario);
444
445#ifdef DEBUG_TIMERS
447 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
449#endif /* DEBUG_TIMERS */
450}
451
452/* =======================================================================
453 * Basic load / save functions.
454 * ======================================================================= */
455
456/************************************************************************/
459void savegame3_load(struct section_file *file)
460{
461 struct loaddata *loading;
463
464 /* initialise loading */
469
470 /* Load the savegame data. */
471 /* [compat] */
473 /* [scenario] */
475 /* [savefile] */
477 /* [game] */
479 /* [random] */
481 /* [settings] */
483 /* [ruledata] */
485 /* [players] (basic data) */
487 /* [map]; needs width and height loaded by [settings] */
489 /* [research] */
491 /* [player<i>] */
493 /* [counters] */
495 /* [event_cache] */
497 /* [treaties] */
499 /* [history] */
501 /* [mapimg] */
503 /* [script] -- must come last as may reference game objects */
505 /* [post_load_compat]; needs the game loaded by [savefile] */
507
508 /* Sanity checks for the loaded game. */
510
511 /* deinitialise loading */
515
516 if (!sg_success) {
517 log_error("Failure loading savegame!");
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 if (pwl->length > MAX_LEN_WORKLIST) {
983 log_sg("worklist length %d, while MAX_LEN_WORKLIST %d.",
984 pwl->length, MAX_LEN_WORKLIST);
985 pwl->length = MAX_LEN_WORKLIST;
986 } else if (pwl->length > wlist_max_length) {
987 log_sg("worklist length %d, while player's max worklist length %d.",
988 pwl->length, wlist_max_length);
989 }
990
991 for (i = 0; i < pwl->length; i++) {
992 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
993
994 /* We lookup the production value by name. An invalid entry isn't a
995 * fatal error; we just truncate the worklist. */
996 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
997 path_str, i);
998 pwl->entries[i] = universal_by_rule_name(kind, name);
999 if (pwl->entries[i].kind == universals_n_invalid()) {
1000 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
1001 name);
1002 pwl->length = i;
1003 break;
1004 }
1005 }
1006
1007 /* Padding entries */
1008 for (; i < wlist_max_length; i++) {
1009 (void) secfile_entry_lookup(file, "%s.wl_kind%d", path_str, i);
1010 (void) secfile_entry_lookup(file, "%s.wl_value%d", path_str, i);
1011 }
1012}
1013
1014/************************************************************************/
1018static void worklist_save(struct section_file *file,
1019 const struct worklist *pwl,
1020 int max_length, const char *path, ...)
1021{
1022 char path_str[1024];
1023 int i;
1024 va_list ap;
1025
1026 /* The first part of the registry path is taken from the varargs to the
1027 * function. */
1028 va_start(ap, path);
1029 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1030 va_end(ap);
1031
1032 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1033
1034 for (i = 0; i < pwl->length; i++) {
1035 const struct universal *entry = pwl->entries + i;
1037 "%s.wl_kind%d", path_str, i);
1039 "%s.wl_value%d", path_str, i);
1040 }
1041
1043
1044 /* We want to keep savegame in tabular format, so each line has to be
1045 * of equal length. Fill table up to maximum worklist size. */
1046 for (i = pwl->length ; i < max_length; i++) {
1047 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1048 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1049 }
1050}
1051
1052/************************************************************************/
1056static void unit_ordering_calc(void)
1057{
1058 int j;
1059
1060 players_iterate(pplayer) {
1061 /* to avoid junk values for unsupported units: */
1062 unit_list_iterate(pplayer->units, punit) {
1063 punit->server.ord_city = 0;
1065 city_list_iterate(pplayer->cities, pcity) {
1066 j = 0;
1067 unit_list_iterate(pcity->units_supported, punit) {
1068 punit->server.ord_city = j++;
1072
1073 whole_map_iterate(&(wld.map), ptile) {
1074 j = 0;
1075 unit_list_iterate(ptile->units, punit) {
1076 punit->server.ord_map = j++;
1079}
1080
1081/************************************************************************/
1085static void unit_ordering_apply(void)
1086{
1087 players_iterate(pplayer) {
1088 city_list_iterate(pplayer->cities, pcity) {
1089 unit_list_sort_ord_city(pcity->units_supported);
1090 }
1093
1094 whole_map_iterate(&(wld.map), ptile) {
1095 unit_list_sort_ord_map(ptile->units);
1097}
1098
1099/************************************************************************/
1106static void sg_extras_set_dbv(struct dbv *extras, char ch,
1107 struct extra_type **idx)
1108{
1109 int i, bin;
1110 const char *pch = strchr(hex_chars, ch);
1111
1112 if (!pch || ch == '\0') {
1113 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1114 bin = 0;
1115 } else {
1116 bin = pch - hex_chars;
1117 }
1118
1119 for (i = 0; i < 4; i++) {
1120 struct extra_type *pextra = idx[i];
1121
1122 if (pextra == NULL) {
1123 continue;
1124 }
1125 if ((bin & (1 << i))
1126 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1127 dbv_set(extras, extra_index(pextra));
1128 }
1129 }
1130}
1131
1132/************************************************************************/
1140 struct extra_type **idx)
1141{
1142 int i, bin;
1143 const char *pch = strchr(hex_chars, ch);
1144
1145 if (!pch || ch == '\0') {
1146 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1147 bin = 0;
1148 } else {
1149 bin = pch - hex_chars;
1150 }
1151
1152 for (i = 0; i < 4; i++) {
1153 struct extra_type *pextra = idx[i];
1154
1155 if (pextra == NULL) {
1156 continue;
1157 }
1158 if ((bin & (1 << i))
1159 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1160 BV_SET(*extras, extra_index(pextra));
1161 }
1162 }
1163}
1164
1165/************************************************************************/
1171static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1172 const int *idx)
1173{
1174 int i, bin = 0;
1175 int max = dbv_bits(extras);
1176
1177 for (i = 0; i < 4; i++) {
1178 int extra = idx[i];
1179
1180 if (extra < 0) {
1181 break;
1182 }
1183
1184 if (extra < max
1185 && (dbv_isset(extras, extra)
1186 /* An invalid resource, a resource that can't exist at the tile's
1187 * current terrain, isn't in the bit extra vector. Save it so it
1188 * can return if the tile's terrain changes to something it can
1189 * exist on. */
1190 || extra_by_number(extra) == presource)) {
1191 bin |= (1 << i);
1192 }
1193 }
1194
1195 return hex_chars[bin];
1196}
1197
1198/************************************************************************/
1204static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1205 const int *idx)
1206{
1207 int i, bin = 0;
1208
1209 for (i = 0; i < 4; i++) {
1210 int extra = idx[i];
1211
1212 if (extra < 0) {
1213 break;
1214 }
1215
1216 if (BV_ISSET(extras, extra)
1217 /* An invalid resource, a resource that can't exist at the tile's
1218 * current terrain, isn't in the bit extra vector. Save it so it
1219 * can return if the tile's terrain changes to something it can
1220 * exist on. */
1221 || extra_by_number(extra) == presource) {
1222 bin |= (1 << i);
1223 }
1224 }
1225
1226 return hex_chars[bin];
1227}
1228
1229/************************************************************************/
1233static struct terrain *char2terrain(char ch)
1234{
1235 /* terrain_by_identifier plus fatal error */
1237 return T_UNKNOWN;
1238 }
1239 terrain_type_iterate(pterrain) {
1240 if (pterrain->identifier_load == ch) {
1241 return pterrain;
1242 }
1244
1245 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1246
1248
1250}
1251
1252/************************************************************************/
1256static char terrain2char(const struct terrain *pterrain)
1257{
1258 if (pterrain == T_UNKNOWN) {
1260 } else {
1261 return pterrain->identifier;
1262 }
1263}
1264
1265/************************************************************************/
1269 const char *path, int plrno)
1270{
1271 char path_with_name[128];
1272 const char *name;
1273 struct advance *padvance;
1274
1276 "%s_name", path);
1277
1279
1280 if (!name || name[0] == '\0') {
1281 /* used by researching_saved */
1282 return A_UNKNOWN;
1283 }
1284 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1285 return A_FUTURE;
1286 }
1287 if (fc_strcasecmp(name, "A_NONE") == 0) {
1288 return A_NONE;
1289 }
1290 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1291 return A_UNSET;
1292 }
1293
1296 "%s: unknown technology \"%s\".", path_with_name, name);
1297
1298 return advance_number(padvance);
1299}
1300
1301/************************************************************************/
1304static void technology_save(struct section_file *file,
1305 const char *path, int plrno, Tech_type_id tech)
1306{
1307 char path_with_name[128];
1308 const char *name;
1309
1311 "%s_name", path);
1312
1313 switch (tech) {
1314 case A_UNKNOWN: /* used by researching_saved */
1315 name = "";
1316 break;
1317 case A_NONE:
1318 name = "A_NONE";
1319 break;
1320 case A_UNSET:
1321 name = "A_UNSET";
1322 break;
1323 case A_FUTURE:
1324 name = "A_FUTURE";
1325 break;
1326 default:
1328 break;
1329 }
1330
1332}
1333
1334/* =======================================================================
1335 * Load / save savefile data.
1336 * ======================================================================= */
1337
1338/************************************************************************/
1342{
1343 int i;
1344 const char *terr_name;
1345 bool ruleset_datafile;
1347 const char *str;
1348
1349 /* Check status and return if not OK (sg_success FALSE). */
1350 sg_check_ret();
1351
1352 /* Load savefile options. */
1353 loading->secfile_options
1354 = secfile_lookup_str(loading->file, "savefile.options");
1355
1356 /* We don't need these entries, but read them anyway to avoid
1357 * warnings about unread secfile entries. */
1358 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1359 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1360
1361 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1363
1364 if (game.scenario.datafile[0] != '\0') {
1366 } else {
1368 }
1369
1372 const char *req_caps;
1373
1376 /* Failed to load correct ruleset */
1377 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1379 }
1380
1381 req_caps = secfile_lookup_str_default(loading->file, "",
1382 "scenario.ruleset_caps");
1383 strncpy(game.scenario.req_caps, req_caps,
1384 sizeof(game.scenario.req_caps) - 1);
1385 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1386
1387 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1388 /* Current ruleset lacks required capabilities. */
1389 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1390 log_normal(_("Ruleset has capabilities: %s"),
1392 /* TRANS: ... ruleset dir ... scenario name ... */
1393 log_error(_("Current ruleset %s not compatible with the scenario %s."
1394 " Trying to switch to the ruleset specified by the"
1395 " scenario."),
1397
1399 }
1400 }
1401
1404 const char *ruleset, *alt_dir;
1405
1408 "savefile.rulesetdir");
1409
1410 /* Load ruleset. */
1412 if (!strcmp("default", game.server.rulesetdir)) {
1413 /* Here 'default' really means current default.
1414 * Saving happens with real ruleset name, so savegames containing this
1415 * are special scenarios. */
1417 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1419 }
1420
1421 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1422 "savefile.ruleset_alt_dir");
1423
1424 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1425 if (alt_dir) {
1427 _("Failed to load either of rulesets '%s' or '%s' "
1428 "needed for savegame."),
1429 ruleset, alt_dir);
1430 } else {
1432 _("Failed to load ruleset '%s' needed for savegame."),
1433 ruleset);
1434 }
1435 }
1436
1438 /* TRANS: ruleset dir */
1439 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1440 }
1441 }
1442
1443 /* Remove all aifill players. Correct number of them get created later
1444 * with correct skill level etc. */
1445 (void) aifill(0);
1446
1447 /* Time to load scenario specific luadata */
1448 if (game.scenario.datafile[0] != '\0') {
1449 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1451 } else {
1452 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1453 const struct strvec **path;
1454 const char *found = NULL;
1455 char testfile[MAX_LEN_PATH];
1456 struct section_file *secfile;
1457
1458 for (path = paths; found == NULL && *path != NULL; path++) {
1459 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1460
1461 found = fileinfoname(*path, testfile);
1462 }
1463
1464 if (found == NULL) {
1465 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1466 sg_success = FALSE;
1467 return;
1468 }
1469
1470 secfile = secfile_load(found, FALSE);
1471 if (secfile == NULL) {
1472 log_error(_("Failed to load scenario luadata file %s.luadata"),
1474 sg_success = FALSE;
1475 return;
1476 }
1477
1478 game.server.luadata = secfile;
1479 }
1480 }
1481
1483 "savefile.dbid");
1484
1485 /* This is in the savegame only if the game has been started before savegame3.c time,
1486 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1488 "savefile.last_updated_as_year");
1489
1490 /* Load improvements. */
1491 loading->improvement.size
1493 "savefile.improvement_size");
1494 if (loading->improvement.size) {
1495 loading->improvement.order
1496 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1497 "savefile.improvement_vector");
1498 sg_failure_ret(loading->improvement.size != 0,
1499 "Failed to load improvement order: %s",
1500 secfile_error());
1501 }
1502
1503 /* Load technologies. */
1504 loading->technology.size
1506 "savefile.technology_size");
1507 if (loading->technology.size) {
1508 loading->technology.order
1509 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1510 "savefile.technology_vector");
1511 sg_failure_ret(loading->technology.size != 0,
1512 "Failed to load technology order: %s",
1513 secfile_error());
1514 }
1515
1516 /* Load Activities. */
1517 loading->activities.size
1519 "savefile.activities_size");
1520 if (loading->activities.size) {
1521 loading->activities.order
1522 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1523 "savefile.activities_vector");
1524 sg_failure_ret(loading->activities.size != 0,
1525 "Failed to load activity order: %s",
1526 secfile_error());
1527 }
1528
1529 /* Load traits. */
1530 loading->trait.size
1532 "savefile.trait_size");
1533 if (loading->trait.size) {
1534 loading->trait.order
1535 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1536 "savefile.trait_vector");
1537 sg_failure_ret(loading->trait.size != 0,
1538 "Failed to load trait order: %s",
1539 secfile_error());
1540 }
1541
1542 /* Load extras. */
1543 loading->extra.size
1545 "savefile.extras_size");
1546 if (loading->extra.size) {
1547 const char **modname;
1548 size_t nmod;
1549 int j;
1550
1551 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1552 "savefile.extras_vector");
1553 sg_failure_ret(loading->extra.size != 0,
1554 "Failed to load extras order: %s",
1555 secfile_error());
1557 "Number of extras defined by the ruleset (= %d) are "
1558 "lower than the number in the savefile (= %d).",
1559 game.control.num_extra_types, (int)loading->extra.size);
1560 /* make sure that the size of the array is divisible by 4 */
1561 nmod = 4 * ((loading->extra.size + 3) / 4);
1562 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1563 for (j = 0; j < loading->extra.size; j++) {
1564 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1565 }
1566 free(modname);
1567 for (; j < nmod; j++) {
1568 loading->extra.order[j] = NULL;
1569 }
1570 }
1571
1572 /* Load multipliers. */
1573 loading->multiplier.size
1575 "savefile.multipliers_size");
1576 if (loading->multiplier.size) {
1577 const char **modname;
1578 int j;
1579
1580 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1581 "savefile.multipliers_vector");
1582 sg_failure_ret(loading->multiplier.size != 0,
1583 "Failed to load multipliers order: %s",
1584 secfile_error());
1585 /* It's OK for the set of multipliers in the savefile to differ
1586 * from those in the ruleset. */
1587 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1588 sizeof(*loading->multiplier.order));
1589 for (j = 0; j < loading->multiplier.size; j++) {
1590 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1591 if (!loading->multiplier.order[j]) {
1592 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1593 "discarding", modname[j]);
1594 }
1595 }
1596 free(modname);
1597 }
1598
1599 /* Load specialists. */
1600 loading->specialist.size
1602 "savefile.specialists_size");
1603 if (loading->specialist.size) {
1604 const char **modname;
1605 size_t nmod;
1606 int j;
1607
1608 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1609 "savefile.specialists_vector");
1610 sg_failure_ret(loading->specialist.size != 0,
1611 "Failed to load specialists order: %s",
1612 secfile_error());
1614 "Number of specialists defined by the ruleset (= %d) are "
1615 "lower than the number in the savefile (= %d).",
1616 game.control.num_specialist_types, (int)loading->specialist.size);
1617 /* make sure that the size of the array is divisible by 4 */
1618 /* That's not really needed with specialists at the moment, but done this way
1619 * for consistency with other types, and to be prepared for the time it needs
1620 * to be this way. */
1621 nmod = 4 * ((loading->specialist.size + 3) / 4);
1622 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1623 for (j = 0; j < loading->specialist.size; j++) {
1624 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1625 }
1626 free(modname);
1627 for (; j < nmod; j++) {
1628 loading->specialist.order[j] = NULL;
1629 }
1630 }
1631
1632 /* Load action order. */
1633 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1634 "savefile.action_size");
1635
1636 sg_failure_ret(loading->action.size > 0,
1637 "Failed to load action order: %s",
1638 secfile_error());
1639
1640 if (loading->action.size) {
1641 const char **modname;
1642 int j;
1643
1644 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1645 "savefile.action_vector");
1646
1647 loading->action.order = fc_calloc(loading->action.size,
1648 sizeof(*loading->action.order));
1649
1650 for (j = 0; j < loading->action.size; j++) {
1652
1653 if (real_action) {
1654 loading->action.order[j] = real_action->id;
1655 } else {
1656 log_sg("Unknown action \'%s\'", modname[j]);
1657 loading->action.order[j] = ACTION_NONE;
1658 }
1659 }
1660
1661 free(modname);
1662 }
1663
1664 /* Load action decision order. */
1665 loading->act_dec.size
1667 "savefile.action_decision_size");
1668
1669 sg_failure_ret(loading->act_dec.size > 0,
1670 "Failed to load action decision order: %s",
1671 secfile_error());
1672
1673 if (loading->act_dec.size) {
1674 const char **modname;
1675 int j;
1676
1677 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1678 "savefile.action_decision_vector");
1679
1680 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1681 sizeof(*loading->act_dec.order));
1682
1683 for (j = 0; j < loading->act_dec.size; j++) {
1684 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1686 }
1687
1688 free(modname);
1689 }
1690
1691 /* Load server side agent order. */
1692 loading->ssa.size
1694 "savefile.server_side_agent_size");
1695
1696 sg_failure_ret(loading->ssa.size > 0,
1697 "Failed to load server side agent order: %s",
1698 secfile_error());
1699
1700 if (loading->ssa.size) {
1701 const char **modname;
1702 int j;
1703
1704 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1705 "savefile.server_side_agent_list");
1706
1707 loading->ssa.order = fc_calloc(loading->ssa.size,
1708 sizeof(*loading->ssa.order));
1709
1710 for (j = 0; j < loading->ssa.size; j++) {
1711 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1713 }
1714
1715 free(modname);
1716 }
1717
1718 /* Load city options order. */
1719 loading->coptions.size
1721 "savefile.city_options_size");
1722
1723 sg_failure_ret(loading->coptions.size > 0,
1724 "Failed to load city options order: %s",
1725 secfile_error());
1726
1727 if (loading->coptions.size) {
1728 const char **modname;
1729 int j;
1730
1731 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1732 "savefile.city_options_vector");
1733
1734 loading->coptions.order = fc_calloc(loading->coptions.size,
1735 sizeof(*loading->coptions.order));
1736
1737 for (j = 0; j < loading->coptions.size; j++) {
1738 loading->coptions.order[j] = city_options_by_name(modname[j],
1740 }
1741
1742 free(modname);
1743 }
1744
1745 /* Terrain identifiers */
1747 pterr->identifier_load = '\0';
1749
1750 i = 0;
1752 "savefile.terrident%d.name", i)) != NULL) {
1754
1755 if (pterr != NULL) {
1756 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1757 "savefile.terrident%d.identifier", i);
1758
1759 pterr->identifier_load = *iptr;
1760 } else {
1761 log_error("Identifier for unknown terrain type %s.", terr_name);
1762 }
1763 i++;
1764 }
1765
1768 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1769 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1770 "%s and %s share a saved identifier",
1772 }
1775}
1776
1777/************************************************************************/
1781{
1782 int i;
1783
1784 /* Check status and return if not OK (sg_success FALSE). */
1785 sg_check_ret();
1786
1787 /* Save savefile options. */
1789
1790 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1791
1792 /* Save reason of the savefile generation. */
1793 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1794
1795 /* Save as accurate freeciv revision information as possible */
1796 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1797
1798 /* Freeciv version used in the very first launch of this game -
1799 * or even saving in pregame. */
1801 "savefile.orig_version");
1802
1803 /* Save rulesetdir at this point as this ruleset is required by this
1804 * savefile. */
1805 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1806
1807 if (game.control.version[0] != '\0') {
1808 /* Current ruleset has version information, save it.
1809 * This is never loaded, but exist in savegame file only for debugging purposes. */
1810 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1811 }
1812
1813 if (game.control.alt_dir[0] != '\0') {
1814 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1815 }
1816
1818 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1819 }
1820
1821 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1822
1823 /* Save improvement order in savegame, so we are not dependent on ruleset
1824 * order. If the game isn't started improvements aren't loaded so we can
1825 * not save the order. */
1827 "savefile.improvement_size");
1828 if (improvement_count() > 0) {
1829 const char *buf[improvement_count()];
1830
1831 improvement_iterate(pimprove) {
1832 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1834
1836 "savefile.improvement_vector");
1837 }
1838
1839 /* Save technology order in savegame, so we are not dependent on ruleset
1840 * order. If the game isn't started advances aren't loaded so we can not
1841 * save the order. */
1843 "savefile.technology_size");
1844 if (game.control.num_tech_types > 0) {
1845 const char *buf[game.control.num_tech_types];
1846
1847 buf[A_NONE] = "A_NONE";
1848 advance_iterate(a) {
1852 "savefile.technology_vector");
1853 }
1854
1855 /* Save activities order in the savegame. */
1857 "savefile.activities_size");
1858 if (ACTIVITY_LAST > 0) {
1859 const char **modname;
1860 int j;
1861
1862 i = 0;
1863
1865
1866 for (j = 0; j < ACTIVITY_LAST; j++) {
1868 }
1869
1872 "savefile.activities_vector");
1873 free(modname);
1874 }
1875
1876 /* Save specialists order in the savegame. */
1878 "savefile.specialists_size");
1879 {
1880 const char **modname;
1881
1882 i = 0;
1884
1888
1890 "savefile.specialists_vector");
1891
1892 free(modname);
1893 }
1894
1895 /* Save trait order in savegame. */
1897 "savefile.trait_size");
1898 {
1899 const char **modname;
1900 enum trait tr;
1901 int j;
1902
1903 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1904
1905 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1906 modname[j] = trait_name(tr);
1907 }
1908
1910 "savefile.trait_vector");
1911 free(modname);
1912 }
1913
1914 /* Save extras order in the savegame. */
1916 "savefile.extras_size");
1917 if (game.control.num_extra_types > 0) {
1918 const char **modname;
1919
1920 i = 0;
1922
1923 extra_type_iterate(pextra) {
1924 modname[i++] = extra_rule_name(pextra);
1926
1929 "savefile.extras_vector");
1930 free(modname);
1931 }
1932
1933 /* Save multipliers order in the savegame. */
1935 "savefile.multipliers_size");
1936 if (multiplier_count() > 0) {
1937 const char **modname;
1938
1940
1941 multipliers_iterate(pmul) {
1944
1947 "savefile.multipliers_vector");
1948 free(modname);
1949 }
1950
1951 /* Save city_option order in the savegame. */
1953 "savefile.city_options_size");
1954 if (CITYO_LAST > 0) {
1955 const char **modname;
1956 int j;
1957
1958 i = 0;
1959 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1960
1961 for (j = 0; j < CITYO_LAST; j++) {
1962 modname[i++] = city_options_name(j);
1963 }
1964
1966 CITYO_LAST,
1967 "savefile.city_options_vector");
1968 free(modname);
1969 }
1970
1971 /* Save action order in the savegame. */
1973 "savefile.action_size");
1974 if (NUM_ACTIONS > 0) {
1975 const char **modname;
1976 int j;
1977
1978 i = 0;
1979 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1980
1981 for (j = 0; j < NUM_ACTIONS; j++) {
1983 }
1984
1987 "savefile.action_vector");
1988 free(modname);
1989 }
1990
1991 /* Save action decision order in the savegame. */
1993 "savefile.action_decision_size");
1994 if (ACT_DEC_COUNT > 0) {
1995 const char **modname;
1996 int j;
1997
1998 i = 0;
2000
2001 for (j = 0; j < ACT_DEC_COUNT; j++) {
2003 }
2004
2007 "savefile.action_decision_vector");
2008 free(modname);
2009 }
2010
2011 /* Save server side agent order in the savegame. */
2013 "savefile.server_side_agent_size");
2014 if (SSA_COUNT > 0) {
2015 const char **modname;
2016 int j;
2017
2018 i = 0;
2019 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2020
2021 for (j = 0; j < SSA_COUNT; j++) {
2023 }
2024
2026 SSA_COUNT,
2027 "savefile.server_side_agent_list");
2028 free(modname);
2029 }
2030
2031 /* Save terrain character mapping in the savegame. */
2032 i = 0;
2034 char buf[2];
2035
2036 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2038 buf[1] = '\0';
2039 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2041}
2042
2043/************************************************************************/
2047 const char *option)
2048{
2049 /* Check status and return if not OK (sg_success FALSE). */
2050 sg_check_ret();
2051
2052 if (option == NULL) {
2053 /* no additional option */
2054 return;
2055 }
2056
2057 sz_strlcat(saving->secfile_options, option);
2058 secfile_replace_str(saving->file, saving->secfile_options,
2059 "savefile.options");
2060}
2061
2062/* =======================================================================
2063 * Load / save game status.
2064 * ======================================================================= */
2065
2066/************************************************************************/
2070{
2071 int i;
2072 const char *name;
2073
2074 /* Check status and return if not OK (sg_success FALSE). */
2075 sg_check_ret();
2076
2077 for (i = 0;
2079 "ruledata.government%d.name", i));
2080 i++) {
2082
2083 if (gov != NULL) {
2085 "ruledata.government%d.changes", i);
2086 }
2087 }
2088}
2089
2090/************************************************************************/
2093static void sg_load_game(struct loaddata *loading)
2094{
2095 const char *str;
2096 int i;
2097
2098 /* Check status and return if not OK (sg_success FALSE). */
2099 sg_check_ret();
2100
2101 /* Load server state. */
2102 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2103 "game.server_state");
2104 loading->server_state = server_states_by_name(str, strcmp);
2105 if (!server_states_is_valid(loading->server_state)) {
2106 /* Don't take any risk! */
2107 loading->server_state = S_S_INITIAL;
2108 }
2109
2111 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2112
2115 "game.meta_patches");
2117
2119 /* Do not overwrite this if the user requested a specific metaserver
2120 * from the command line (option --Metaserver). */
2124 "game.meta_server"));
2125 }
2126
2127 if ('\0' == srvarg.serverid[0]) {
2128 /* Do not overwrite this if the user requested a specific metaserver
2129 * from the command line (option --serverid). */
2132 "game.serverid"));
2133 }
2134 sz_strlcpy(server.game_identifier,
2135 secfile_lookup_str_default(loading->file, "", "game.id"));
2136 /* We are not checking game_identifier legality just yet.
2137 * That's done when we are sure that rand seed has been initialized,
2138 * so that we can generate new game_identifier, if needed.
2139 * See sq_load_sanitycheck(). */
2140
2142 "game.phase_mode");
2143 if (str != NULL) {
2146 log_error("Illegal phase mode \"%s\"", str);
2148 }
2149 } else {
2150 log_error("Phase mode missing");
2151 }
2152
2154 "game.phase_mode_stored");
2155 if (str != NULL) {
2158 log_error("Illegal stored phase mode \"%s\"", str);
2160 }
2161 } else {
2162 log_error("Stored phase mode missing");
2163 }
2166 "game.phase");
2170 "game.scoreturn");
2171
2174 "game.timeoutint");
2177 "game.timeoutintinc");
2180 "game.timeoutinc");
2183 "game.timeoutincmult");
2186 "game.timeoutcounter");
2187
2188 game.info.turn
2189 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2191 "game.year"), "%s", secfile_error());
2193 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2194
2196 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2198 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2200 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2201
2203 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2205 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2207 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2208
2209 /* Savegame may have stored random_seed for documentation purposes only,
2210 * but we want to keep it for resaving. */
2211 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2212
2213 /* Global advances. */
2215 "game.global_advances");
2216 if (str != NULL) {
2217 sg_failure_ret(strlen(str) == loading->technology.size,
2218 "Invalid length of 'game.global_advances' ("
2219 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2220 strlen(str), loading->technology.size);
2221 for (i = 0; i < loading->technology.size; i++) {
2222 sg_failure_ret(str[i] == '1' || str[i] == '0',
2223 "Undefined value '%c' within 'game.global_advances'.",
2224 str[i]);
2225 if (str[i] == '1') {
2226 struct advance *padvance
2227 = advance_by_rule_name(loading->technology.order[i]);
2228
2229 if (padvance != NULL) {
2231 }
2232 }
2233 }
2234 }
2235
2237 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2238
2240 = secfile_lookup_int_default(loading->file, 0, "game.last_turn_change_time") / 100.0;
2241}
2242
2243/************************************************************************/
2247{
2248 int set_count = 0;
2249
2251 char path[256];
2252
2253 fc_snprintf(path, sizeof(path),
2254 "ruledata.government%d", set_count++);
2255
2257 "%s.name", path);
2258 secfile_insert_int(saving->file, pgov->changed_to_times,
2259 "%s.changes", path);
2261}
2262
2263/************************************************************************/
2266static void sg_save_game(struct savedata *saving)
2267{
2269 char global_advances[game.control.num_tech_types + 1];
2270 int i;
2271
2272 /* Check status and return if not OK (sg_success FALSE). */
2273 sg_check_ret();
2274
2275 /* Game state: once the game is no longer a new game (ie, has been
2276 * started the first time), it should always be considered a running
2277 * game for savegame purposes. */
2278 if (saving->scenario && !game.scenario.players) {
2280 } else {
2282 }
2284 "game.server_state");
2285
2286 if (game.server.phase_timer != NULL) {
2290 "game.phase_seconds");
2291 }
2292
2294 "game.meta_patches");
2295 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2296
2297 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2298 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2299
2302 "game.phase_mode");
2305 "game.phase_mode_stored");
2307 "game.phase");
2309 "game.scoreturn");
2310
2312 "game.timeoutint");
2314 "game.timeoutintinc");
2316 "game.timeoutinc");
2318 "game.timeoutincmult");
2320 "game.timeoutcounter");
2321
2322 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2323 secfile_insert_int(saving->file, game.info.year, "game.year");
2325 "game.year_0_hack");
2326
2328 "game.globalwarming");
2330 "game.heating");
2332 "game.warminglevel");
2333
2335 "game.nuclearwinter");
2337 "game.cooling");
2339 "game.coolinglevel");
2340 /* For debugging purposes only.
2341 * Do not save it if it's 0 (not known);
2342 * this confuses people reading this 'document' less than
2343 * saving 0. */
2344 if (game.server.seed != 0) {
2346 "game.random_seed");
2347 }
2348
2349 /* Global advances. */
2350 for (i = 0; i < game.control.num_tech_types; i++) {
2351 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2352 }
2353 global_advances[i] = '\0';
2354 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2355
2356 if (!game_was_started()) {
2357 saving->save_players = FALSE;
2358 } else {
2359 if (saving->scenario) {
2360 saving->save_players = game.scenario.players;
2361 } else {
2362 saving->save_players = TRUE;
2363 }
2364#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2366 "game.last_turn_change_time");
2367#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2369 "game.last_turn_change_time");
2370#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2371 }
2372 secfile_insert_bool(saving->file, saving->save_players,
2373 "game.save_players");
2374
2375 if (srv_state != S_S_INITIAL) {
2376 const char *ainames[ai_type_get_count()];
2377
2378 i = 0;
2379 ai_type_iterate(ait) {
2380 ainames[i] = ait->name;
2381 i++;
2383
2385 "game.ai_types");
2386 }
2387}
2388
2389/* =======================================================================
2390 * Load / save random status.
2391 * ======================================================================= */
2392
2393/************************************************************************/
2396static void sg_load_random(struct loaddata *loading)
2397{
2398 /* Check status and return if not OK (sg_success FALSE). */
2399 sg_check_ret();
2400
2401 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2402 const char *str;
2403 int i;
2404
2406 "random.index_J"), "%s", secfile_error());
2408 "random.index_K"), "%s", secfile_error());
2410 "random.index_X"), "%s", secfile_error());
2411
2412 for (i = 0; i < 8; i++) {
2413 str = secfile_lookup_str(loading->file, "random.table%d",i);
2414 sg_failure_ret(NULL != str, "%s", secfile_error());
2415 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2416 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2417 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2418 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2419 }
2420 loading->rstate.is_init = TRUE;
2421 fc_rand_set_state(loading->rstate);
2422 } else {
2423 /* No random values - mark the setting. */
2424 (void) secfile_entry_by_path(loading->file, "random.saved");
2425
2426 /* We're loading a game without a seed (which is okay, if it's a scenario).
2427 * We need to generate the game seed now because it will be needed later
2428 * during the load. */
2430 loading->rstate = fc_rand_state();
2431 }
2432}
2433
2434/************************************************************************/
2437static void sg_save_random(struct savedata *saving)
2438{
2439 /* Check status and return if not OK (sg_success FALSE). */
2440 sg_check_ret();
2441
2442 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2443 int i;
2444 RANDOM_STATE rstate = fc_rand_state();
2445
2446 secfile_insert_bool(saving->file, TRUE, "random.saved");
2447 fc_assert(rstate.is_init);
2448
2449 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2450 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2451 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2452
2453 for (i = 0; i < 8; i++) {
2454 char vec[100];
2455
2456 fc_snprintf(vec, sizeof(vec),
2457 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2458 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2459 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2460 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2461 secfile_insert_str(saving->file, vec, "random.table%d", i);
2462 }
2463 } else {
2464 secfile_insert_bool(saving->file, FALSE, "random.saved");
2465 }
2466}
2467
2468/* =======================================================================
2469 * Load / save lua script data.
2470 * ======================================================================= */
2471
2472/************************************************************************/
2475static void sg_load_script(struct loaddata *loading)
2476{
2477 /* Check status and return if not OK (sg_success FALSE). */
2478 sg_check_ret();
2479
2481}
2482
2483/************************************************************************/
2486static void sg_save_script(struct savedata *saving)
2487{
2488 /* Check status and return if not OK (sg_success FALSE). */
2489 sg_check_ret();
2490
2492}
2493
2494/* =======================================================================
2495 * Load / save scenario data.
2496 * ======================================================================= */
2497
2498/************************************************************************/
2502{
2503 const char *buf;
2504 int game_version;
2505
2506 /* Check status and return if not OK (sg_success FALSE). */
2507 sg_check_ret();
2508
2509 /* Load version. */
2511 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2512 /* We require at least version 2.90.99 - and at that time we saved version
2513 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2514 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2515 "version 2.90.99 required.");
2516
2517 loading->full_version = game_version;
2518
2519 game.scenario.datafile[0] = '\0';
2520
2522 "scenario.is_scenario"), "%s", secfile_error());
2523 if (!game.scenario.is_scenario) {
2524 return;
2525 }
2526
2527 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2528 if (buf[0] != '\0') {
2530 }
2531
2533 "scenario.authors");
2534 if (buf[0] != '\0') {
2536 } else {
2537 game.scenario.authors[0] = '\0';
2538 }
2539
2541 "scenario.description");
2542 if (buf[0] != '\0') {
2544 } else {
2545 game.scenario_desc.description[0] = '\0';
2546 }
2548 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2550 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2553 "scenario.startpos_nations");
2556 "scenario.prevent_new_cities");
2559 "scenario.lake_flooding");
2562 "scenario.handmade");
2565 "scenario.allow_ai_type_fallback");
2566
2569 "scenario.ruleset_locked");
2570
2572 "scenario.datafile");
2573 if (buf[0] != '\0') {
2575 }
2576
2577 sg_failure_ret(loading->server_state == S_S_INITIAL
2578 || (loading->server_state == S_S_RUNNING
2579 && game.scenario.players),
2580 "Invalid scenario definition (server state '%s' and "
2581 "players are %s).",
2582 server_states_name(loading->server_state),
2583 game.scenario.players ? "saved" : "not saved");
2584}
2585
2586/************************************************************************/
2590{
2591 struct entry *mod_entry;
2592 int game_version;
2593
2594 /* Check status and return if not OK (sg_success FALSE). */
2595 sg_check_ret();
2596
2597 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2598#ifdef EMERGENCY_VERSION
2600#endif /* EMERGENCY_VERSION */
2601 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2602
2603 if (!saving->scenario || !game.scenario.is_scenario) {
2604 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2605 return;
2606 }
2607
2608 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2609
2610 /* Name is mandatory to the level that is saved even if empty. */
2611 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2613
2614 /* Authors list is saved only if it exist */
2615 if (game.scenario.authors[0] != '\0') {
2617 "scenario.authors");
2619 }
2620
2621 /* Description is saved only if it exist */
2622 if (game.scenario_desc.description[0] != '\0') {
2624 "scenario.description");
2626 }
2627
2628 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2629 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2631 "scenario.startpos_nations");
2634 "scenario.prevent_new_cities");
2635 }
2637 "scenario.lake_flooding");
2638 if (game.scenario.handmade) {
2640 "scenario.handmade");
2641 }
2644 "scenario.allow_ai_type_fallback");
2645 }
2646
2647 if (game.scenario.datafile[0] != '\0') {
2649 "scenario.datafile");
2650 }
2652 "scenario.ruleset_locked");
2653 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2655 "scenario.ruleset_caps");
2656 }
2657}
2658
2659/* =======================================================================
2660 * Load / save game settings.
2661 * ======================================================================= */
2662
2663/************************************************************************/
2667{
2668 /* Check status and return if not OK (sg_success FALSE). */
2669 sg_check_ret();
2670
2671 settings_game_load(loading->file, "settings");
2672
2673 /* Save current status of fogofwar. */
2675
2676 /* Add all compatibility settings here. */
2677}
2678
2679/************************************************************************/
2683{
2685
2686 /* Check status and return if not OK (sg_success FALSE). */
2687 sg_check_ret();
2688
2689 if (saving->scenario) {
2690 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2691 }
2692
2693 settings_game_save(saving->file, "settings");
2694 /* Restore real map generator. */
2696
2697 /* Add all compatibility settings here. */
2698}
2699
2700
2701/************************************************************************/
2705{
2706 struct city *pcity;
2707 int i, j;
2708 size_t length, length2;
2709 int *city_count;
2711 "savefile.city_counters_order_size");
2712
2713 if (0==length) {
2714
2715 return;
2716 }
2717
2718 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2719
2720 sg_failure_ret(loading->counter.order != 0,
2721 "Failed to load counter's ruleset order: %s",
2722 secfile_error());
2723 sg_failure_ret(loading->counter.size = length,
2724 "Counter vector in savegame have bad size: %s",
2725 secfile_error());
2726
2727 int corder[length];
2728
2729 for (i = 0; i < length; i++) {
2730
2731 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2733 }
2734
2735 i = 0;
2736 while (NULL != (city_count =
2738 "counters.c%d", i))) {
2739
2740 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);
2741
2742 pcity = game_city_by_number(city_count[0]);
2743
2744 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2745
2746 for (j = 0; j < length; j++) {
2747
2748 pcity->counter_values[corder[j]] = city_count[j+1];
2749 }
2750 i++;
2751 }
2752}
2753
2754/************************************************************************/
2758{
2759 /* Check status and return if not OK (sg_success FALSE). */
2760 sg_check_ret();
2761
2762 const char **countnames;;
2763 int *countvalues;
2764 int i, j, count;
2765
2767
2768 secfile_insert_int(saving->file, count,
2769 "savefile.city_counters_order_size");
2770
2771 if (0 == count) {
2772
2773 return;
2774 }
2775
2776 countnames = fc_calloc(count, sizeof(*countnames));
2777 for (j = 0; j < count; j++) {
2779 }
2780
2782 "savefile.city_counters_order_vector");
2783
2785
2786 // Saving city's counters
2787
2788 j = 0;
2789 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2790
2792
2793 city_list_iterate(_pplayer->cities, pcity) {
2794
2795 countvalues[0] = pcity->id;
2796 for (i = 0; i < count; ++i) {
2797
2798 countvalues[i+1] = pcity->counter_values[i];
2799 }
2800
2801 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2802 ++j;
2805
2807}
2808
2809/* =======================================================================
2810 * Load / save the main map.
2811 * ======================================================================= */
2812
2813/************************************************************************/
2816static void sg_load_map(struct loaddata *loading)
2817{
2818 /* Check status and return if not OK (sg_success FALSE). */
2819 sg_check_ret();
2820
2821 /* This defaults to TRUE even if map has not been generated.
2822 * We rely on that
2823 * 1) scenario maps have it explicitly right.
2824 * 2) when map is actually generated, it re-initialize this to FALSE. */
2826 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2828 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2829
2831
2832 /* Savegame may have stored random_seed for documentation purposes only,
2833 * but we want to keep it for resaving. */
2835 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2836
2837 if (S_S_INITIAL == loading->server_state
2839 /* Generator MAPGEN_SCENARIO is used;
2840 * this map was done with the map editor. */
2841
2842 /* Load tiles. */
2846
2847 /* Nothing more needed for a scenario. */
2848 secfile_entry_ignore(loading->file, "game.save_known");
2849
2850 return;
2851 }
2852
2853 if (S_S_INITIAL == loading->server_state) {
2854 /* Nothing more to do if it is not a scenario but in initial state. */
2855 return;
2856 }
2857
2864}
2865
2866/************************************************************************/
2869static void sg_save_map(struct savedata *saving)
2870{
2871 /* Check status and return if not OK (sg_success FALSE). */
2872 sg_check_ret();
2873
2874 if (map_is_empty()) {
2875 /* No map. */
2876 return;
2877 }
2878
2879 if (saving->scenario) {
2881 "map.have_huts");
2883 "map.have_resources");
2884 } else {
2885 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2886 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2887 }
2888
2889 /* For debugging purposes only.
2890 * Do not save it if it's 0 (not known);
2891 * this confuses people reading this 'document' less than
2892 * saving 0. */
2893 if (wld.map.server.seed != 0) {
2895 "map.random_seed");
2896 }
2897
2904}
2905
2906/************************************************************************/
2910{
2911 /* Check status and return if not OK (sg_success FALSE). */
2912 sg_check_ret();
2913
2914 /* Initialize the map for the current topology. 'map.xsize' and
2915 * 'map.ysize' must be set. */
2917
2918 /* Allocate map. */
2920
2921 /* get the terrain type */
2922 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2923 "map.t%04d");
2925
2926 /* Check for special tile sprites. */
2927 whole_map_iterate(&(wld.map), ptile) {
2928 const char *spec_sprite;
2929 const char *label;
2930 int nat_x, nat_y;
2931
2933 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2934 nat_x, nat_y);
2935 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2936 nat_x, nat_y);
2937 if (NULL != ptile->spec_sprite) {
2938 ptile->spec_sprite = fc_strdup(spec_sprite);
2939 }
2940 if (label != NULL) {
2941 tile_set_label(ptile, label);
2942 }
2944}
2945
2946/************************************************************************/
2950{
2951 /* Check status and return if not OK (sg_success FALSE). */
2952 sg_check_ret();
2953
2954 /* Save the terrain type. */
2955 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2956 "map.t%04d");
2957
2958 /* Save special tile sprites. */
2959 whole_map_iterate(&(wld.map), ptile) {
2960 int nat_x, nat_y;
2961
2963 if (ptile->spec_sprite) {
2964 secfile_insert_str(saving->file, ptile->spec_sprite,
2965 "map.spec_sprite_%d_%d", nat_x, nat_y);
2966 }
2967 if (ptile->label != NULL) {
2968 secfile_insert_str(saving->file, ptile->label,
2969 "map.label_%d_%d", nat_x, nat_y);
2970 }
2972}
2973
2974/************************************************************************/
2978{
2979 /* Check status and return if not OK (sg_success FALSE). */
2980 sg_check_ret();
2981
2982 /* Load extras. */
2983 halfbyte_iterate_extras(j, loading->extra.size) {
2984 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
2985 loading->extra.order + 4 * j),
2986 loading->file, "map.e%02d_%04d", j);
2988
2989 if (S_S_INITIAL != loading->server_state
2992 whole_map_iterate(&(wld.map), ptile) {
2994 if (tile_has_extra(ptile, pres)) {
2995 tile_set_resource(ptile, pres);
2996
2997 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
2998 BV_CLR(ptile->extras, extra_index(pres));
2999 }
3000 }
3003 }
3004}
3005
3006/************************************************************************/
3010{
3011 /* Check status and return if not OK (sg_success FALSE). */
3012 sg_check_ret();
3013
3014 /* Save extras. */
3016 int mod[4];
3017 int l;
3018
3019 for (l = 0; l < 4; l++) {
3020 if (4 * j + 1 > game.control.num_extra_types) {
3021 mod[l] = -1;
3022 } else {
3023 mod[l] = 4 * j + l;
3024 }
3025 }
3026 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3027 saving->file, "map.e%02d_%04d", j);
3029}
3030
3031/************************************************************************/
3036{
3037 struct nation_type *pnation;
3038 struct startpos *psp;
3039 struct tile *ptile;
3040 const char SEPARATOR = '#';
3041 const char *nation_names;
3042 int nat_x, nat_y;
3043 bool exclude;
3044 int i, startpos_count;
3045
3046 /* Check status and return if not OK (sg_success FALSE). */
3047 sg_check_ret();
3048
3050 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3051
3052 if (0 == startpos_count) {
3053 /* Nothing to do. */
3054 return;
3055 }
3056
3057 for (i = 0; i < startpos_count; i++) {
3058 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3059 || !secfile_lookup_int(loading->file, &nat_y,
3060 "map.startpos%d.y", i)) {
3061 log_sg("Warning: Undefined coordinates for startpos %d", i);
3062 continue;
3063 }
3064
3065 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3066 if (NULL == ptile) {
3067 log_error("Start position native coordinates (%d, %d) do not exist "
3068 "in this map. Skipping...", nat_x, nat_y);
3069 continue;
3070 }
3071
3072 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3073 "map.startpos%d.exclude", i);
3074
3075 psp = map_startpos_new(ptile);
3076
3078 "map.startpos%d.nations", i);
3079 if (NULL != nation_names && '\0' != nation_names[0]) {
3080 const size_t size = strlen(nation_names) + 1;
3081 char buf[size], *start, *end;
3082
3084 for (start = buf - 1; NULL != start; start = end) {
3085 start++;
3086 if ((end = strchr(start, SEPARATOR))) {
3087 *end = '\0';
3088 }
3089
3090 pnation = nation_by_rule_name(start);
3091 if (NO_NATION_SELECTED != pnation) {
3092 if (exclude) {
3093 startpos_disallow(psp, pnation);
3094 } else {
3095 startpos_allow(psp, pnation);
3096 }
3097 } else {
3098 log_verbose("Missing nation \"%s\".", start);
3099 }
3100 }
3101 }
3102 }
3103
3104 if (0 < map_startpos_count()
3105 && loading->server_state == S_S_INITIAL
3107 log_verbose("Number of starts (%d) are lower than rules.max_players "
3108 "(%d), lowering rules.max_players.",
3111 }
3112
3113 /* Re-initialize nation availability in light of start positions.
3114 * This has to be after loading [scenario] and [map].startpos and
3115 * before we seek nations for players. */
3117}
3118
3119/************************************************************************/
3123{
3124 struct tile *ptile;
3125 const char SEPARATOR = '#';
3126 int i = 0;
3127
3128 /* Check status and return if not OK (sg_success FALSE). */
3129 sg_check_ret();
3130
3132 return;
3133 }
3134
3136 "map.startpos_count");
3137
3139 int nat_x, nat_y;
3140
3141 ptile = startpos_tile(psp);
3142
3144 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3145 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3146
3148 "map.startpos%d.exclude", i);
3149 if (startpos_allows_all(psp)) {
3150 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3151 } else {
3152 const struct nation_hash *nations = startpos_raw_nations(psp);
3154
3155 nation_names[0] = '\0';
3156 nation_hash_iterate(nations, pnation) {
3157 if ('\0' == nation_names[0]) {
3159 sizeof(nation_names));
3160 } else {
3162 "%c%s", SEPARATOR, nation_rule_name(pnation));
3163 }
3166 "map.startpos%d.nations", i);
3167 }
3168 i++;
3170
3172}
3173
3174/************************************************************************/
3178{
3179 int x, y;
3180 struct tile *claimer = NULL;
3181 struct extra_type *placing = NULL;
3182
3183 /* Check status and return if not OK (sg_success FALSE). */
3184 sg_check_ret();
3185
3186 if (game.info.is_new_game) {
3187 /* No owner/source information for a new game / scenario. */
3188 return;
3189 }
3190
3191 /* Owner, ownership source, and infra turns are stored as plain numbers */
3192 for (y = 0; y < wld.map.ysize; y++) {
3193 const char *buffer1 = secfile_lookup_str(loading->file,
3194 "map.owner%04d", y);
3195 const char *buffer2 = secfile_lookup_str(loading->file,
3196 "map.source%04d", y);
3197 const char *buffer3 = secfile_lookup_str(loading->file,
3198 "map.eowner%04d", y);
3200 NULL,
3201 "map.placing%04d", y);
3203 NULL,
3204 "map.infra_turns%04d", y);
3205 const char *ptr1 = buffer1;
3206 const char *ptr2 = buffer2;
3207 const char *ptr3 = buffer3;
3208 const char *ptr_placing = buffer_placing;
3209 const char *ptr_turns = buffer_turns;
3210
3214
3215 for (x = 0; x < wld.map.xsize; x++) {
3216 char token1[TOKEN_SIZE];
3217 char token2[TOKEN_SIZE];
3218 char token3[TOKEN_SIZE];
3220 char token_turns[TOKEN_SIZE];
3221 struct player *owner = NULL;
3222 struct player *eowner = NULL;
3223 int turns;
3224 int number;
3225 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3226
3227 scanin(&ptr1, ",", token1, sizeof(token1));
3228 sg_failure_ret(token1[0] != '\0',
3229 "Map size not correct (map.owner%d).", y);
3230 if (strcmp(token1, "-") == 0) {
3231 owner = NULL;
3232 } else {
3234 "Got map owner %s in (%d, %d).", token1, x, y);
3235 owner = player_by_number(number);
3236 }
3237
3238 scanin(&ptr2, ",", token2, sizeof(token2));
3239 sg_failure_ret(token2[0] != '\0',
3240 "Map size not correct (map.source%d).", y);
3241 if (strcmp(token2, "-") == 0) {
3242 claimer = NULL;
3243 } else {
3245 "Got map source %s in (%d, %d).", token2, x, y);
3246 claimer = index_to_tile(&(wld.map), number);
3247 }
3248
3249 scanin(&ptr3, ",", token3, sizeof(token3));
3250 sg_failure_ret(token3[0] != '\0',
3251 "Map size not correct (map.eowner%d).", y);
3252 if (strcmp(token3, "-") == 0) {
3253 eowner = NULL;
3254 } else {
3256 "Got base owner %s in (%d, %d).", token3, x, y);
3257 eowner = player_by_number(number);
3258 }
3259
3260 if (ptr_placing != NULL) {
3262 sg_failure_ret(token_placing[0] != '\0',
3263 "Map size not correct (map.placing%d).", y);
3264 if (strcmp(token_placing, "-") == 0) {
3265 placing = NULL;
3266 } else {
3268 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3269 placing = extra_by_number(number);
3270 }
3271 } else {
3272 placing = NULL;
3273 }
3274
3275 if (ptr_turns != NULL) {
3276 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3277 sg_failure_ret(token_turns[0] != '\0',
3278 "Map size not correct (map.infra_turns%d).", y);
3280 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3281 turns = number;
3282 } else {
3283 turns = 1;
3284 }
3285
3287 tile_claim_bases(ptile, eowner);
3288 ptile->placing = placing;
3289 ptile->infra_turns = turns;
3290 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3291 }
3292 }
3293}
3294
3295/************************************************************************/
3299{
3300 int x, y;
3301
3302 /* Check status and return if not OK (sg_success FALSE). */
3303 sg_check_ret();
3304
3305 if (saving->scenario && !saving->save_players) {
3306 /* Nothing to do for a scenario without saved players. */
3307 return;
3308 }
3309
3310 /* Store owner and ownership source as plain numbers. */
3311 for (y = 0; y < wld.map.ysize; y++) {
3312 char line[wld.map.xsize * TOKEN_SIZE];
3313
3314 line[0] = '\0';
3315 for (x = 0; x < wld.map.xsize; x++) {
3316 char token[TOKEN_SIZE];
3317 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3318
3319 if (!saving->save_players || tile_owner(ptile) == NULL) {
3320 strcpy(token, "-");
3321 } else {
3322 fc_snprintf(token, sizeof(token), "%d",
3323 player_number(tile_owner(ptile)));
3324 }
3325 strcat(line, token);
3326 if (x + 1 < wld.map.xsize) {
3327 strcat(line, ",");
3328 }
3329 }
3330 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3331 }
3332
3333 for (y = 0; y < wld.map.ysize; y++) {
3334 char line[wld.map.xsize * TOKEN_SIZE];
3335
3336 line[0] = '\0';
3337 for (x = 0; x < wld.map.xsize; x++) {
3338 char token[TOKEN_SIZE];
3339 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3340
3341 if (ptile->claimer == NULL) {
3342 strcpy(token, "-");
3343 } else {
3344 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3345 }
3346 strcat(line, token);
3347 if (x + 1 < wld.map.xsize) {
3348 strcat(line, ",");
3349 }
3350 }
3351 secfile_insert_str(saving->file, line, "map.source%04d", y);
3352 }
3353
3354 for (y = 0; y < wld.map.ysize; y++) {
3355 char line[wld.map.xsize * TOKEN_SIZE];
3356
3357 line[0] = '\0';
3358 for (x = 0; x < wld.map.xsize; x++) {
3359 char token[TOKEN_SIZE];
3360 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3361
3362 if (!saving->save_players || extra_owner(ptile) == NULL) {
3363 strcpy(token, "-");
3364 } else {
3365 fc_snprintf(token, sizeof(token), "%d",
3366 player_number(extra_owner(ptile)));
3367 }
3368 strcat(line, token);
3369 if (x + 1 < wld.map.xsize) {
3370 strcat(line, ",");
3371 }
3372 }
3373 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3374 }
3375
3376 for (y = 0; y < wld.map.ysize; y++) {
3377 char line[wld.map.xsize * TOKEN_SIZE];
3378
3379 line[0] = '\0';
3380 for (x = 0; x < wld.map.xsize; x++) {
3381 char token[TOKEN_SIZE];
3382 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3383
3384 if (ptile->placing == NULL) {
3385 strcpy(token, "-");
3386 } else {
3387 fc_snprintf(token, sizeof(token), "%d",
3388 extra_number(ptile->placing));
3389 }
3390 strcat(line, token);
3391 if (x + 1 < wld.map.xsize) {
3392 strcat(line, ",");
3393 }
3394 }
3395 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3396 }
3397
3398 for (y = 0; y < wld.map.ysize; y++) {
3399 char line[wld.map.xsize * TOKEN_SIZE];
3400
3401 line[0] = '\0';
3402 for (x = 0; x < wld.map.xsize; x++) {
3403 char token[TOKEN_SIZE];
3404 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3405
3406 if (ptile->placing != NULL) {
3407 fc_snprintf(token, sizeof(token), "%d",
3408 ptile->infra_turns);
3409 } else {
3410 fc_snprintf(token, sizeof(token), "0");
3411 }
3412 strcat(line, token);
3413 if (x + 1 < wld.map.xsize) {
3414 strcat(line, ",");
3415 }
3416 }
3417 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3418 }
3419}
3420
3421/************************************************************************/
3425{
3426 int x, y;
3427
3428 /* Check status and return if not OK (sg_success FALSE). */
3429 sg_check_ret();
3430
3431 sg_failure_ret(loading->worked_tiles == NULL,
3432 "City worked map not loaded!");
3433
3434 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3435 sizeof(*loading->worked_tiles));
3436
3437 for (y = 0; y < wld.map.ysize; y++) {
3438 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3439 y);
3440 const char *ptr = buffer;
3441
3442 sg_failure_ret(NULL != buffer,
3443 "Savegame corrupt - map line %d not found.", y);
3444 for (x = 0; x < wld.map.xsize; x++) {
3445 char token[TOKEN_SIZE];
3446 int number;
3447 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3448
3449 scanin(&ptr, ",", token, sizeof(token));
3450 sg_failure_ret('\0' != token[0],
3451 "Savegame corrupt - map size not correct.");
3452 if (strcmp(token, "-") == 0) {
3453 number = -1;
3454 } else {
3455 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3456 "Savegame corrupt - got tile worked by city "
3457 "id=%s in (%d, %d).", token, x, y);
3458 }
3459
3460 loading->worked_tiles[ptile->index] = number;
3461 }
3462 }
3463}
3464
3465/************************************************************************/
3469{
3470 int x, y;
3471
3472 /* Check status and return if not OK (sg_success FALSE). */
3473 sg_check_ret();
3474
3475 if (saving->scenario && !saving->save_players) {
3476 /* Nothing to do for a scenario without saved players. */
3477 return;
3478 }
3479
3480 /* additionally save the tiles worked by the cities */
3481 for (y = 0; y < wld.map.ysize; y++) {
3482 char line[wld.map.xsize * TOKEN_SIZE];
3483
3484 line[0] = '\0';
3485 for (x = 0; x < wld.map.xsize; x++) {
3486 char token[TOKEN_SIZE];
3487 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3488 struct city *pcity = tile_worked(ptile);
3489
3490 if (pcity == NULL) {
3491 strcpy(token, "-");
3492 } else {
3493 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3494 }
3495 strcat(line, token);
3496 if (x < wld.map.xsize) {
3497 strcat(line, ",");
3498 }
3499 }
3500 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3501 }
3502}
3503
3504/************************************************************************/
3508{
3509 /* Check status and return if not OK (sg_success FALSE). */
3510 sg_check_ret();
3511
3512 players_iterate(pplayer) {
3513 /* Allocate player private map here; it is needed in different modules
3514 * besides this one ((i.e. sg_load_player_*()). */
3515 player_map_init(pplayer);
3517
3519 "game.save_known")) {
3520 int lines = player_slot_max_used_number() / 32 + 1;
3521 int j, p, l, i;
3522 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3523
3524 for (l = 0; l < lines; l++) {
3525 for (j = 0; j < 8; j++) {
3526 for (i = 0; i < 4; i++) {
3527 /* Only bother trying to load the map for this halfbyte if at least
3528 * one of the corresponding player slots is in use. */
3529 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3530 LOAD_MAP_CHAR(ch, ptile,
3531 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3532 |= ascii_hex2bin(ch, j),
3533 loading->file, "map.k%02d_%04d", l * 8 + j);
3534 break;
3535 }
3536 }
3537 }
3538 }
3539
3540 players_iterate(pplayer) {
3541 dbv_clr_all(&pplayer->tile_known);
3543
3544 /* HACK: we read the known data from hex into 32-bit integers, and
3545 * now we convert it to the known tile data of each player. */
3546 whole_map_iterate(&(wld.map), ptile) {
3547 players_iterate(pplayer) {
3548 p = player_index(pplayer);
3549 l = player_index(pplayer) / 32;
3550
3551 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3552 map_set_known(ptile, pplayer);
3553 }
3556
3557 FC_FREE(known);
3558 }
3559}
3560
3561/************************************************************************/
3565{
3566 /* Check status and return if not OK (sg_success FALSE). */
3567 sg_check_ret();
3568
3569 if (!saving->save_players) {
3570 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3571 return;
3572 } else {
3573 int lines = player_slot_max_used_number() / 32 + 1;
3574
3576 "game.save_known");
3578 int j, p, l, i;
3579 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3580
3581 /* HACK: we convert the data into a 32-bit integer, and then save it as
3582 * hex. */
3583
3584 whole_map_iterate(&(wld.map), ptile) {
3585 players_iterate(pplayer) {
3586 if (map_is_known(ptile, pplayer)) {
3587 p = player_index(pplayer);
3588 l = p / 32;
3589 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3590 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3591 }
3594
3595 for (l = 0; l < lines; l++) {
3596 for (j = 0; j < 8; j++) {
3597 for (i = 0; i < 4; i++) {
3598 /* Only bother saving the map for this halfbyte if at least one
3599 * of the corresponding player slots is in use */
3600 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3601 /* put 4-bit segments of the 32-bit "known" field */
3603 + tile_index(ptile)], j),
3604 saving->file, "map.k%02d_%04d", l * 8 + j);
3605 break;
3606 }
3607 }
3608 }
3609 }
3610
3611 FC_FREE(known);
3612 }
3613 }
3614}
3615
3616/* =======================================================================
3617 * Load / save player data.
3618 *
3619 * This is split into two parts as some data can only be loaded if the
3620 * number of players is known and the corresponding player slots are
3621 * defined.
3622 * ======================================================================= */
3623
3624/************************************************************************/
3628{
3629 int i, k, nplayers;
3630 const char *str;
3631 bool shuffle_loaded = TRUE;
3632
3633 /* Check status and return if not OK (sg_success FALSE). */
3634 sg_check_ret();
3635
3636 if (S_S_INITIAL == loading->server_state
3637 || game.info.is_new_game) {
3638 /* Nothing more to do. */
3639 return;
3640 }
3641
3642 /* Load destroyed wonders: */
3644 "players.destroyed_wonders");
3645 sg_failure_ret(str != NULL, "%s", secfile_error());
3646 sg_failure_ret(strlen(str) == loading->improvement.size,
3647 "Invalid length for 'players.destroyed_wonders' ("
3648 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3649 strlen(str), loading->improvement.size);
3650 for (k = 0; k < loading->improvement.size; k++) {
3651 sg_failure_ret(str[k] == '1' || str[k] == '0',
3652 "Undefined value '%c' within "
3653 "'players.destroyed_wonders'.", str[k]);
3654
3655 if (str[k] == '1') {
3656 struct impr_type *pimprove
3657 = improvement_by_rule_name(loading->improvement.order[k]);
3658
3659 if (pimprove != NULL) {
3662 }
3663 }
3664 }
3665
3666 server.identity_number
3667 = secfile_lookup_int_default(loading->file, server.identity_number,
3668 "players.identity_number_used");
3669
3670 /* First remove all defined players. */
3671 players_iterate(pplayer) {
3672 server_remove_player(pplayer);
3674
3675 /* Now, load the players from the savefile. */
3676 player_slots_iterate(pslot) {
3677 struct player *pplayer;
3678 struct rgbcolor *prgbcolor = NULL;
3679 int pslot_id = player_slot_index(pslot);
3680
3681 if (NULL == secfile_section_lookup(loading->file, "player%d",
3682 pslot_id)) {
3683 continue;
3684 }
3685
3686 /* Get player AI type. */
3687 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3688 player_slot_index(pslot));
3689 sg_failure_ret(str != NULL, "%s", secfile_error());
3690
3691 /* Get player color */
3692 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3693 pslot_id)) {
3694 if (game_was_started()) {
3695 log_sg("Game has started, yet player %d has no color defined.",
3696 pslot_id);
3697 /* This will be fixed up later */
3698 } else {
3699 log_verbose("No color defined for player %d.", pslot_id);
3700 /* Colors will be assigned on game start, or at end of savefile
3701 * loading if game has already started */
3702 }
3703 }
3704
3705 /* Create player. */
3706 pplayer = server_create_player(player_slot_index(pslot), str,
3707 prgbcolor,
3710 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3711
3712 server_player_init(pplayer, FALSE, FALSE);
3713
3714 /* Free the color definition. */
3716
3717 /* Multipliers (policies) */
3718
3719 /* First initialise player values with ruleset defaults; this will
3720 * cover any in the ruleset not known when the savefile was created. */
3721 multipliers_iterate(pmul) {
3722 pplayer->multipliers[multiplier_index(pmul)].value
3723 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3725
3726 /* Now override with any values from the savefile. */
3727 for (k = 0; k < loading->multiplier.size; k++) {
3728 const struct multiplier *pmul = loading->multiplier.order[k];
3729
3730 if (pmul) {
3732 int val =
3734 "player%d.multiplier%d.val",
3735 player_slot_index(pslot), k);
3736 int rval = (((CLIP(pmul->start, val, pmul->stop)
3737 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3738
3739 if (rval != val) {
3740 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3741 "was %d, clamped to %d", pslot_id,
3742 multiplier_rule_name(pmul), val, rval);
3743 }
3744 pplayer->multipliers[idx].value = rval;
3745
3746 val =
3748 pplayer->multipliers[idx].value,
3749 "player%d.multiplier%d.target",
3750 player_slot_index(pslot), k);
3751 rval = (((CLIP(pmul->start, val, pmul->stop)
3752 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3753
3754 if (rval != val) {
3755 log_verbose("Player %d had illegal value for multiplier_target "
3756 " \"%s\": was %d, clamped to %d", pslot_id,
3757 multiplier_rule_name(pmul), val, rval);
3758 }
3759 pplayer->multipliers[idx].target = rval;
3760
3761 pplayer->multipliers[idx].changed
3763 "player%d.multiplier%d.changed",
3764 player_slot_index(pslot), k);
3765 } /* else silently discard multiplier not in current ruleset */
3766 }
3767
3768 /* Must be loaded before tile owner is set. */
3769 pplayer->server.border_vision =
3771 "player%d.border_vision",
3772 player_slot_index(pslot));
3773
3775 "player%d.autoselect_weight",
3776 pslot_id);
3778
3779 /* check number of players */
3780 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3781 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3782 "(%d) from the loaded game does not match the number of "
3783 "players present (%d).", nplayers, player_count());
3784
3785 /* Load team information. */
3786 players_iterate(pplayer) {
3787 int team;
3788 struct team_slot *tslot = NULL;
3789
3791 "player%d.team_no",
3792 player_number(pplayer))
3794 "Invalid team definition for player %s (nb %d).",
3795 player_name(pplayer), player_number(pplayer));
3796 /* Should never fail when slot given is not NULL */
3797 team_add_player(pplayer, team_new(tslot));
3799
3800 /* Loading the shuffle list is quite complex. At the time of saving the
3801 * shuffle data is saved as
3802 * shuffled_player_<number> = player_slot_id
3803 * where number is an increasing number and player_slot_id is a number
3804 * between 0 and the maximum number of player slots. Now we have to create
3805 * a list
3806 * shuffler_players[number] = player_slot_id
3807 * where all player slot IDs are used exactly one time. The code below
3808 * handles this ... */
3809 if (secfile_lookup_int_default(loading->file, -1,
3810 "players.shuffled_player_%d", 0) >= 0) {
3811 int slots = player_slot_count();
3812 int plrcount = player_count();
3815
3816 for (i = 0; i < slots; i++) {
3817 /* Array to save used numbers. */
3819 /* List of all player IDs (needed for set_shuffled_players()). It is
3820 * initialised with the value -1 to indicate that no value is set. */
3821 shuffled_players[i] = -1;
3822 }
3823
3824 /* Load shuffled player list. */
3825 for (i = 0; i < plrcount; i++) {
3826 int shuffle
3828 "players.shuffled_player_%d", i);
3829
3830 if (shuffle == -1) {
3831 log_sg("Missing player shuffle information (index %d) "
3832 "- reshuffle player list!", i);
3834 break;
3835 } else if (shuffled_player_set[shuffle]) {
3836 log_sg("Player shuffle %d used two times "
3837 "- reshuffle player list!", shuffle);
3839 break;
3840 }
3841 /* Set this ID as used. */
3843
3844 /* Save the player ID in the shuffle list. */
3846 }
3847
3848 if (shuffle_loaded) {
3849 /* Insert missing numbers. */
3850 int shuffle_index = plrcount;
3851
3852 for (i = 0; i < slots; i++) {
3853 if (!shuffled_player_set[i]) {
3855 }
3856
3857 /* shuffle_index must not grow higher than size of shuffled_players. */
3859 "Invalid player shuffle data!");
3860 }
3861
3862#ifdef FREECIV_DEBUG
3863 log_debug("[load shuffle] player_count() = %d", player_count());
3864 player_slots_iterate(pslot) {
3865 int plrid = player_slot_index(pslot);
3866
3867 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3869 shuffled_player_set[plrid] ? "is used" : "-");
3871#endif /* FREECIV_DEBUG */
3872
3873 /* Set shuffle list from savegame. */
3875 }
3876 }
3877
3878 if (!shuffle_loaded) {
3879 /* No shuffled players included or error loading them, so shuffle them
3880 * (this may include scenarios). */
3882 }
3883}
3884
3885/************************************************************************/
3889{
3890 /* Check status and return if not OK (sg_success FALSE). */
3891 sg_check_ret();
3892
3893 if (game.info.is_new_game) {
3894 /* Nothing to do. */
3895 return;
3896 }
3897
3898 players_iterate(pplayer) {
3899 sg_load_player_main(loading, pplayer);
3901 sg_load_player_units(loading, pplayer);
3903
3904 /* Check the success of the functions above. */
3905 sg_check_ret();
3906
3907 /* Print out some information */
3908 if (is_ai(pplayer)) {
3909 log_normal(_("%s has been added as %s level AI-controlled player "
3910 "(%s)."), player_name(pplayer),
3911 ai_level_translated_name(pplayer->ai_common.skill_level),
3912 ai_name(pplayer->ai));
3913 } else {
3914 log_normal(_("%s has been added as human player."),
3915 player_name(pplayer));
3916 }
3918
3919 /* Also load the transport status of the units here. It must be a special
3920 * case as all units must be known (unit on an allied transporter). */
3921 players_iterate(pplayer) {
3922 /* Load unit transport status. */
3925
3926 /* Savegame may contain nation assignments that are incompatible with the
3927 * current nationset. Ensure they are compatible, one way or another. */
3929
3930 /* Some players may have invalid nations in the ruleset. Once all players
3931 * are loaded, pick one of the remaining nations for them. */
3932 players_iterate(pplayer) {
3933 if (pplayer->nation == NO_NATION_SELECTED) {
3936 /* TRANS: Minor error message: <Leader> ... <Poles>. */
3937 log_sg(_("%s had invalid nation; changing to %s."),
3938 player_name(pplayer), nation_plural_for_player(pplayer));
3939
3940 ai_traits_init(pplayer);
3941 }
3943
3944 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
3947 if (pplayers_allied(plr, aplayer)) {
3949 DS_ALLIANCE);
3950
3953 log_sg("Illegal alliance structure detected: "
3954 "%s alliance to %s reduced to peace treaty.",
3959 }
3960 }
3963
3964 /* Update cached city illness. This can depend on trade routes,
3965 * so can't be calculated until all players have been loaded. */
3966 if (game.info.illness_on) {
3967 cities_iterate(pcity) {
3968 pcity->server.illness
3969 = city_illness_calc(pcity, NULL, NULL,
3970 &(pcity->illness_trade), NULL);
3972 }
3973
3974 /* Update all city information. This must come after all cities are
3975 * loaded (in player_load) but before player (dumb) cities are loaded
3976 * in player_load_vision(). */
3977 players_iterate(plr) {
3978 city_list_iterate(plr->cities, pcity) {
3979 city_refresh(pcity);
3980 sanity_check_city(pcity);
3981 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
3984
3985 /* Since the cities must be placed on the map to put them on the
3986 player map we do this afterwards */
3987 players_iterate(pplayer) {
3989 /* Check the success of the function above. */
3990 sg_check_ret();
3992
3993 /* Check shared vision and tiles. */
3994 players_iterate(pplayer) {
3995 BV_CLR_ALL(pplayer->gives_shared_vision);
3996 BV_CLR_ALL(pplayer->gives_shared_tiles);
3997 BV_CLR_ALL(pplayer->server.really_gives_vision);
3999
4000 /* Set up shared vision... */
4001 players_iterate(pplayer) {
4002 int plr1 = player_index(pplayer);
4003
4005 int plr2 = player_index(pplayer2);
4006
4008 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4009 give_shared_vision(pplayer, pplayer2);
4010 }
4012 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4013 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4014 }
4017
4018 /* ...and check it */
4021 /* TODO: Is there a good reason player is not marked as
4022 * giving shared vision to themselves -> really_gives_vision()
4023 * returning FALSE when pplayer1 == pplayer2 */
4024 if (pplayer1 != pplayer2
4027 sg_regr(3000900,
4028 _("%s did not give shared vision to team member %s."),
4031 }
4033 sg_regr(3000900,
4034 _("%s did not give shared vision to team member %s."),
4037 }
4038 }
4041
4044
4045 /* All vision is ready; this calls city_thaw_workers_queue(). */
4047
4048 /* Make sure everything is consistent. */
4049 players_iterate(pplayer) {
4050 unit_list_iterate(pplayer->units, punit) {
4052 struct tile *ptile = unit_tile(punit);
4053
4054 log_sg("%s doing illegal activity in savegame!",
4056 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4060 : "missing",
4061 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4063 }
4066
4067 cities_iterate(pcity) {
4068 city_refresh(pcity);
4069 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4071
4072 /* Player colors are always needed once game has started. Pre-2.4 savegames
4073 * lack them. This cannot be in compatibility conversion layer as we need
4074 * all the player data available to be able to assign best colors. */
4075 if (game_was_started()) {
4077 }
4078}
4079
4080/************************************************************************/
4083static void sg_save_players(struct savedata *saving)
4084{
4085 /* Check status and return if not OK (sg_success FALSE). */
4086 sg_check_ret();
4087
4088 if ((saving->scenario && !saving->save_players)
4089 || !game_was_started()) {
4090 /* Nothing to do for a scenario without saved players or a game in
4091 * INITIAL state. */
4092 return;
4093 }
4094
4095 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4096
4097 /* Save destroyed wonders as bitvector. Note that improvement order
4098 * is saved in 'savefile.improvement.order'. */
4099 {
4100 char destroyed[B_LAST+1];
4101
4102 improvement_iterate(pimprove) {
4103 if (is_great_wonder(pimprove)
4104 && great_wonder_is_destroyed(pimprove)) {
4105 destroyed[improvement_index(pimprove)] = '1';
4106 } else {
4107 destroyed[improvement_index(pimprove)] = '0';
4108 }
4110 destroyed[improvement_count()] = '\0';
4112 "players.destroyed_wonders");
4113 }
4114
4115 secfile_insert_int(saving->file, server.identity_number,
4116 "players.identity_number_used");
4117
4118 /* Save player order. */
4119 {
4120 int i = 0;
4121 shuffled_players_iterate(pplayer) {
4122 secfile_insert_int(saving->file, player_number(pplayer),
4123 "players.shuffled_player_%d", i);
4124 i++;
4126 }
4127
4128 /* Sort units. */
4130
4131 /* Save players. */
4132 players_iterate(pplayer) {
4133 sg_save_player_main(saving, pplayer);
4134 sg_save_player_cities(saving, pplayer);
4135 sg_save_player_units(saving, pplayer);
4137 sg_save_player_vision(saving, pplayer);
4139}
4140
4141/************************************************************************/
4145 struct player *plr)
4146{
4147 const char **slist;
4148 int i, plrno = player_number(plr);
4149 const char *str;
4150 struct government *gov;
4151 const char *level;
4152 const char *barb_str;
4153 size_t nval;
4154 const char *kind;
4155
4156 /* Check status and return if not OK (sg_success FALSE). */
4157 sg_check_ret();
4158
4159 /* Basic player data. */
4160 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4161 sg_failure_ret(str != NULL, "%s", secfile_error());
4163 sz_strlcpy(plr->username,
4165 "player%d.username", plrno));
4167 "player%d.unassigned_user", plrno),
4168 "%s", secfile_error());
4171 "player%d.orig_username", plrno));
4174 "player%d.ranked_username",
4175 plrno));
4177 "player%d.unassigned_ranked", plrno),
4178 "%s", secfile_error());
4180 "player%d.delegation_username",
4181 plrno);
4182 /* Defaults to no delegation. */
4183 if (strlen(str)) {
4185 }
4186
4187 /* Player flags */
4188 BV_CLR_ALL(plr->flags);
4189 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4190 for (i = 0; i < nval; i++) {
4191 const char *sval = slist[i];
4193
4194 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4195
4196 BV_SET(plr->flags, fid);
4197 }
4198 free(slist);
4199
4200 /* Nation */
4201 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4203 if (plr->nation != NULL) {
4204 ai_traits_init(plr);
4205 }
4206
4207 /* Government */
4208 str = secfile_lookup_str(loading->file, "player%d.government_name",
4209 plrno);
4211 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4212 plrno, str);
4213 plr->government = gov;
4214
4215 /* Target government */
4217 "player%d.target_government_name", plrno);
4218 if (str != NULL) {
4220 } else {
4221 plr->target_government = NULL;
4222 }
4225 "player%d.revolution_finishes", plrno);
4226
4227 /* Load diplomatic data (diplstate + embassy + vision).
4228 * Shared vision is loaded in sg_load_players(). */
4230 players_iterate(pplayer) {
4231 char buf[32];
4232 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4233 i = player_index(pplayer);
4234
4235 /* Load diplomatic status */
4236 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4237
4238 ds->type =
4240 diplstate_type, "%s.current", buf);
4241 ds->max_state =
4243 diplstate_type, "%s.closest", buf);
4244
4245 /* FIXME: If either party is barbarian, we cannot enforce below check */
4246#if 0
4247 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4248 sg_regr(3020000,
4249 "Player%d: War with player %d who has never been met. "
4250 "Reverted to No Contact state.", plrno, i);
4251 ds->type = DS_NO_CONTACT;
4252 }
4253#endif
4254
4255 if (valid_dst_closest(ds) != ds->max_state) {
4256 sg_regr(3020000,
4257 "Player%d: closest diplstate to player %d less than current. "
4258 "Updated.", plrno, i);
4259 ds->max_state = ds->type;
4260 }
4261
4262 ds->first_contact_turn =
4264 "%s.first_contact_turn", buf);
4265 ds->turns_left =
4266 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4267 ds->has_reason_to_cancel =
4269 "%s.has_reason_to_cancel", buf);
4270 ds->contact_turns_left =
4272 "%s.contact_turns_left", buf);
4273
4274 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4275 buf)) {
4276 BV_SET(plr->real_embassy, i);
4277 }
4278 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4279 * must be known. */
4281
4282 /* load ai data */
4284 char buf[32];
4285
4286 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4288
4290 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4291 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4293
4295 "player%d.adv.wonder_city",
4296 plrno);
4297
4298 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4299
4300 /* Some sane defaults */
4301 plr->ai_common.fuzzy = 0;
4302 plr->ai_common.expand = 100;
4303 plr->ai_common.science_cost = 100;
4304
4305
4307 "player%d.ai.level", plrno);
4308 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4309 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4311 } else {
4313 }
4314
4316 log_sg("Player%d: Invalid AI level \"%s\". "
4317 "Changed to \"%s\".", plrno, level,
4320 }
4321
4323 "player%d.ai.barb_type", plrno);
4325
4327 log_sg("Player%d: Invalid barbarian type \"%s\". "
4328 "Changed to \"None\".", plrno, barb_str);
4330 }
4331
4332 if (is_barbarian(plr)) {
4333 server.nbarbarians++;
4334 }
4335
4336 if (is_ai(plr)) {
4338 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4339 }
4340
4341 /* Load nation style. */
4342 {
4343 struct nation_style *style;
4344
4345 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4346
4347 sg_failure_ret(str != NULL, "%s", secfile_error());
4348 style = style_by_rule_name(str);
4349 if (style == NULL) {
4350 style = style_by_number(0);
4351 log_sg("Player%d: unsupported city_style_name \"%s\". "
4352 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4353 }
4354 plr->style = style;
4355 }
4356
4358 "player%d.idle_turns", plrno),
4359 "%s", secfile_error());
4360 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4361 if (sex_by_name(kind) == SEX_MALE) {
4362 plr->is_male = TRUE;
4363 } else {
4364 plr->is_male = FALSE;
4365 }
4367 "player%d.is_alive", plrno),
4368 "%s", secfile_error());
4370 "player%d.turns_alive", plrno),
4371 "%s", secfile_error());
4373 "player%d.last_war", plrno),
4374 "%s", secfile_error());
4376 "player%d.phase_done", plrno);
4378 "player%d.gold", plrno),
4379 "%s", secfile_error());
4381 "player%d.rates.tax", plrno),
4382 "%s", secfile_error());
4384 "player%d.rates.science", plrno),
4385 "%s", secfile_error());
4387 "player%d.rates.luxury", plrno),
4388 "%s", secfile_error());
4390 "player%d.infrapts",
4391 plrno);
4392 plr->server.bulbs_last_turn =
4394 "player%d.research.bulbs_last_turn", plrno);
4395
4396 /* Traits */
4397 if (plr->nation) {
4398 for (i = 0; i < loading->trait.size; i++) {
4399 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4400
4401 if (trait_is_valid(tr)) {
4402 int val;
4403
4404 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4405 plrno, i),
4406 "%s", secfile_error());
4407 plr->ai_common.traits[tr].val = val;
4408
4410 "player%d.trait%d.mod", plrno, i),
4411 "%s", secfile_error());
4412 plr->ai_common.traits[tr].mod = val;
4413 }
4414 }
4415 }
4416
4417 /* Achievements */
4418 {
4419 int count;
4420
4421 count = secfile_lookup_int_default(loading->file, -1,
4422 "player%d.achievement_count", plrno);
4423
4424 if (count > 0) {
4425 for (i = 0; i < count; i++) {
4426 const char *name;
4427 struct achievement *pach;
4428 bool first;
4429
4431 "player%d.achievement%d.name", plrno, i);
4433
4435 "Unknown achievement \"%s\".", name);
4436
4438 "player%d.achievement%d.first",
4439 plrno, i),
4440 "achievement error: %s", secfile_error());
4441
4442 sg_failure_ret(pach->first == NULL || !first,
4443 "Multiple players listed as first to get achievement \"%s\".",
4444 name);
4445
4446 BV_SET(pach->achievers, player_index(plr));
4447
4448 if (first) {
4449 pach->first = plr;
4450 }
4451 }
4452 }
4453 }
4454
4455 /* Player score. */
4456 plr->score.happy =
4458 "score%d.happy", plrno);
4459 plr->score.content =
4461 "score%d.content", plrno);
4462 plr->score.unhappy =
4464 "score%d.unhappy", plrno);
4465 plr->score.angry =
4467 "score%d.angry", plrno);
4468
4469 /* Make sure that the score about specialists in current ruleset that
4470 * were not present at saving time are set to zero. */
4472 plr->score.specialists[sp] = 0;
4474
4475 for (i = 0; i < loading->specialist.size; i++) {
4476 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4478 "score%d.specialists%d", plrno, i);
4479 }
4480
4481 plr->score.wonders =
4483 "score%d.wonders", plrno);
4484 plr->score.techs =
4486 "score%d.techs", plrno);
4487 plr->score.techout =
4489 "score%d.techout", plrno);
4490 plr->score.landarea =
4492 "score%d.landarea", plrno);
4493 plr->score.settledarea =
4495 "score%d.settledarea", plrno);
4496 plr->score.population =
4498 "score%d.population", plrno);
4499 plr->score.cities =
4501 "score%d.cities", plrno);
4502 plr->score.units =
4504 "score%d.units", plrno);
4505 plr->score.pollution =
4507 "score%d.pollution", plrno);
4508 plr->score.literacy =
4510 "score%d.literacy", plrno);
4511 plr->score.bnp =
4513 "score%d.bnp", plrno);
4514 plr->score.mfg =
4516 "score%d.mfg", plrno);
4517 plr->score.spaceship =
4519 "score%d.spaceship", plrno);
4520 plr->score.units_built =
4522 "score%d.units_built", plrno);
4523 plr->score.units_killed =
4525 "score%d.units_killed", plrno);
4526 plr->score.units_lost =
4528 "score%d.units_lost", plrno);
4529 plr->score.units_used =
4531 "score%d.units_used", plrno);
4532 plr->score.culture =
4534 "score%d.culture", plrno);
4535 plr->score.game =
4537 "score%d.total", plrno);
4538
4539 /* Load space ship data. */
4540 {
4541 struct player_spaceship *ship = &plr->spaceship;
4542 char prefix[32];
4543 const char *st;
4544 int ei;
4545
4546 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4549 &ei,
4550 "%s.state", prefix),
4551 "%s", secfile_error());
4552 ship->state = ei;
4553
4554 if (ship->state != SSHIP_NONE) {
4555 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4556 "%s.structurals", prefix),
4557 "%s", secfile_error());
4558 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4559 "%s.components", prefix),
4560 "%s", secfile_error());
4562 "%s.modules", prefix),
4563 "%s", secfile_error());
4565 "%s.fuel", prefix),
4566 "%s", secfile_error());
4567 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4568 "%s.propulsion", prefix),
4569 "%s", secfile_error());
4570 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4571 "%s.habitation", prefix),
4572 "%s", secfile_error());
4573 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4574 "%s.life_support", prefix),
4575 "%s", secfile_error());
4576 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4577 "%s.solar_panels", prefix),
4578 "%s", secfile_error());
4579
4580 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4581 sg_failure_ret(st != NULL, "%s", secfile_error())
4582 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4583 sg_failure_ret(st[i] == '1' || st[i] == '0',
4584 "Undefined value '%c' within '%s.structure'.", st[i],
4585 prefix)
4586
4587 if (!(st[i] == '0')) {
4588 BV_SET(ship->structure, i);
4589 }
4590 }
4591 if (ship->state >= SSHIP_LAUNCHED) {
4592 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4593 "%s.launch_year", prefix),
4594 "%s", secfile_error());
4595 }
4597 }
4598 }
4599
4600 /* Load lost wonder data. */
4601 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4602 /* If not present, probably an old savegame; nothing to be done */
4603 if (str != NULL) {
4604 int k;
4605
4606 sg_failure_ret(strlen(str) == loading->improvement.size,
4607 "Invalid length for 'player%d.lost_wonders' ("
4608 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4609 plrno, strlen(str), loading->improvement.size);
4610 for (k = 0; k < loading->improvement.size; k++) {
4611 sg_failure_ret(str[k] == '1' || str[k] == '0',
4612 "Undefined value '%c' within "
4613 "'player%d.lost_wonders'.", plrno, str[k]);
4614
4615 if (str[k] == '1') {
4616 struct impr_type *pimprove =
4617 improvement_by_rule_name(loading->improvement.order[k]);
4618 if (pimprove) {
4619 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4620 }
4621 }
4622 }
4623 }
4624
4625 plr->history =
4626 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4627 plr->server.huts =
4628 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4629}
4630
4631/************************************************************************/
4635 struct player *plr)
4636{
4637 int i, k, plrno = player_number(plr);
4638 struct player_spaceship *ship = &plr->spaceship;
4639 const char *flag_names[PLRF_COUNT];
4640 int set_count;
4641
4642 /* Check status and return if not OK (sg_success FALSE). */
4643 sg_check_ret();
4644
4645 set_count = 0;
4646 for (i = 0; i < PLRF_COUNT; i++) {
4647 if (player_has_flag(plr, i)) {
4649 }
4650 }
4651
4653 "player%d.flags", plrno);
4654
4655 secfile_insert_str(saving->file, ai_name(plr->ai),
4656 "player%d.ai_type", plrno);
4658 "player%d.name", plrno);
4660 "player%d.username", plrno);
4662 "player%d.unassigned_user", plrno);
4663 if (plr->rgb != NULL) {
4664 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4665 } else {
4666 /* Colorless players are ok in pregame */
4667 if (game_was_started()) {
4668 log_sg("Game has started, yet player %d has no color defined.", plrno);
4669 }
4670 }
4672 "player%d.ranked_username", plrno);
4674 "player%d.unassigned_ranked", plrno);
4676 "player%d.orig_username", plrno);
4679 : "",
4680 "player%d.delegation_username", plrno);
4682 "player%d.nation", plrno);
4683 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4684 "player%d.team_no", plrno);
4685
4688 "player%d.government_name", plrno);
4689
4690 if (plr->target_government) {
4693 "player%d.target_government_name", plrno);
4694 }
4695
4697 "player%d.style_by_name", plrno);
4698
4700 "player%d.idle_turns", plrno);
4701 if (plr->is_male) {
4703 "player%d.kind", plrno);
4704 } else {
4706 "player%d.kind", plrno);
4707 }
4709 "player%d.is_alive", plrno);
4711 "player%d.turns_alive", plrno);
4713 "player%d.last_war", plrno);
4715 "player%d.phase_done", plrno);
4716
4717 players_iterate(pplayer) {
4718 char buf[32];
4719 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4720
4721 i = player_index(pplayer);
4722
4723 /* save diplomatic state */
4724 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4725
4726 secfile_insert_enum(saving->file, ds->type,
4727 diplstate_type, "%s.current", buf);
4728 secfile_insert_enum(saving->file, ds->max_state,
4729 diplstate_type, "%s.closest", buf);
4730 secfile_insert_int(saving->file, ds->first_contact_turn,
4731 "%s.first_contact_turn", buf);
4732 secfile_insert_int(saving->file, ds->turns_left,
4733 "%s.turns_left", buf);
4734 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4735 "%s.has_reason_to_cancel", buf);
4736 secfile_insert_int(saving->file, ds->contact_turns_left,
4737 "%s.contact_turns_left", buf);
4739 "%s.embassy", buf);
4740 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4741 "%s.gives_shared_vision", buf);
4742 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4743 "%s.gives_shared_tiles", buf);
4745
4748 /* save ai data */
4750 "player%d.ai%d.love", plrno, i);
4751 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4753
4755 "player%d.adv.wonder_city", plrno);
4756
4757 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4758
4759 /* Multipliers (policies) */
4760 i = multiplier_count();
4761
4762 for (k = 0; k < i; k++) {
4764 "player%d.multiplier%d.val", plrno, k);
4766 "player%d.multiplier%d.target", plrno, k);
4768 "player%d.multiplier%d.changed", plrno, k);
4769 }
4770
4772 "player%d.ai.level", plrno);
4774 "player%d.ai.barb_type", plrno);
4776 "player%d.gold", plrno);
4778 "player%d.rates.tax", plrno);
4780 "player%d.rates.science", plrno);
4782 "player%d.rates.luxury", plrno);
4784 "player%d.infrapts", plrno);
4786 "player%d.research.bulbs_last_turn", plrno);
4787
4788 /* Save traits */
4789 {
4790 enum trait tr;
4791 int j;
4792
4793 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4795 "player%d.trait%d.val", plrno, j);
4797 "player%d.trait%d.mod", plrno, j);
4798 }
4799 }
4800
4801 /* Save achievements */
4802 {
4803 int j = 0;
4804
4806 if (achievement_player_has(pach, plr)) {
4808 "player%d.achievement%d.name", plrno, j);
4809 if (pach->first == plr) {
4811 "player%d.achievement%d.first", plrno, j);
4812 } else {
4814 "player%d.achievement%d.first", plrno, j);
4815 }
4816
4817 j++;
4818 }
4820
4821 secfile_insert_int(saving->file, j,
4822 "player%d.achievement_count", plrno);
4823 }
4824
4826 "player%d.revolution_finishes", plrno);
4827
4828 /* Player score */
4830 "score%d.happy", plrno);
4832 "score%d.content", plrno);
4834 "score%d.unhappy", plrno);
4836 "score%d.angry", plrno);
4839 "score%d.specialists%d", plrno, sp);
4842 "score%d.wonders", plrno);
4844 "score%d.techs", plrno);
4846 "score%d.techout", plrno);
4848 "score%d.landarea", plrno);
4850 "score%d.settledarea", plrno);
4852 "score%d.population", plrno);
4854 "score%d.cities", plrno);
4856 "score%d.units", plrno);
4858 "score%d.pollution", plrno);
4860 "score%d.literacy", plrno);
4861 secfile_insert_int(saving->file, plr->score.bnp,
4862 "score%d.bnp", plrno);
4863 secfile_insert_int(saving->file, plr->score.mfg,
4864 "score%d.mfg", plrno);
4866 "score%d.spaceship", plrno);
4868 "score%d.units_built", plrno);
4870 "score%d.units_killed", plrno);
4872 "score%d.units_lost", plrno);
4874 "score%d.units_used", plrno);
4876 "score%d.culture", plrno);
4877 secfile_insert_int(saving->file, plr->score.game,
4878 "score%d.total", plrno);
4879
4880 /* Save space ship status. */
4881 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4882 plrno);
4883 if (ship->state != SSHIP_NONE) {
4884 char buf[32];
4885 char st[NUM_SS_STRUCTURALS+1];
4886 int ssi;
4887
4888 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4889
4890 secfile_insert_int(saving->file, ship->structurals,
4891 "%s.structurals", buf);
4892 secfile_insert_int(saving->file, ship->components,
4893 "%s.components", buf);
4894 secfile_insert_int(saving->file, ship->modules,
4895 "%s.modules", buf);
4896 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4897 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4898 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4899 secfile_insert_int(saving->file, ship->life_support,
4900 "%s.life_support", buf);
4901 secfile_insert_int(saving->file, ship->solar_panels,
4902 "%s.solar_panels", buf);
4903
4904 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4905 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4906 }
4907 st[ssi] = '\0';
4908 secfile_insert_str(saving->file, st, "%s.structure", buf);
4909 if (ship->state >= SSHIP_LAUNCHED) {
4910 secfile_insert_int(saving->file, ship->launch_year,
4911 "%s.launch_year", buf);
4912 }
4913 }
4914
4915 /* Save lost wonders info. */
4916 {
4917 char lost[B_LAST+1];
4918
4919 improvement_iterate(pimprove) {
4920 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
4921 lost[improvement_index(pimprove)] = '1';
4922 } else {
4923 lost[improvement_index(pimprove)] = '0';
4924 }
4926 lost[improvement_count()] = '\0';
4928 "player%d.lost_wonders", plrno);
4929 }
4930
4931 secfile_insert_int(saving->file, plr->history,
4932 "player%d.history", plrno);
4934 "player%d.hut_count", plrno);
4935
4937 "player%d.border_vision", plrno);
4938
4939 if (saving->scenario) {
4940 if (plr->autoselect_weight < 0) { /* Apply default behavior */
4941 int def = 1; /* We want users to get a player in a scenario */
4942
4944 /* This isn't usable player */
4945 def = 0;
4946 }
4947
4948 secfile_insert_int(saving->file, def,
4949 "player%d.autoselect_weight", plrno);
4950 } else {
4952 "player%d.autoselect_weight", plrno);
4953 }
4954 }
4955}
4956
4957/************************************************************************/
4961 struct player *plr)
4962{
4963 int ncities, i, plrno = player_number(plr);
4964 bool tasks_handled;
4966
4967 /* Check status and return if not OK (sg_success FALSE). */
4968 sg_check_ret();
4969
4971 "player%d.ncities", plrno),
4972 "%s", secfile_error());
4973
4974 if (!plr->is_alive && ncities > 0) {
4975 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
4976 ncities = 0;
4977 }
4978
4980 "player%d.wl_max_length",
4981 plrno);
4983 log_sg("wlist_max_length %d over MAX_LEN_WORKLIST (%d)",
4985 }
4986
4988 "player%d.routes_max_length", plrno);
4989
4990 /* Load all cities of the player. */
4991 for (i = 0; i < ncities; i++) {
4992 char buf[32];
4993 struct city *pcity;
4994
4995 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
4996
4997 /* Create a dummy city. */
4998 pcity = create_city_virtual(plr, NULL, buf);
4999 adv_city_alloc(pcity);
5000 if (!sg_load_player_city(loading, plr, pcity, buf,
5002 adv_city_free(pcity);
5003 destroy_city_virtual(pcity);
5004 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5005 }
5006
5008 idex_register_city(&wld, pcity);
5009
5010 /* Load the information about the nationality of citizens. This is done
5011 * here because the city sanity check called by citizens_update() requires
5012 * that the city is registered. */
5014
5015 /* After everything is loaded, but before vision. */
5016 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
5017
5018 /* adding the city contribution to fog-of-war */
5019 pcity->server.vision = vision_new(plr, city_tile(pcity));
5021 city_refresh_vision(pcity);
5022
5023 city_list_append(plr->cities, pcity);
5024 }
5025
5027 for (i = 0; !tasks_handled; i++) {
5028 int city_id;
5029 struct city *pcity = NULL;
5030
5031 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5032 plrno, i);
5033
5034 if (city_id != -1) {
5035 pcity = player_city_by_number(plr, city_id);
5036 }
5037
5038 if (pcity != NULL) {
5039 const char *str;
5040 int nat_x, nat_y;
5041 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5042
5043 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5044 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5045
5046 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5047
5048 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5050
5052 "Unknown workertask activity %s", str);
5053
5054 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5055
5056 if (strcmp("-", str)) {
5058
5059 sg_failure_ret(ptask->tgt != NULL,
5060 "Unknown workertask target %s", str);
5061 } else {
5062 ptask->tgt = NULL;
5063
5064 if (ptask->act == ACTIVITY_IRRIGATE) {
5066 } else if (ptask->act == ACTIVITY_MINE) {
5067 ptask->act = ACTIVITY_MINE;
5068 }
5069 }
5070
5071 ptask->want = secfile_lookup_int_default(loading->file, 1,
5072 "player%d.task%d.want", plrno, i);
5073
5075 } else {
5077 }
5078 }
5079}
5080
5081/************************************************************************/
5084static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5085 struct city *pcity, const char *citystr,
5087{
5088 struct player *past;
5089 const char *kind, *name, *str;
5090 int id, i, repair, sp_count = 0, workers = 0, value;
5091 int nat_x, nat_y;
5092 citizens size;
5093 const char *stylename;
5094 int partner;
5095 int want;
5096 int tmp_int;
5097 const struct civ_map *nmap = &(wld.map);
5098
5100 FALSE, "%s", secfile_error());
5102 FALSE, "%s", secfile_error());
5103 pcity->tile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5104 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5105 "%s has invalid center tile (%d, %d)",
5106 citystr, nat_x, nat_y);
5108 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5109
5110 /* Instead of dying, use 'citystr' string for damaged name. */
5112 "%s.name", citystr));
5113
5114 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5115 citystr), FALSE, "%s", secfile_error());
5116
5118 "%s.original", citystr);
5119 past = player_by_number(id);
5120 if (NULL != past) {
5121 pcity->original = past;
5122 }
5123
5124 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5125 citystr), FALSE, "%s", secfile_error());
5126 size = (citizens)value; /* set the correct type */
5127 sg_warn_ret_val(value == (int)size, FALSE,
5128 "Invalid city size: %d, set to %d", value, size);
5129 city_size_set(pcity, size);
5130
5131 for (i = 0; i < loading->specialist.size; i++) {
5132 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5133 citystr, i),
5134 FALSE, "%s", secfile_error());
5135 pcity->specialists[specialist_index(loading->specialist.order[i])]
5136 = (citizens)value;
5137 sp_count += value;
5138 }
5139
5140 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5141 for (i = 0; partner != 0; i++) {
5142 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5143 const char *dir;
5144 const char *good_str;
5145
5146 /* Append to routes list immediately, so the pointer can be found for freeing
5147 * even if we abort */
5149
5150 proute->partner = partner;
5151 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5153 "No traderoute direction found for %s", citystr);
5156 "Illegal route direction %s", dir);
5157 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5159 "No good found for %s", citystr);
5161 sg_warn_ret_val(proute->goods != NULL, FALSE,
5162 "Illegal good %s", good_str);
5163
5164 /* Next one */
5166 "%s.traderoute%d", citystr, i + 1);
5167 }
5168
5169 for (; i < routes_max; i++) {
5170 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5171 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5172 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5173 }
5174
5176 "%s.food_stock", citystr),
5177 FALSE, "%s", secfile_error());
5179 "%s.shield_stock", citystr),
5180 FALSE, "%s", secfile_error());
5181 pcity->history =
5182 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5183
5184 pcity->airlift =
5185 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5186 pcity->was_happy =
5187 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5188 citystr);
5189 pcity->had_famine =
5190 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5191 citystr);
5192
5193 pcity->turn_plague =
5194 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5195
5197 "%s.anarchy", citystr),
5198 FALSE, "%s", secfile_error());
5199 pcity->rapture =
5200 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5201 pcity->steal =
5202 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5203
5205 "%s.turn_founded", citystr),
5206 FALSE, "%s", secfile_error());
5208 "%s.acquire_t", citystr),
5209 FALSE, "%s", secfile_error());
5210 pcity->acquire_t = tmp_int;
5211 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5212 citystr), FALSE, "%s", secfile_error());
5213 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5214 citystr), FALSE, "%s", secfile_error());
5215
5217 "%s.turn_last_built", citystr),
5218 FALSE, "%s", secfile_error());
5219
5220 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5221 citystr);
5222 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5223 citystr);
5224 pcity->production = universal_by_rule_name(kind, name);
5226 "%s.currently_building: unknown \"%s\" \"%s\".",
5227 citystr, kind, name);
5228
5229 want = secfile_lookup_int_default(loading->file, 0,
5230 "%s.current_want", citystr);
5231 if (pcity->production.kind == VUT_IMPROVEMENT) {
5232 pcity->server.adv->
5233 building_want[improvement_index(pcity->production.value.building)]
5234 = want;
5235 }
5236
5237 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5238 citystr);
5239 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5240 citystr);
5243 "%s.changed_from: unknown \"%s\" \"%s\".",
5244 citystr, kind, name);
5245
5246 pcity->before_change_shields =
5248 "%s.before_change_shields", citystr);
5249 pcity->caravan_shields =
5251 "%s.caravan_shields", citystr);
5252 pcity->disbanded_shields =
5254 "%s.disbanded_shields", citystr);
5257 "%s.last_turns_shield_surplus",
5258 citystr);
5259
5261 "%s.style", citystr);
5262 if (stylename != NULL) {
5264 } else {
5265 pcity->style = 0;
5266 }
5267 if (pcity->style < 0) {
5268 pcity->style = city_style(pcity);
5269 }
5270
5271 pcity->server.synced = FALSE; /* Must re-sync with clients */
5272
5273 /* Initialise list of city improvements. */
5274 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5275 pcity->built[i].turn = I_NEVER;
5276 }
5277
5278 /* Load city improvements. */
5279 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5281 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5282 "Invalid length of '%s.improvements' ("
5283 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5284 citystr, strlen(str), loading->improvement.size);
5285 for (i = 0; i < loading->improvement.size; i++) {
5286 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5287 "Undefined value '%c' within '%s.improvements'.",
5288 str[i], citystr)
5289
5290 if (str[i] == '1') {
5291 struct impr_type *pimprove
5292 = improvement_by_rule_name(loading->improvement.order[i]);
5293
5294 if (pimprove) {
5295 city_add_improvement(pcity, pimprove);
5296 }
5297 }
5298 }
5299
5300 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5301 "No worked tiles map defined.");
5302
5303 city_freeze_workers(pcity);
5304
5305 /* Load new savegame with variable (squared) city radius and worked
5306 * tiles map */
5307
5308 int radius_sq
5309 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5310 citystr);
5311 city_map_radius_sq_set(pcity, radius_sq);
5312
5314 if (loading->worked_tiles[ptile->index] == pcity->id) {
5315 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5316 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5317 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5318 TILE_XY(pcity->tile), TILE_XY(ptile));
5320 sp_count++;
5321 } else {
5322 tile_set_worked(ptile, pcity);
5323 workers++;
5324 }
5325
5326#ifdef FREECIV_DEBUG
5327 /* Set this tile to unused; a check for not reset tiles is
5328 * included in game_load_internal() */
5329 loading->worked_tiles[ptile->index] = -1;
5330#endif /* FREECIV_DEBUG */
5331 }
5333
5334 if (tile_worked(city_tile(pcity)) != pcity) {
5335 struct city *pwork = tile_worked(city_tile(pcity));
5336
5337 if (NULL != pwork) {
5338 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5339 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5342
5343 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5344 pwork->specialists[DEFAULT_SPECIALIST]++;
5346 } else {
5347 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5348 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5349 city_size_get(pcity));
5350 }
5351
5352 /* Repair pcity */
5353 tile_set_worked(city_tile(pcity), pcity);
5354 city_repair_size(pcity, -1);
5355 }
5356
5357 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5358 if (0 != repair) {
5359 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5360 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5361 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5362 workers, FREE_WORKED_TILES, sp_count);
5363
5364 /* Repair pcity */
5365 city_repair_size(pcity, repair);
5366 }
5367
5368 /* worklist_init() done in create_city_virtual() */
5369 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5370
5371 /* Load city options. */
5372 BV_CLR_ALL(pcity->city_options);
5373 for (i = 0; i < loading->coptions.size; i++) {
5374 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5375 citystr, i)) {
5376 BV_SET(pcity->city_options, loading->coptions.order[i]);
5377 }
5378 }
5380 "%s.wlcb", citystr),
5381 FALSE, "%s", secfile_error());
5382 pcity->wlcb = tmp_int;
5383
5384 /* Load the city rally point. */
5385 {
5386 int len = secfile_lookup_int_default(loading->file, 0,
5387 "%s.rally_point_length", citystr);
5388 int unconverted;
5389
5390 pcity->rally_point.length = len;
5391 if (len > 0) {
5393
5394 pcity->rally_point.orders
5395 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5396 pcity->rally_point.persistent
5398 "%s.rally_point_persistent", citystr);
5399 pcity->rally_point.vigilant
5401 "%s.rally_point_vigilant", citystr);
5402
5405 "%s.rally_point_orders", citystr);
5408 "%s.rally_point_dirs", citystr);
5411 "%s.rally_point_activities", citystr);
5412
5413 for (i = 0; i < len; i++) {
5414 struct unit_order *order = &pcity->rally_point.orders[i];
5415
5416 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5417 || rally_activities[i] == '\0') {
5418 log_sg("Invalid rally point.");
5419 free(pcity->rally_point.orders);
5420 pcity->rally_point.orders = NULL;
5421 pcity->rally_point.length = 0;
5422 break;
5423 }
5424 order->order = char2order(rally_orders[i]);
5425 order->dir = char2dir(rally_dirs[i]);
5426 order->activity = char2activity(rally_activities[i]);
5427
5429 "%s.rally_point_action_vec,%d",
5430 citystr, i);
5431
5432 if (unconverted == -1) {
5433 order->action = ACTION_NONE;
5434 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5435 /* Look up what action id the unconverted number represents. */
5436 order->action = loading->action.order[unconverted];
5437 } else {
5438 if (order->order == ORDER_PERFORM_ACTION) {
5439 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5440 pcity->id);
5441 }
5442
5443 order->action = ACTION_NONE;
5444 }
5445
5446 order->target
5448 "%s.rally_point_tgt_vec,%d",
5449 citystr, i);
5450 order->sub_target
5452 "%s.rally_point_sub_tgt_vec,%d",
5453 citystr, i);
5454 }
5455 } else {
5456 pcity->rally_point.orders = NULL;
5457
5458 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5459 citystr);
5460 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5461 citystr);
5462 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5463 citystr);
5464 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5465 citystr);
5466 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5467 citystr);
5468 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5469 citystr);
5471 "%s.rally_point_tgt_vec", citystr);
5473 "%s.rally_point_sub_tgt_vec", citystr);
5474 }
5475 }
5476
5477 /* Load the city manager parameters. */
5478 {
5479 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5480 "%s.cma_enabled", citystr);
5481 if (enabled) {
5482 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5483
5484 for (i = 0; i < O_LAST; i++) {
5486 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5488 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5489 }
5490
5492 loading->file, FALSE, "%s.max_growth", citystr);
5494 loading->file, FALSE, "%s.require_happy", citystr);
5496 loading->file, FALSE, "%s.allow_disorder", citystr);
5498 loading->file, FALSE, "%s.allow_specialists", citystr);
5500 loading->file, 0, "%s.happy_factor", citystr);
5501 pcity->cm_parameter = param;
5502 } else {
5503 pcity->cm_parameter = NULL;
5504
5505 for (i = 0; i < O_LAST; i++) {
5507 "%s.cma_minimal_surplus,%d", citystr, i);
5509 "%s.cma_factor,%d", citystr, i);
5510 }
5511
5512 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5513 citystr);
5514 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5515 citystr);
5516 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5517 citystr);
5518 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5519 citystr);
5520 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5521 citystr);
5522 }
5523 }
5524
5525 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5526
5527 return TRUE;
5528}
5529
5530/************************************************************************/
5534 struct player *plr,
5535 struct city *pcity,
5536 const char *citystr)
5537{
5539 citizens size;
5540
5541 citizens_init(pcity);
5542 player_slots_iterate(pslot) {
5543 int nationality;
5544
5545 nationality = secfile_lookup_int_default(loading->file, -1,
5546 "%s.citizen%d", citystr,
5547 player_slot_index(pslot));
5548 if (nationality > 0 && !player_slot_is_used(pslot)) {
5549 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5550 city_name_get(pcity), player_slot_index(pslot));
5551 continue;
5552 }
5553
5554 if (nationality != -1 && player_slot_is_used(pslot)) {
5555 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5556 "Invalid value for citizens of player %d in %s: %d.",
5557 player_slot_index(pslot), city_name_get(pcity), nationality);
5558 citizens_nation_set(pcity, pslot, nationality);
5559 }
5561 /* Sanity check. */
5562 size = citizens_count(pcity);
5563 if (size != city_size_get(pcity)) {
5564 if (size != 0) {
5565 /* size == 0 can be result from the fact that ruleset had no
5566 * nationality enabled at saving time, so no citizens at all
5567 * were saved. But something more serious must be going on if
5568 * citizens have been saved partially - if some of them are there. */
5569 log_sg("City size and number of citizens does not match in %s "
5570 "(%d != %d)! Repairing ...", city_name_get(pcity),
5571 city_size_get(pcity), size);
5572 }
5573 citizens_update(pcity, NULL);
5574 }
5575 }
5576}
5577
5578/************************************************************************/
5582 struct player *plr)
5583{
5585 int i = 0;
5586 int plrno = player_number(plr);
5588
5589 /* Check status and return if not OK (sg_success FALSE). */
5590 sg_check_ret();
5591
5593 "player%d.ncities", plrno);
5594
5596 /* Initialise the nation list for the citizens information. */
5597 player_slots_iterate(pslot) {
5600 }
5601
5602 /* First determine length of longest worklist, rally point order, and the
5603 * nationalities we have. */
5604 city_list_iterate(plr->cities, pcity) {
5605 int routes;
5606
5607 /* Check the sanity of the city. */
5608 city_refresh(pcity);
5609 sanity_check_city(pcity);
5610
5611 if (pcity->worklist.length > wlist_max_length) {
5612 wlist_max_length = pcity->worklist.length;
5613 }
5614
5615 if (pcity->rally_point.length > rally_point_max_length) {
5616 rally_point_max_length = pcity->rally_point.length;
5617 }
5618
5619 routes = city_num_trade_routes(pcity);
5620 if (routes > routes_max) {
5621 routes_max = routes;
5622 }
5623
5625 /* Find all nations of the citizens,*/
5626 players_iterate(pplayer) {
5627 if (!nations[player_index(pplayer)]
5628 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5629 nations[player_index(pplayer)] = TRUE;
5630 }
5632 }
5634
5636 "player%d.wl_max_length", plrno);
5638 "player%d.routes_max_length", plrno);
5639
5640 city_list_iterate(plr->cities, pcity) {
5641 struct tile *pcenter = city_tile(pcity);
5642 char impr_buf[B_LAST + 1];
5643 char buf[32];
5644 int j, nat_x, nat_y;
5645
5646 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5647
5648
5650 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5651 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5652
5653 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5654
5655 if (pcity->original != NULL) {
5656 secfile_insert_int(saving->file, player_number(pcity->original),
5657 "%s.original", buf);
5658 } else {
5659 secfile_insert_int(saving->file, -1, "%s.original", buf);
5660 }
5661 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5662
5663 j = 0;
5665 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5666 buf, j++);
5668
5669 j = 0;
5671 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5672 buf, j);
5674 "%s.route_direction%d", buf, j);
5676 "%s.route_good%d", buf, j);
5677 j++;
5679
5680 /* Save dummy values to keep tabular format happy */
5681 for (; j < routes_max; j++) {
5682 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5684 "%s.route_direction%d", buf, j);
5686 "%s.route_good%d", buf, j);
5687 }
5688
5689 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5690 buf);
5691 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5692 buf);
5693 secfile_insert_int(saving->file, pcity->history, "%s.history",
5694 buf);
5695
5696 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5697 buf);
5698 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5699 buf);
5700 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5701 buf);
5702 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5703 buf);
5704
5705 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5706 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5707 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5708 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5709 buf);
5710 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5711 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5712 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5713 secfile_insert_int(saving->file, pcity->turn_last_built,
5714 "%s.turn_last_built", buf);
5715
5716 /* For visual debugging, variable length strings together here */
5717 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5718
5719 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5720 "%s.currently_building_kind", buf);
5721 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5722 "%s.currently_building_name", buf);
5723
5724 if (pcity->production.kind == VUT_IMPROVEMENT) {
5726 pcity->server.adv->
5727 building_want[improvement_index(pcity->production.value.building)],
5728 "%s.current_want", buf);
5729 } else {
5730 secfile_insert_int(saving->file, 0,
5731 "%s.current_want", buf);
5732 }
5733
5734 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5735 "%s.changed_from_kind", buf);
5736 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5737 "%s.changed_from_name", buf);
5738
5739 secfile_insert_int(saving->file, pcity->before_change_shields,
5740 "%s.before_change_shields", buf);
5741 secfile_insert_int(saving->file, pcity->caravan_shields,
5742 "%s.caravan_shields", buf);
5743 secfile_insert_int(saving->file, pcity->disbanded_shields,
5744 "%s.disbanded_shields", buf);
5745 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5746 "%s.last_turns_shield_surplus", buf);
5747
5748 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5749 "%s.style", buf);
5750
5751 /* Save the squared city radius and all tiles within the corresponding
5752 * city map. */
5753 secfile_insert_int(saving->file, pcity->city_radius_sq,
5754 "player%d.c%d.city_radius_sq", plrno, i);
5755 /* The tiles worked by the city are saved using the main map.
5756 * See also sg_save_map_worked(). */
5757
5758 /* Save improvement list as bytevector. Note that improvement order
5759 * is saved in savefile.improvement_order. */
5760 improvement_iterate(pimprove) {
5761 impr_buf[improvement_index(pimprove)]
5762 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5763 : '1';
5765 impr_buf[improvement_count()] = '\0';
5766
5768 "Invalid size of the improvement vector (%s.improvements: "
5769 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5770 strlen(impr_buf), sizeof(impr_buf));
5771 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5772
5773 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5774 buf);
5775
5776 for (j = 0; j < CITYO_LAST; j++) {
5777 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5778 "%s.option%d", buf, j);
5779 }
5780 secfile_insert_int(saving->file, pcity->wlcb,
5781 "%s.wlcb", buf);
5782
5783 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5784
5786 /* Save nationality of the citizens,*/
5787 players_iterate(pplayer) {
5788 if (nations[player_index(pplayer)]) {
5790 citizens_nation_get(pcity, pplayer->slot),
5791 "%s.citizen%d", buf, player_index(pplayer));
5792 }
5794 }
5795
5796 secfile_insert_int(saving->file, pcity->rally_point.length,
5797 "%s.rally_point_length", buf);
5798 if (pcity->rally_point.length) {
5799 int len = pcity->rally_point.length;
5800 char orders[len + 1], dirs[len + 1], activities[len + 1];
5801 int actions[len];
5802 int targets[len];
5803 int sub_targets[len];
5804
5805 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5806 "%s.rally_point_persistent", buf);
5807 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5808 "%s.rally_point_vigilant", buf);
5809
5810 for (j = 0; j < len; j++) {
5811 orders[j] = order2char(pcity->rally_point.orders[j].order);
5812 dirs[j] = '?';
5813 activities[j] = '?';
5814 targets[j] = NO_TARGET;
5815 sub_targets[j] = NO_TARGET;
5816 actions[j] = -1;
5817 switch (pcity->rally_point.orders[j].order) {
5818 case ORDER_MOVE:
5819 case ORDER_ACTION_MOVE:
5820 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5821 break;
5822 case ORDER_ACTIVITY:
5823 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5824 activities[j]
5825 = activity2char(pcity->rally_point.orders[j].activity);
5826 break;
5828 actions[j] = pcity->rally_point.orders[j].action;
5829 targets[j] = pcity->rally_point.orders[j].target;
5830 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5831 break;
5832 case ORDER_FULL_MP:
5833 case ORDER_LAST:
5834 break;
5835 }
5836
5837 if (actions[j] == ACTION_NONE) {
5838 actions[j] = -1;
5839 }
5840 }
5841 orders[len] = dirs[len] = activities[len] = '\0';
5842
5843 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5844 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5845 secfile_insert_str(saving->file, activities,
5846 "%s.rally_point_activities", buf);
5847
5849 "%s.rally_point_action_vec", buf);
5850 /* Fill in dummy values for order targets so the registry will save
5851 * the unit table in a tabular format. */
5852 for (j = len; j < rally_point_max_length; j++) {
5853 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5854 buf, j);
5855 }
5856
5857 secfile_insert_int_vec(saving->file, targets, len,
5858 "%s.rally_point_tgt_vec", buf);
5859 /* Fill in dummy values for order targets so the registry will save
5860 * the unit table in a tabular format. */
5861 for (j = len; j < rally_point_max_length; j++) {
5863 "%s.rally_point_tgt_vec,%d", buf, j);
5864 }
5865
5866 secfile_insert_int_vec(saving->file, sub_targets, len,
5867 "%s.rally_point_sub_tgt_vec", buf);
5868 /* Fill in dummy values for order targets so the registry will save
5869 * the unit table in a tabular format. */
5870 for (j = len; j < rally_point_max_length; j++) {
5871 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5872 buf, j);
5873 }
5874 } else {
5875 /* Put all the same fields into the savegame - otherwise the
5876 * registry code can't correctly use a tabular format and the
5877 * savegame will be bigger. */
5878 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5879 buf);
5880 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5881 buf);
5882 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5883 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5884 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5885 buf);
5886
5887 /* Fill in dummy values for order targets so the registry will save
5888 * the unit table in a tabular format. */
5889
5890 /* The start of a vector has no number. */
5891 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5892 buf);
5893 for (j = 1; j < rally_point_max_length; j++) {
5894 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5895 buf, j);
5896 }
5897
5898 /* The start of a vector has no number. */
5899 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5900 buf);
5901 for (j = 1; j < rally_point_max_length; j++) {
5903 "%s.rally_point_tgt_vec,%d", buf, j);
5904 }
5905
5906 /* The start of a vector has no number. */
5907 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5908 buf);
5909 for (j = 1; j < rally_point_max_length; j++) {
5910 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5911 buf, j);
5912 }
5913 }
5914
5915 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5916 "%s.cma_enabled", buf);
5917 if (pcity->cm_parameter) {
5919 pcity->cm_parameter->minimal_surplus, O_LAST,
5920 "%s.cma_minimal_surplus", buf);
5922 pcity->cm_parameter->factor, O_LAST,
5923 "%s.cma_factor", buf);
5924 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
5925 "%s.max_growth", buf);
5926 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
5927 "%s.require_happy", buf);
5928 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
5929 "%s.allow_disorder", buf);
5931 pcity->cm_parameter->allow_specialists,
5932 "%s.allow_specialists", buf);
5933 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
5934 "%s.happy_factor", buf);
5935 } else {
5936 int zeros[O_LAST];
5937
5938 memset(zeros, 0, sizeof(zeros));
5940 "%s.cma_minimal_surplus", buf);
5942 "%s.cma_factor", buf);
5943 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
5944 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
5945 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
5946 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
5947 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
5948 }
5949
5950 i++;
5952
5953 i = 0;
5954 city_list_iterate(plr->cities, pcity) {
5955 worker_task_list_iterate(pcity->task_reqs, ptask) {
5956 int nat_x, nat_y;
5957
5959 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
5960 plrno, i);
5961 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
5962 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
5964 "player%d.task%d.activity",
5965 plrno, i);
5966 if (ptask->tgt != NULL) {
5968 "player%d.task%d.target",
5969 plrno, i);
5970 } else {
5971 secfile_insert_str(saving->file, "-",
5972 "player%d.task%d.target",
5973 plrno, i);
5974 }
5975 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
5976
5977 i++;
5980}
5981
5982/************************************************************************/
5986 struct player *plr)
5987{
5988 int nunits, i, plrno = player_number(plr);
5989 size_t orders_max_length;
5990
5991 /* Check status and return if not OK (sg_success FALSE). */
5992 sg_check_ret();
5993
5995 "player%d.nunits", plrno),
5996 "%s", secfile_error());
5997 if (!plr->is_alive && nunits > 0) {
5998 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
5999 nunits = 0; /* Some old savegames may be buggy. */
6000 }
6001
6003 "player%d.orders_max_length",
6004 plrno);
6005
6006 for (i = 0; i < nunits; i++) {
6007 struct unit *punit;
6008 struct city *pcity;
6009 const char *name;
6010 char buf[32];
6011 struct unit_type *type;
6012 struct tile *ptile;
6013
6014 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6015
6016 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6018 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6019
6020 /* Create a dummy unit. */
6021 punit = unit_virtual_create(plr, NULL, type, 0);
6024 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6025 }
6026
6029
6030 if ((pcity = game_city_by_number(punit->homecity))) {
6032 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6033 log_sg("%s: bad home city %d.", buf, punit->homecity);
6035 }
6036
6037 ptile = unit_tile(punit);
6038
6039 /* allocate the unit's contribution to fog of war */
6042 /* NOTE: There used to be some map_set_known calls here. These were
6043 * unneeded since unfogging the tile when the unit sees it will
6044 * automatically reveal that tile. */
6045
6048 }
6049}
6050
6051/************************************************************************/
6055 struct player *plr, struct unit *punit,
6057 const char *unitstr)
6058{
6059 enum unit_activity activity;
6060 int nat_x, nat_y;
6061 struct extra_type *pextra = NULL;
6062 struct tile *ptile;
6063 int extra_id;
6064 int ei;
6065 const char *facing_str;
6066 int natnbr;
6067 int unconverted;
6068 const char *str;
6069
6071 unitstr), FALSE, "%s", secfile_error());
6073 FALSE, "%s", secfile_error());
6075 FALSE, "%s", secfile_error());
6076
6077 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6078 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6079 unitstr, nat_x, nat_y);
6080 unit_tile_set(punit, ptile);
6081
6084 "%s.facing", unitstr);
6085 if (facing_str[0] != 'x') {
6086 /* We don't touch punit->facing if savegame does not contain that
6087 * information. Initial orientation set by unit_virtual_create()
6088 * is as good as any. */
6089 enum direction8 facing = char2dir(facing_str[0]);
6090
6091 if (direction8_is_valid(facing)) {
6092 punit->facing = facing;
6093 } else {
6094 log_error("Illegal unit orientation '%s'", facing_str);
6095 }
6096 }
6097
6098 /* If savegame has unit nationality, it doesn't hurt to
6099 * internally set it even if nationality rules are disabled. */
6101 player_number(plr),
6102 "%s.nationality", unitstr);
6103
6105 if (punit->nationality == NULL) {
6106 punit->nationality = plr;
6107 }
6108
6110 "%s.homecity", unitstr), FALSE,
6111 "%s", secfile_error());
6113 "%s.moves", unitstr), FALSE,
6114 "%s", secfile_error());
6116 "%s.fuel", unitstr), FALSE,
6117 "%s", secfile_error());
6118
6120 "%s.activity", unitstr), FALSE,
6121 "%s", secfile_error());
6122 if (ei >= 0 && ei < loading->activities.size) {
6123 activity = unit_activity_by_name(loading->activities.order[ei],
6125 } else {
6126 log_sg("Invalid activity id for unit %d", punit->id);
6127 activity = ACTIVITY_IDLE;
6128 }
6129
6132 "%s.born", unitstr);
6135 "%s.current_form_turn", unitstr);
6136
6138 "%s.activity_tgt", unitstr);
6139
6140 if (extra_id != -2) {
6141 if (extra_id >= 0 && extra_id < loading->extra.size) {
6142 pextra = loading->extra.order[extra_id];
6143 set_unit_activity_targeted(punit, activity, pextra);
6144 } else if (activity == ACTIVITY_IRRIGATE) {
6148 punit);
6149 if (tgt != NULL) {
6151 } else {
6153 }
6154 } else if (activity == ACTIVITY_MINE) {
6156 EC_MINE,
6158 punit);
6159 if (tgt != NULL) {
6161 } else {
6163 }
6164 } else {
6165 set_unit_activity(punit, activity);
6166 }
6167 } else {
6169 } /* activity_tgt == NULL */
6170
6172 "%s.activity_count", unitstr), FALSE,
6173 "%s", secfile_error());
6174
6177 "%s.changed_from", unitstr);
6178
6180 "%s.changed_from_tgt", unitstr), FALSE,
6181 "%s", secfile_error());
6182
6183 if (extra_id >= 0 && extra_id < loading->extra.size) {
6184 punit->changed_from_target = loading->extra.order[extra_id];
6185 } else {
6187 }
6188
6191 "%s.changed_from_count", unitstr);
6192
6193 /* Special case: for a long time, we accidentally incremented
6194 * activity_count while a unit was sentried, so it could increase
6195 * without bound (bug #20641) and be saved in old savefiles.
6196 * We zero it to prevent potential trouble overflowing the range
6197 * in network packets, etc. */
6198 if (activity == ACTIVITY_SENTRY) {
6199 punit->activity_count = 0;
6200 }
6203 }
6204
6205 punit->veteran
6206 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6207 {
6208 /* Protect against change in veteran system in ruleset */
6209 const int levels = utype_veteran_levels(unit_type_get(punit));
6210
6211 if (punit->veteran >= levels) {
6212 fc_assert(levels >= 1);
6213 punit->veteran = levels - 1;
6214 }
6215 }
6218 "%s.done_moving", unitstr);
6221 "%s.battlegroup", unitstr);
6222
6224 "%s.go", unitstr)) {
6225 int gnat_x, gnat_y;
6226
6228 "%s.goto_x", unitstr), FALSE,
6229 "%s", secfile_error());
6231 "%s.goto_y", unitstr), FALSE,
6232 "%s", secfile_error());
6233
6235 } else {
6236 punit->goto_tile = NULL;
6237
6238 if (punit->activity == ACTIVITY_GOTO) {
6239 /* goto_tile should never be NULL with ACTIVITY_GOTO */
6240 sg_regr(3020200, "Unit %d on goto without goto_tile. Aborting goto.",
6241 punit->id);
6243 }
6244
6245 /* These variables are not used but needed for saving the unit table.
6246 * Load them to prevent unused variables errors. */
6247 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6248 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6249 }
6250
6251 /* Load AI data of the unit. */
6252 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6253
6256 "%s.server_side_agent",
6257 unitstr);
6258 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6259 /* Look up what server side agent the unconverted number represents. */
6260 punit->ssa_controller = loading->ssa.order[unconverted];
6261 } else {
6262 log_sg("Invalid server side agent %d for unit %d",
6263 unconverted, punit->id);
6264
6266 }
6267
6269 "%s.hp", unitstr), FALSE,
6270 "%s", secfile_error());
6271
6273 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6275 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6276 punit->moved
6277 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6280 "%s.paradropped", unitstr);
6281 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6282 if (str[0] != '\0') {
6284 }
6285
6286 /* The transport status (punit->transported_by) is loaded in
6287 * sg_player_units_transport(). */
6288
6289 /* Initialize upkeep values: these are hopefully initialized
6290 * elsewhere before use (specifically, in city_support(); but
6291 * fixme: check whether always correctly initialized?).
6292 * Below is mainly for units which don't have homecity --
6293 * otherwise these don't get initialized (and AI calculations
6294 * etc may use junk values). */
6298
6300 "%s.action_decision", unitstr),
6301 FALSE, "%s", secfile_error());
6302
6303 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6304 /* Look up what action decision want the unconverted number
6305 * represents. */
6306 punit->action_decision_want = loading->act_dec.order[unconverted];
6307 } else {
6308 log_sg("Invalid action decision want for unit %d", punit->id);
6309
6311 }
6312
6314 /* Load the tile to act against. */
6315 int adwt_x, adwt_y;
6316
6317 if (secfile_lookup_int(loading->file, &adwt_x,
6318 "%s.action_decision_tile_x", unitstr)
6320 "%s.action_decision_tile_y", unitstr)) {
6322 adwt_x, adwt_y);
6323 } else {
6326 log_sg("Bad action_decision_tile for unit %d", punit->id);
6327 }
6328 } else {
6329 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6330 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6332 }
6333
6335
6336 /* Load the unit orders */
6337 {
6338 int len = secfile_lookup_int_default(loading->file, 0,
6339 "%s.orders_length", unitstr);
6340
6341 if (len > 0) {
6342 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6343 int j;
6344
6345 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6349 "%s.orders_index", unitstr);
6352 "%s.orders_repeat", unitstr);
6355 "%s.orders_vigilant", unitstr);
6356
6359 "%s.orders_list", unitstr);
6362 "%s.dir_list", unitstr);
6365 "%s.activity_list", unitstr);
6366
6368
6369 for (j = 0; j < len; j++) {
6370 struct unit_order *order = &punit->orders.list[j];
6372 int order_sub_tgt;
6373
6374 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6375 || act_unitstr[j] == '\0') {
6376 log_sg("Invalid unit orders.");
6378 break;
6379 }
6380 order->order = char2order(orders_unitstr[j]);
6381 order->dir = char2dir(dir_unitstr[j]);
6382 order->activity = char2activity(act_unitstr[j]);
6383
6385 "%s.action_vec,%d",
6386 unitstr, j);
6387
6388 if (unconverted == -1) {
6389 order->action = ACTION_NONE;
6390 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6391 /* Look up what action id the unconverted number represents. */
6392 order->action = loading->action.order[unconverted];
6393 } else {
6394 if (order->order == ORDER_PERFORM_ACTION) {
6395 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6396 }
6397
6398 order->action = ACTION_NONE;
6399 }
6400
6401 if (order->order == ORDER_LAST
6402 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6403 || (order->order == ORDER_ACTION_MOVE
6404 && !direction8_is_valid(order->dir))
6405 || (order->order == ORDER_PERFORM_ACTION
6406 && !action_id_exists(order->action))
6407 || (order->order == ORDER_ACTIVITY
6408 && order->activity == ACTIVITY_LAST)) {
6409 /* An invalid order. Just drop the orders for this unit. */
6411 punit->orders.list = NULL;
6412 punit->orders.length = 0;
6414 punit->goto_tile = NULL;
6415 break;
6416 }
6417
6419 "%s.tgt_vec,%d",
6420 unitstr, j);
6422 "%s.sub_tgt_vec,%d",
6423 unitstr, j);
6424
6425 if (order->order == ORDER_PERFORM_ACTION) {
6426 /* Validate sub target */
6427 switch (action_id_get_sub_target_kind(order->action)) {
6428 case ASTK_BUILDING:
6429 /* Sub target is a building. */
6430 if (order_sub_tgt < 0
6431 || order_sub_tgt >= loading->improvement.size
6432 || !loading->improvement.order[order_sub_tgt]) {
6433 /* Sub target is invalid. */
6434 log_sg("Cannot find building %d for %s to %s",
6437 order->sub_target = B_LAST;
6438 } else {
6439 struct impr_type *pimprove
6440 = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
6441
6442 if (pimprove != NULL) {
6443 order->sub_target = improvement_index(pimprove);
6444 }
6445 }
6446 break;
6447 case ASTK_TECH:
6448 /* Sub target is a technology. */
6449 {
6450 bool failure = order_sub_tgt < 0
6451 || order_sub_tgt >= loading->technology.size
6452 || !loading->technology.order[order_sub_tgt];
6453 struct advance *padvance = NULL;
6454
6455 if (!failure) {
6456 padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
6457 }
6458 if (padvance == NULL) {
6459 /* Target tech is invalid. */
6460 log_sg("Cannot find tech %d for %s to steal",
6462 order->sub_target = A_NONE;
6463 } else {
6465 }
6466 }
6467 break;
6468 case ASTK_EXTRA:
6470 /* These take an extra. */
6472 break;
6473 case ASTK_NONE:
6474 /* None of these can take a sub target. */
6476 "Specified sub target for action %d unsupported.",
6477 order->action);
6478 order->sub_target = NO_TARGET;
6479 break;
6480 case ASTK_COUNT:
6482 "Bad action action %d.",
6483 order->action);
6484 order->sub_target = NO_TARGET;
6485 break;
6486 }
6487 }
6488
6489 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6490 enum unit_activity act;
6491
6493 || !loading->extra.order[order_sub_tgt]) {
6494 if (order_sub_tgt != EXTRA_NONE) {
6495 log_sg("Cannot find extra %d for %s to build",
6497 }
6498
6499 order->sub_target = EXTRA_NONE;
6500 } else {
6501 order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
6502 }
6503
6504 /* An action or an activity may require an extra target. */
6505 if (action_wants_extra) {
6506 act = action_id_get_activity(order->action);
6507 } else {
6508 act = order->activity;
6509 }
6510
6511 if (unit_activity_is_valid(act)
6513 && order->sub_target == EXTRA_NONE) {
6514 /* Missing required action extra target. */
6516 punit->orders.list = NULL;
6517 punit->orders.length = 0;
6519 punit->goto_tile = NULL;
6520 break;
6521 }
6522 } else if (order->order != ORDER_PERFORM_ACTION) {
6523 if (order_sub_tgt != -1) {
6524 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6525 order_sub_tgt, -1, order->order);
6526 }
6527 order->sub_target = NO_TARGET;
6528 }
6529 }
6530
6531 for (; j < orders_max_length; j++) {
6533 "%s.action_vec,%d", unitstr, j);
6535 "%s.tgt_vec,%d", unitstr, j);
6537 "%s.sub_tgt_vec,%d", unitstr, j);
6538 }
6539 } else {
6540 int j;
6541
6543
6544 /* Never nullify goto_tile for a unit that is in active goto. */
6545 if (punit->activity != ACTIVITY_GOTO) {
6546 punit->goto_tile = NULL;
6547 }
6548
6549 punit->orders.list = NULL;
6550 punit->orders.length = 0;
6551
6552 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6553 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6554 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6555 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6556 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6557 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6558 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6559 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6560 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6561
6562 for (j = 1; j < orders_max_length; j++) {
6564 "%s.action_vec,%d", unitstr, j);
6566 "%s.tgt_vec,%d", unitstr, j);
6568 "%s.sub_tgt_vec,%d", unitstr, j);
6569 }
6570 }
6571 }
6572
6573 return TRUE;
6574}
6575
6576/************************************************************************/
6581 struct player *plr)
6582{
6583 int nunits, i, plrno = player_number(plr);
6584
6585 /* Check status and return if not OK (sg_success FALSE). */
6586 sg_check_ret();
6587
6588 /* Recheck the number of units for the player. This is a copied from
6589 * sg_load_player_units(). */
6591 "player%d.nunits", plrno),
6592 "%s", secfile_error());
6593 if (!plr->is_alive && nunits > 0) {
6594 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6595 nunits = 0; /* Some old savegames may be buggy. */
6596 }
6597
6598 for (i = 0; i < nunits; i++) {
6599 int id_unit, id_trans;
6600 struct unit *punit, *ptrans;
6601
6603 "player%d.u%d.id",
6604 plrno, i);
6606 fc_assert_action(punit != NULL, continue);
6607
6609 "player%d.u%d.transported_by",
6610 plrno, i);
6611 if (id_trans == -1) {
6612 /* Not transported. */
6613 continue;
6614 }
6615
6617 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6618
6619 if (ptrans) {
6620#ifndef FREECIV_NDEBUG
6621 bool load_success =
6622#endif
6624
6625 fc_assert_action(load_success, continue);
6626 }
6627 }
6628}
6629
6630/************************************************************************/
6634 struct player *plr)
6635{
6636 int i = 0;
6637 int longest_order = 0;
6638 int plrno = player_number(plr);
6639
6640 /* Check status and return if not OK (sg_success FALSE). */
6641 sg_check_ret();
6642
6644 "player%d.nunits", plrno);
6645
6646 /* Find the longest unit order so different order length won't break
6647 * storing units in the tabular format. */
6649 if (punit->has_orders) {
6650 if (longest_order < punit->orders.length) {
6652 }
6653 }
6655
6657 "player%d.orders_max_length", plrno);
6658
6660 char buf[32];
6661 char dirbuf[2] = " ";
6662 int nat_x, nat_y;
6663 int last_order, j;
6664
6665 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6666 dirbuf[0] = dir2char(punit->facing);
6667 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6668
6670 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6671 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6672
6673 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6676 "%s.nationality", buf);
6677 }
6678 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6679 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6680 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6682 "%s.type_by_name", buf);
6683
6684 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6686 "%s.activity_count", buf);
6687 if (punit->activity_target == NULL) {
6688 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6689 } else {
6691 "%s.activity_tgt", buf);
6692 }
6693
6695 "%s.changed_from", buf);
6697 "%s.changed_from_count", buf);
6698 if (punit->changed_from_target == NULL) {
6699 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6700 } else {
6702 "%s.changed_from_tgt", buf);
6703 }
6704
6706 "%s.done_moving", buf);
6707 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6708 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6710 "%s.born", buf);
6712 "%s.current_form_turn", buf);
6714 "%s.battlegroup", buf);
6715
6716 if (punit->goto_tile) {
6718 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6719 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6720 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6721 } else {
6722 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6723 /* Set this values to allow saving it as table. */
6724 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6725 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6726 }
6727
6729 "%s.server_side_agent", buf);
6730
6731 /* Save AI data of the unit. */
6732 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6733
6735 "%s.ord_map", buf);
6737 "%s.ord_city", buf);
6738 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6740 "%s.paradropped", buf);
6742 ? unit_transport_get(punit)->id : -1,
6743 "%s.transported_by", buf);
6744 if (punit->carrying != NULL) {
6746 "%s.carrying", buf);
6747 } else {
6748 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6749 }
6750
6752 "%s.action_decision", buf);
6753
6754 /* Stored as tile rather than direction to make sure the target tile is
6755 * sane. */
6760 "%s.action_decision_tile_x", buf);
6762 "%s.action_decision_tile_y", buf);
6763 } else {
6764 /* Dummy values to get tabular format. */
6765 secfile_insert_int(saving->file, -1,
6766 "%s.action_decision_tile_x", buf);
6767 secfile_insert_int(saving->file, -1,
6768 "%s.action_decision_tile_y", buf);
6769 }
6770
6772 "%s.stay", buf);
6773
6774 if (punit->has_orders) {
6775 int len = punit->orders.length;
6776 char orders_buf[len + 1], dir_buf[len + 1];
6777 char act_buf[len + 1];
6778 int action_buf[len];
6779 int tgt_vec[len];
6780 int sub_tgt_vec[len];
6781
6782 last_order = len;
6783
6784 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6786 "%s.orders_index", buf);
6788 "%s.orders_repeat", buf);
6790 "%s.orders_vigilant", buf);
6791
6792 for (j = 0; j < len; j++) {
6794 dir_buf[j] = '?';
6795 act_buf[j] = '?';
6796 tgt_vec[j] = NO_TARGET;
6797 sub_tgt_vec[j] = -1;
6798 action_buf[j] = -1;
6799 switch (punit->orders.list[j].order) {
6800 case ORDER_MOVE:
6801 case ORDER_ACTION_MOVE:
6802 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6803 break;
6804 case ORDER_ACTIVITY:
6807 break;
6810 tgt_vec[j] = punit->orders.list[j].target;
6812 break;
6813 case ORDER_FULL_MP:
6814 case ORDER_LAST:
6815 break;
6816 }
6817
6818 if (action_buf[j] == ACTION_NONE) {
6819 action_buf[j] = -1;
6820 }
6821 }
6822 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6823
6824 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6825 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6826 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6827
6829 "%s.action_vec", buf);
6830 /* Fill in dummy values for order targets so the registry will save
6831 * the unit table in a tabular format. */
6832 for (j = last_order; j < longest_order; j++) {
6833 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6834 }
6835
6837 "%s.tgt_vec", buf);
6838 /* Fill in dummy values for order targets so the registry will save
6839 * the unit table in a tabular format. */
6840 for (j = last_order; j < longest_order; j++) {
6841 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6842 }
6843
6845 "%s.sub_tgt_vec", buf);
6846 /* Fill in dummy values for order targets so the registry will save
6847 * the unit table in a tabular format. */
6848 for (j = last_order; j < longest_order; j++) {
6849 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6850 }
6851 } else {
6852
6853 /* Put all the same fields into the savegame - otherwise the
6854 * registry code can't correctly use a tabular format and the
6855 * savegame will be bigger. */
6856 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6857 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6858 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6859 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6860 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6861 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6862 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6863
6864 /* Fill in dummy values for order targets so the registry will save
6865 * the unit table in a tabular format. */
6866
6867 /* The start of a vector has no number. */
6868 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6869 for (j = 1; j < longest_order; j++) {
6870 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6871 }
6872
6873 /* The start of a vector has no number. */
6874 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6875 for (j = 1; j < longest_order; j++) {
6876 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6877 }
6878
6879 /* The start of a vector has no number. */
6880 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6881 for (j = 1; j < longest_order; j++) {
6882 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6883 }
6884 }
6885
6886 i++;
6888}
6889
6890/************************************************************************/
6894 struct player *plr)
6895{
6896 int plrno = player_number(plr);
6897
6898 /* Check status and return if not OK (sg_success FALSE). */
6899 sg_check_ret();
6900
6901 /* Toss any existing attribute_block (should not exist) */
6902 if (plr->attribute_block.data) {
6904 plr->attribute_block.data = NULL;
6905 }
6906
6907 /* This is a big heap of opaque data for the client, check everything! */
6909 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6910
6911 if (0 > plr->attribute_block.length) {
6912 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6913 plr->attribute_block.length);
6914 plr->attribute_block.length = 0;
6915 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6916 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6918 plr->attribute_block.length = 0;
6919 } else if (0 < plr->attribute_block.length) {
6920 int part_nr, parts;
6921 int quoted_length;
6922 char *quoted;
6923#ifndef FREECIV_NDEBUG
6924 size_t actual_length;
6925#endif
6926
6929 "player%d.attribute_v2_block_length_quoted",
6930 plrno), "%s", secfile_error());
6933 "player%d.attribute_v2_block_parts", plrno),
6934 "%s", secfile_error());
6935
6937 quoted[0] = '\0';
6939 for (part_nr = 0; part_nr < parts; part_nr++) {
6940 const char *current =
6942 "player%d.attribute_v2_block_data.part%d",
6943 plrno, part_nr);
6944 if (!current) {
6945 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6946 break;
6947 }
6948 log_debug("attribute_v2_block_length_quoted=%d"
6949 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
6950 quoted_length, strlen(quoted), strlen(current));
6951 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6952 strcat(quoted, current);
6953 }
6955 "attribute_v2_block_length_quoted=%d"
6956 " actual=" SIZE_T_PRINTF,
6958
6959#ifndef FREECIV_NDEBUG
6961#endif
6963 plr->attribute_block.data,
6964 plr->attribute_block.length);
6966 free(quoted);
6967 }
6968}
6969
6970/************************************************************************/
6974 struct player *plr)
6975{
6976 int plrno = player_number(plr);
6977
6978 /* Check status and return if not OK (sg_success FALSE). */
6979 sg_check_ret();
6980
6981 /* This is a big heap of opaque data from the client. Although the binary
6982 * format is not user editable, keep the lines short enough for debugging,
6983 * and hope that data compression will keep the file a reasonable size.
6984 * Note that the "quoted" format is a multiple of 3.
6985 */
6986#define PART_SIZE (3*256)
6987#define PART_ADJUST (3)
6988 if (plr->attribute_block.data) {
6989 char part[PART_SIZE + PART_ADJUST];
6990 int parts;
6991 int current_part_nr;
6993 plr->attribute_block.length);
6994 char *quoted_at = strchr(quoted, ':');
6995 size_t bytes_left = strlen(quoted);
6996 size_t bytes_at_colon = 1 + (quoted_at - quoted);
6998
7000 "player%d.attribute_v2_block_length", plrno);
7002 "player%d.attribute_v2_block_length_quoted", plrno);
7003
7004 /* Try to wring some compression efficiencies out of the "quoted" format.
7005 * The first line has a variable length decimal, mis-aligning triples.
7006 */
7007 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7008 /* first line can be longer */
7009 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7010 } else {
7011 parts = 1;
7012 }
7013
7015 "player%d.attribute_v2_block_parts", plrno);
7016
7017 if (parts > 1) {
7019
7020 /* first line can be longer */
7022 part[size_of_current_part] = '\0';
7024 "player%d.attribute_v2_block_data.part%d",
7025 plrno, 0);
7028 current_part_nr = 1;
7029 } else {
7030 quoted_at = quoted;
7031 current_part_nr = 0;
7032 }
7033
7036
7038 part[size_of_current_part] = '\0';
7040 "player%d.attribute_v2_block_data.part%d",
7041 plrno,
7045 }
7046 fc_assert(bytes_left == 0);
7047 free(quoted);
7048 }
7049#undef PART_ADJUST
7050#undef PART_SIZE
7051}
7052
7053/************************************************************************/
7057 struct player *plr)
7058{
7059 int plrno = player_number(plr);
7060 int total_ncities
7062 "player%d.dc_total", plrno);
7063 int i;
7064 bool someone_alive = FALSE;
7065
7066 /* Check status and return if not OK (sg_success FALSE). */
7067 sg_check_ret();
7068
7071 if (pteam_member->is_alive) {
7073 break;
7074 }
7076
7077 if (!someone_alive) {
7078 /* Reveal all for completely dead teams. */
7080 }
7081 }
7082
7083 if (-1 == total_ncities
7084 || !game.info.fogofwar
7086 "game.save_private_map")) {
7087 /* We have:
7088 * - a dead player;
7089 * - fogged cities are not saved for any reason;
7090 * - a savegame with fog of war turned off;
7091 * - or game.save_private_map is not set to FALSE in the scenario /
7092 * savegame. The players private knowledge is set to be what they could
7093 * see without fog of war. */
7094 whole_map_iterate(&(wld.map), ptile) {
7095 if (map_is_known(ptile, plr)) {
7096 struct city *pcity = tile_city(ptile);
7097
7098 update_player_tile_last_seen(plr, ptile);
7099 update_player_tile_knowledge(plr, ptile);
7100
7101 if (NULL != pcity) {
7102 update_dumb_city(plr, pcity);
7103 }
7104 }
7106
7107 /* Nothing more to do; */
7108 return;
7109 }
7110
7111 /* Load player map (terrain). */
7112 LOAD_MAP_CHAR(ch, ptile,
7113 map_get_player_tile(ptile, plr)->terrain
7114 = char2terrain(ch), loading->file,
7115 "player%d.map_t%04d", plrno);
7116
7117 /* Load player map (extras). */
7118 halfbyte_iterate_extras(j, loading->extra.size) {
7119 LOAD_MAP_CHAR(ch, ptile,
7121 ch, loading->extra.order + 4 * j),
7122 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7124
7125 whole_map_iterate(&(wld.map), ptile) {
7126 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7127 bool regr_warn = FALSE;
7128
7130 int pres_id = extra_number(pres);
7131
7132 if (BV_ISSET(plrtile->extras, pres_id)) {
7133 if (plrtile->terrain == NULL) {
7134 if (!regr_warn) {
7135 log_sgfix("FoW tile (%d, %d) has extras, though it's on unknown.",
7136 TILE_XY(ptile));
7137 regr_warn = TRUE;
7138 }
7139 BV_CLR(plrtile->extras, pres_id);
7140 } else {
7141 plrtile->resource = pres;
7142 if (!terrain_has_resource(plrtile->terrain, pres)) {
7143 BV_CLR(plrtile->extras, pres_id);
7144 }
7145 }
7146 }
7149
7151 /* Load player map (border). */
7152 int x, y;
7153
7154 for (y = 0; y < wld.map.ysize; y++) {
7155 const char *buffer
7156 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7157 plrno, y);
7158 const char *buffer2
7159 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7160 plrno, y);
7161 const char *ptr = buffer;
7162 const char *ptr2 = buffer2;
7163
7164 sg_failure_ret(NULL != buffer,
7165 "Savegame corrupt - map line %d not found.", y);
7166 for (x = 0; x < wld.map.xsize; x++) {
7167 char token[TOKEN_SIZE];
7168 char token2[TOKEN_SIZE];
7169 int number;
7170 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7171
7172 scanin(&ptr, ",", token, sizeof(token));
7173 sg_failure_ret('\0' != token[0],
7174 "Savegame corrupt - map size not correct.");
7175 if (strcmp(token, "-") == 0) {
7176 map_get_player_tile(ptile, plr)->owner = NULL;
7177 } else {
7178 sg_failure_ret(str_to_int(token, &number),
7179 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7180 token, x, y);
7181 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7182 }
7183
7184 scanin(&ptr2, ",", token2, sizeof(token2));
7185 sg_failure_ret('\0' != token2[0],
7186 "Savegame corrupt - map size not correct.");
7187 if (strcmp(token2, "-") == 0) {
7188 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7189 } else {
7191 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7192 token, x, y);
7193 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7194 }
7195 }
7196 }
7197 }
7198
7199 /* Load player map (update time). */
7200 for (i = 0; i < 4; i++) {
7201 /* put 4-bit segments of 16-bit "updated" field */
7202 if (i == 0) {
7203 LOAD_MAP_CHAR(ch, ptile,
7204 map_get_player_tile(ptile, plr)->last_updated
7205 = ascii_hex2bin(ch, i),
7206 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7207 } else {
7208 LOAD_MAP_CHAR(ch, ptile,
7209 map_get_player_tile(ptile, plr)->last_updated
7210 |= ascii_hex2bin(ch, i),
7211 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7212 }
7213 }
7214
7215 /* Load player map known cities. */
7216 for (i = 0; i < total_ncities; i++) {
7217 struct vision_site *pdcity;
7218 char buf[32];
7219 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7220
7224 pdcity);
7226 } else {
7227 /* Error loading the data. */
7228 log_sg("Skipping seen city %d for player %d.", i, plrno);
7229 if (pdcity != NULL) {
7231 }
7232 }
7233 }
7234
7235 /* Repair inconsistent player maps. */
7236 whole_map_iterate(&(wld.map), ptile) {
7237 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7238 struct city *pcity = tile_city(ptile);
7239
7240 update_player_tile_knowledge(plr, ptile);
7241 reality_check_city(plr, ptile);
7242
7243 if (NULL != pcity) {
7244 update_dumb_city(plr, pcity);
7245 }
7246 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7247 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7248 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7249
7250 plrtile->owner = tile_owner(ptile);
7251 }
7253}
7254
7255/************************************************************************/
7259 struct player *plr,
7260 struct vision_site *pdcity,
7261 const char *citystr)
7262{
7263 const char *str;
7264 int i, id, size;
7265 citizens city_size;
7266 int nat_x, nat_y;
7267 const char *stylename;
7268 enum capital_type cap;
7269 const char *vname;
7270
7272 citystr),
7273 FALSE, "%s", secfile_error());
7275 citystr),
7276 FALSE, "%s", secfile_error());
7277 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7278 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7279 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7280
7281 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7282 citystr),
7283 FALSE, "%s", secfile_error());
7284 pdcity->owner = player_by_number(id);
7285 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7286 "%s has invalid owner (%d); skipping.", citystr, id);
7287
7289 "%s.id", citystr),
7290 FALSE, "%s", secfile_error());
7292 "%s has invalid id (%d); skipping.", citystr, id);
7293
7295 "%s.size", citystr),
7296 FALSE, "%s", secfile_error());
7297 city_size = (citizens)size; /* set the correct type */
7298 sg_warn_ret_val(size == (int)city_size, FALSE,
7299 "Invalid city size: %d; set to %d.", size, city_size);
7300 vision_site_size_set(pdcity, city_size);
7301
7302 /* Initialise list of improvements */
7303 BV_CLR_ALL(pdcity->improvements);
7304 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7306 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7307 "Invalid length of '%s.improvements' ("
7308 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7309 citystr, strlen(str), loading->improvement.size);
7310 for (i = 0; i < loading->improvement.size; i++) {
7311 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7312 "Undefined value '%c' within '%s.improvements'.",
7313 str[i], citystr)
7314
7315 if (str[i] == '1') {
7316 struct impr_type *pimprove =
7317 improvement_by_rule_name(loading->improvement.order[i]);
7318 if (pimprove) {
7319 BV_SET(pdcity->improvements, improvement_index(pimprove));
7320 }
7321 }
7322 }
7323
7325 "%s.name", citystr);
7326
7327 if (vname != NULL) {
7328 pdcity->name = fc_strdup(vname);
7329 }
7330
7332 "%s.occupied", citystr);
7334 "%s.walls", citystr);
7336 "%s.happy", citystr);
7338 "%s.unhappy", citystr);
7340 "%s.style", citystr);
7341 if (stylename != NULL) {
7343 } else {
7344 pdcity->style = 0;
7345 }
7346 if (pdcity->style < 0) {
7347 pdcity->style = 0;
7348 }
7349
7350 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7351 "%s.city_image", citystr);
7352
7354 "%s.capital", citystr),
7356
7358 pdcity->capital = cap;
7359 } else {
7360 pdcity->capital = CAPITAL_NOT;
7361 }
7362
7363 return TRUE;
7364}
7365
7366/************************************************************************/
7370 struct player *plr)
7371{
7372 int i, plrno = player_number(plr);
7373
7374 /* Check status and return if not OK (sg_success FALSE). */
7375 sg_check_ret();
7376
7378 /* The player can see all, there's no reason to save the private map. */
7379 return;
7380 }
7381
7382 /* Save the map (terrain). */
7383 SAVE_MAP_CHAR(ptile,
7385 saving->file, "player%d.map_t%04d", plrno);
7386
7388 /* Save the map (borders). */
7389 int x, y;
7390
7391 for (y = 0; y < wld.map.ysize; y++) {
7392 char line[wld.map.xsize * TOKEN_SIZE];
7393
7394 line[0] = '\0';
7395 for (x = 0; x < wld.map.xsize; x++) {
7396 char token[TOKEN_SIZE];
7397 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7398 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7399
7400 if (plrtile == NULL || plrtile->owner == NULL) {
7401 strcpy(token, "-");
7402 } else {
7403 fc_snprintf(token, sizeof(token), "%d",
7404 player_number(plrtile->owner));
7405 }
7406 strcat(line, token);
7407 if (x < wld.map.xsize) {
7408 strcat(line, ",");
7409 }
7410 }
7411 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7412 plrno, y);
7413 }
7414
7415 for (y = 0; y < wld.map.ysize; y++) {
7416 char line[wld.map.xsize * TOKEN_SIZE];
7417
7418 line[0] = '\0';
7419 for (x = 0; x < wld.map.xsize; x++) {
7420 char token[TOKEN_SIZE];
7421 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7422 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7423
7424 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7425 strcpy(token, "-");
7426 } else {
7427 fc_snprintf(token, sizeof(token), "%d",
7428 player_number(plrtile->extras_owner));
7429 }
7430 strcat(line, token);
7431 if (x < wld.map.xsize) {
7432 strcat(line, ",");
7433 }
7434 }
7435 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7436 plrno, y);
7437 }
7438 }
7439
7440 /* Save the map (extras). */
7442 int mod[4];
7443 int l;
7444
7445 for (l = 0; l < 4; l++) {
7446 if (4 * j + 1 > game.control.num_extra_types) {
7447 mod[l] = -1;
7448 } else {
7449 mod[l] = 4 * j + l;
7450 }
7451 }
7452
7453 SAVE_MAP_CHAR(ptile,
7455 map_get_player_tile(ptile, plr)->resource,
7456 mod),
7457 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7459
7460 /* Save the map (update time). */
7461 for (i = 0; i < 4; i++) {
7462 /* put 4-bit segments of 16-bit "updated" field */
7463 SAVE_MAP_CHAR(ptile,
7465 map_get_player_tile(ptile, plr)->last_updated, i),
7466 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7467 }
7468
7469 /* Save known cities. */
7470 i = 0;
7471 whole_map_iterate(&(wld.map), ptile) {
7472 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7473 char impr_buf[B_LAST + 1];
7474 char buf[32];
7475
7476 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7477
7478 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7479 int nat_x, nat_y;
7480
7482 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7483 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7484
7485 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7487 "%s.owner", buf);
7488
7490 "%s.size", buf);
7491 secfile_insert_bool(saving->file, pdcity->occupied,
7492 "%s.occupied", buf);
7493 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7494 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7495 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7497 "%s.style", buf);
7498 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7500 "%s.capital", buf);
7501
7502 /* Save improvement list as bitvector. Note that improvement order
7503 * is saved in savefile.improvement.order. */
7504 improvement_iterate(pimprove) {
7505 impr_buf[improvement_index(pimprove)]
7506 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7507 ? '1' : '0';
7509 impr_buf[improvement_count()] = '\0';
7511 "Invalid size of the improvement vector (%s.improvements: "
7512 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7513 buf, strlen(impr_buf), sizeof(impr_buf));
7514 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7515 if (pdcity->name != NULL) {
7516 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7517 }
7518
7519 i++;
7520 }
7522
7523 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7524}
7525
7526/* =======================================================================
7527 * Load / save the researches.
7528 * ======================================================================= */
7529
7530/************************************************************************/
7534{
7535 struct research *presearch;
7536 int count;
7537 int number;
7538 const char *str;
7539 int i, j;
7540 int *vlist_research;
7541
7543 /* Check status and return if not OK (sg_success FALSE). */
7544 sg_check_ret();
7545
7546 /* Initialize all researches. */
7550
7551 /* May be unsaved (e.g. scenario case). */
7552 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7553 for (i = 0; i < count; i++) {
7555 "research.r%d.number", i),
7556 "%s", secfile_error());
7557 presearch = research_by_number(number);
7559 "Invalid research number %d in 'research.r%d.number'",
7560 number, i);
7561
7562 presearch->tech_goal = technology_load(loading->file,
7563 "research.r%d.goal", i);
7565 &presearch->techs_researched,
7566 "research.r%d.techs", i),
7567 "%s", secfile_error());
7569 &presearch->future_tech,
7570 "research.r%d.futuretech", i),
7571 "%s", secfile_error());
7573 &presearch->bulbs_researched,
7574 "research.r%d.bulbs", i),
7575 "%s", secfile_error());
7577 &presearch->bulbs_researching_saved,
7578 "research.r%d.bulbs_before", i),
7579 "%s", secfile_error());
7580 presearch->researching_saved = technology_load(loading->file,
7581 "research.r%d.saved", i);
7582 presearch->researching = technology_load(loading->file,
7583 "research.r%d.now", i);
7585 &presearch->free_bulbs,
7586 "research.r%d.free_bulbs", i),
7587 "%s", secfile_error());
7588
7589 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7590 sg_failure_ret(str != NULL, "%s", secfile_error());
7591 sg_failure_ret(strlen(str) == loading->technology.size,
7592 "Invalid length of 'research.r%d.done' ("
7593 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7594 i, strlen(str), loading->technology.size);
7595 for (j = 0; j < loading->technology.size; j++) {
7596 sg_failure_ret(str[j] == '1' || str[j] == '0',
7597 "Undefined value '%c' within 'research.r%d.done'.",
7598 str[j], i);
7599
7600 if (str[j] == '1') {
7601 struct advance *padvance
7602 = advance_by_rule_name(loading->technology.order[j]);
7603
7604 if (padvance) {
7606 TECH_KNOWN);
7607 }
7608 }
7609 }
7610
7612 size_t count_res;
7613 int tn;
7614
7616 "research.r%d.vbs", i);
7617
7618 for (tn = 0; tn < count_res; tn++) {
7619 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7620
7621 if (padvance != NULL) {
7622 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7623 = vlist_research[tn];
7624 }
7625 }
7626 }
7627 }
7628
7629 /* In case of tech_leakage, we can update research only after all the
7630 * researches have been loaded */
7634}
7635
7636/************************************************************************/
7640{
7641 char invs[A_LAST];
7642 int i = 0;
7643 int *vlist_research;
7644
7646 /* Check status and return if not OK (sg_success FALSE). */
7647 sg_check_ret();
7648
7649 if (saving->save_players) {
7652 "research.r%d.number", i);
7653 technology_save(saving->file, "research.r%d.goal",
7654 i, presearch->tech_goal);
7655 secfile_insert_int(saving->file, presearch->techs_researched,
7656 "research.r%d.techs", i);
7657 secfile_insert_int(saving->file, presearch->future_tech,
7658 "research.r%d.futuretech", i);
7659 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7660 "research.r%d.bulbs_before", i);
7664 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7668 "research.r%d.vbs", i);
7669 if (vlist_research) {
7671 }
7672 }
7673 technology_save(saving->file, "research.r%d.saved",
7674 i, presearch->researching_saved);
7675 secfile_insert_int(saving->file, presearch->bulbs_researched,
7676 "research.r%d.bulbs", i);
7677 technology_save(saving->file, "research.r%d.now",
7678 i, presearch->researching);
7679 secfile_insert_int(saving->file, presearch->free_bulbs,
7680 "research.r%d.free_bulbs", i);
7681 /* Save technology lists as bytevector. Note that technology order is
7682 * saved in savefile.technology.order */
7683 advance_index_iterate(A_NONE, tech_id) {
7684 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7686 == TECH_KNOWN ? '1' : '0');
7689 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7690 i++;
7692 secfile_insert_int(saving->file, i, "research.count");
7693 }
7694}
7695
7696/* =======================================================================
7697 * Load / save the event cache. Should be the last thing to do.
7698 * ======================================================================= */
7699
7700/************************************************************************/
7704{
7705 /* Check status and return if not OK (sg_success FALSE). */
7706 sg_check_ret();
7707
7708 event_cache_load(loading->file, "event_cache");
7709}
7710
7711/************************************************************************/
7715{
7716 /* Check status and return if not OK (sg_success FALSE). */
7717 sg_check_ret();
7718
7719 if (saving->scenario) {
7720 /* Do _not_ save events in a scenario. */
7721 return;
7722 }
7723
7724 event_cache_save(saving->file, "event_cache");
7725}
7726
7727/* =======================================================================
7728 * Load / save the open treaties
7729 * ======================================================================= */
7730
7731/************************************************************************/
7735{
7736 int tidx;
7737 const char *plr0;
7738
7739 /* Check status and return if not OK (sg_success FALSE). */
7740 sg_check_ret();
7741
7742 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7743 "treaty%d.plr0", tidx)) != NULL ;
7744 tidx++) {
7745 const char *plr1;
7746 const char *ct;
7747 int cidx;
7748 struct player *p0, *p1;
7749
7750 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7751
7752 p0 = player_by_name(plr0);
7753 p1 = player_by_name(plr1);
7754
7755 if (p0 == NULL || p1 == NULL) {
7756 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7757 } else {
7758 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7759
7762
7763 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7764 "treaty%d.clause%d.type",
7765 tidx, cidx)) != NULL ;
7766 cidx++ ) {
7768 const char *plrx;
7769
7770 if (!clause_type_is_valid(type)) {
7771 log_error("Invalid clause type \"%s\"", ct);
7772 } else {
7773 struct player *pgiver = NULL;
7774
7775 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7776 tidx, cidx);
7777
7778 if (!fc_strcasecmp(plrx, plr0)) {
7779 pgiver = p0;
7780 } else if (!fc_strcasecmp(plrx, plr1)) {
7781 pgiver = p1;
7782 } else {
7783 log_error("Clause giver %s is not participant of the treaty"
7784 "between %s and %s", plrx, plr0, plr1);
7785 }
7786
7787 if (pgiver != NULL) {
7788 int value;
7789
7790 value = secfile_lookup_int_default(loading->file, 0,
7791 "treaty%d.clause%d.value",
7792 tidx, cidx);
7793
7794 add_clause(ptreaty, pgiver, type, value, NULL);
7795 }
7796 }
7797 }
7798
7799 /* These must be after clauses have been added so that acceptance
7800 * does not get cleared by what seems like changes to the treaty. */
7802 "treaty%d.accept0", tidx);
7804 "treaty%d.accept1", tidx);
7805 }
7806 }
7807}
7808
7809typedef struct {
7810 int tidx;
7813
7814/************************************************************************/
7817static void treaty_save(struct Treaty *ptr, void *data_in)
7818{
7819 char tpath[512];
7820 int cidx = 0;
7822
7823 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7824
7825 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7826 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7827 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7828 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7829
7831 char cpath[512];
7832
7833 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7834
7835 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7836 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7837 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7839}
7840
7841/************************************************************************/
7845{
7846 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7847
7849}
7850
7851/* =======================================================================
7852 * Load / save the history report
7853 * ======================================================================= */
7854
7855/************************************************************************/
7859{
7861 int turn;
7862
7863 /* Check status and return if not OK (sg_success FALSE). */
7864 sg_check_ret();
7865
7866 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7867
7868 if (turn != -2) {
7869 hist->turn = turn;
7870 }
7871
7872 if (turn + 1 >= game.info.turn) {
7873 const char *str;
7874
7875 str = secfile_lookup_str(loading->file, "history.title");
7876 sg_failure_ret(str != NULL, "%s", secfile_error());
7877 sz_strlcpy(hist->title, str);
7878 str = secfile_lookup_str(loading->file, "history.body");
7879 sg_failure_ret(str != NULL, "%s", secfile_error());
7880 sz_strlcpy(hist->body, str);
7881 }
7882}
7883
7884/************************************************************************/
7887static void sg_save_history(struct savedata *saving)
7888{
7890
7891 secfile_insert_int(saving->file, hist->turn, "history.turn");
7892
7893 if (hist->turn + 1 >= game.info.turn) {
7894 secfile_insert_str(saving->file, hist->title, "history.title");
7895 secfile_insert_str(saving->file, hist->body, "history.body");
7896 }
7897}
7898
7899/* =======================================================================
7900 * Load / save the mapimg definitions.
7901 * ======================================================================= */
7902
7903/************************************************************************/
7906static void sg_load_mapimg(struct loaddata *loading)
7907{
7908 int mapdef_count, i;
7909
7910 /* Check status and return if not OK (sg_success FALSE). */
7911 sg_check_ret();
7912
7913 /* Clear all defined map images. */
7914 while (mapimg_count() > 0) {
7915 mapimg_delete(0);
7916 }
7917
7919 "mapimg.count");
7920 log_verbose("Saved map image definitions: %d.", mapdef_count);
7921
7922 if (0 >= mapdef_count) {
7923 return;
7924 }
7925
7926 for (i = 0; i < mapdef_count; i++) {
7927 const char *p;
7928
7929 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7930 if (NULL == p) {
7931 log_verbose("[Mapimg %4d] Missing definition.", i);
7932 continue;
7933 }
7934
7935 if (!mapimg_define(p, FALSE)) {
7936 log_error("Invalid map image definition %4d: %s.", i, p);
7937 }
7938
7939 log_verbose("Mapimg %4d loaded.", i);
7940 }
7941}
7942
7943/************************************************************************/
7946static void sg_save_mapimg(struct savedata *saving)
7947{
7948 /* Check status and return if not OK (sg_success FALSE). */
7949 sg_check_ret();
7950
7951 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7952 if (mapimg_count() > 0) {
7953 int i;
7954
7955 for (i = 0; i < mapimg_count(); i++) {
7956 char buf[MAX_LEN_MAPDEF];
7957
7958 mapimg_id2str(i, buf, sizeof(buf));
7959 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7960 }
7961 }
7962}
7963
7964/* =======================================================================
7965 * Sanity checks for loading / saving a game.
7966 * ======================================================================= */
7967
7968/************************************************************************/
7972{
7973 int players;
7974
7975 /* Check status and return if not OK (sg_success FALSE). */
7976 sg_check_ret();
7977
7978 if (game.info.is_new_game) {
7979 /* Nothing to do for new games (or not started scenarios). */
7980 return;
7981 }
7982
7983 /* Old savegames may have maxplayers lower than current player count,
7984 * fix. */
7985 players = normal_player_count();
7986 if (game.server.max_players < players) {
7987 log_verbose("Max players lower than current players, fixing");
7988 game.server.max_players = players;
7989 }
7990
7991 /* Fix ferrying sanity */
7992 players_iterate(pplayer) {
7993 unit_list_iterate_safe(pplayer->units, punit) {
7996 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8002 }
8005
8006 /* Fix stacking issues. We don't rely on the savegame preserving
8007 * alliance invariants (old savegames often did not) so if there are any
8008 * unallied units on the same tile we just bounce them. */
8009 players_iterate(pplayer) {
8011 resolve_unit_stacks(pplayer, aplayer, TRUE);
8014
8015 /* Recalculate the potential buildings for each city. Has caused some
8016 * problems with game random state.
8017 * This also changes the game state if you save the game directly after
8018 * loading it and compare the results. */
8019 players_iterate(pplayer) {
8020 /* Building advisor needs data phase open in order to work */
8021 adv_data_phase_init(pplayer, FALSE);
8022 building_advisor(pplayer);
8023 /* Close data phase again so it can be opened again when game starts. */
8024 adv_data_phase_done(pplayer);
8026
8027 /* Prevent a buggy or intentionally crafted save game from crashing
8028 * Freeciv. See hrm Bug #887748 */
8029 players_iterate(pplayer) {
8030 city_list_iterate(pplayer->cities, pcity) {
8031 worker_task_list_iterate(pcity->task_reqs, ptask) {
8032 if (!worker_task_is_sane(ptask)) {
8033 log_error("[city id: %d] Bad worker task %d.",
8034 pcity->id, ptask->act);
8035 worker_task_list_remove(pcity->task_reqs, ptask);
8036 free(ptask);
8037 ptask = NULL;
8038 }
8042
8043 /* Check worked tiles map */
8044#ifdef FREECIV_DEBUG
8045 if (loading->worked_tiles != NULL) {
8046 /* Check the entire map for unused worked tiles */
8047 whole_map_iterate(&(wld.map), ptile) {
8048 if (loading->worked_tiles[ptile->index] != -1) {
8049 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8050 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8051 }
8053 }
8054#endif /* FREECIV_DEBUG */
8055
8056 /* Check researching technologies and goals. */
8058 int techs;
8059
8060 if (presearch->researching != A_UNSET
8061 && !is_future_tech(presearch->researching)
8062 && (valid_advance_by_number(presearch->researching) == NULL
8064 != TECH_PREREQS_KNOWN))) {
8065 log_sg(_("%s had invalid researching technology."),
8067 presearch->researching = A_UNSET;
8068 }
8069 if (presearch->tech_goal != A_UNSET
8070 && !is_future_tech(presearch->tech_goal)
8071 && (valid_advance_by_number(presearch->tech_goal) == NULL
8074 == TECH_KNOWN))) {
8075 log_sg(_("%s had invalid technology goal."),
8077 presearch->tech_goal = A_UNSET;
8078 }
8079
8081
8082 if (presearch->techs_researched != techs) {
8083 sg_regr(3000300,
8084 _("%s had finished researches count wrong."),
8086 presearch->techs_researched = techs;
8087 }
8089
8090 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8091 players_iterate(pplayer) {
8092 int unique_count[U_LAST];
8093
8094 memset(unique_count, 0, sizeof(unique_count));
8095
8096 unit_list_iterate(pplayer->units, punit) {
8099
8102 log_sg(_("%s has multiple units of type %s though it should be possible "
8103 "to have only one."),
8105 }
8108
8109 players_iterate(pplayer) {
8110 unit_list_iterate_safe(pplayer->units, punit) {
8111 if (punit->has_orders
8113 punit->orders.list)) {
8114 log_sg("Invalid unit orders for unit %d.", punit->id);
8116 }
8119
8120 /* Check max rates (rules may have changed since saving) */
8121 players_iterate(pplayer) {
8124
8125 /* Check initial city sanity */
8126 players_iterate(pplayer) {
8127 if (!player_has_flag(pplayer, PLRF_FIRST_CITY)
8128 && city_list_size(pplayer->cities) > 0) {
8129 log_sg(_("%s inconsistency: Has never had their first city, "
8130 "but has cities this very moment. Fixing."),
8131 player_name(pplayer));
8132 BV_SET(pplayer->flags, PLRF_FIRST_CITY);
8133 }
8135
8136 if (0 == strlen(server.game_identifier)
8137 || !is_base64url(server.game_identifier)) {
8138 /* This uses fc_rand(), so random state has to be initialized before. */
8139 randomize_base64url_string(server.game_identifier,
8140 sizeof(server.game_identifier));
8141 }
8142
8143 /* Restore game random state, just in case various initialization code
8144 * inexplicably altered the previously existing state. */
8145 if (!game.info.is_new_game) {
8146 fc_rand_set_state(loading->rstate);
8147 }
8148
8149 /* At the end do the default sanity checks. */
8150 sanity_check();
8151}
8152
8153/************************************************************************/
8157{
8158 /* Check status and return if not OK (sg_success FALSE). */
8159 sg_check_ret();
8160}
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:268
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:570
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:3444
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2884
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:3371
void destroy_city_virtual(struct city *pcity)
Definition city.c:3530
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:2772
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:2843
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3445
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:73
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
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:1669
#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:1875
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1685
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1705
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1774
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:1862
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:1762
bool map_is_empty(void)
Definition map.c:149
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1652
#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:3208
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:2456
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2406
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3254
void shuffle_players(void)
Definition plrhand.c:2381
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:3241
void fit_nationset_to_players(void)
Definition plrhand.c:2662
#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:9367
#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:432
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:7887
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1204
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2757
static void unit_ordering_apply(void)
Definition savegame3.c:1085
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3627
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:1018
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3507
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3177
bool sg_success
Definition savecompat.c:34
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:155
static char * quote_block(const void *const data, int length)
Definition savegame3.c:895
#define halfbyte_iterate_extras_end
Definition savegame3.c:263
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:258
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2816
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:3009
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3468
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:154
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4083
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:222
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5581
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5533
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4960
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2909
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:6054
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:1341
static enum unit_activity char2activity(char activity)
Definition savegame3.c:872
static void unit_ordering_calc(void)
Definition savegame3.c:1056
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2666
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5985
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1256
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2437
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3122
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7533
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3424
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:175
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2046
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2396
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1780
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6580
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7858
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7844
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3298
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7639
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:279
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2475
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2501
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2093
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:4144
static char order2char(enum unit_orders order)
Definition savegame3.c:735
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7734
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2589
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1139
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6633
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2246
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1171
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1268
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7369
static enum direction8 char2dir(char dir)
Definition savegame3.c:759
#define ACTIVITY_LAST_SAVEGAME3
Definition savegame3.c:156
static bool sg_load_player_city(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr, int wlist_max_length, int routes_max)
Definition savegame3.c:5084
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1233
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8156
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7906
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6893
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:6973
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2069
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2869
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7056
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2949
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:7946
static const char savefile_options_default[]
Definition savegame3.c:281
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:7258
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2704
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3035
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:621
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3888
#define PART_ADJUST
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1304
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7714
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:2977
static void treaty_save(struct Treaty *ptr, void *data_in)
Definition savegame3.c:7817
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:7971
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7703
void savegame3_load(struct section_file *file)
Definition savegame3.c:459
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1106
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2266
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4634
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2486
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2682
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3564
void save_restore_sane_state(void)
Definition savemain.c:354
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
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
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:272
struct section_file * file
Definition savegame3.c:268
bool scenario
Definition savegame3.c:273
bool save_players
Definition savegame3.c:276
char secfile_options[512]
Definition savegame3.c:269
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:7811
enum unit_activity activity
Definition unit.h:93
enum unit_orders order
Definition unit.h:92
int action
Definition unit.h:99
enum direction8 dir
Definition unit.h:101
int target
Definition unit.h:96
int sub_target
Definition unit.h:97
Definition unit.h:137
int length
Definition unit.h:194
int upkeep[O_LAST]
Definition unit.h:147
bool has_orders
Definition unit.h:192
struct unit::@80 orders
enum action_decision action_decision_want
Definition unit.h:201
int battlegroup
Definition unit.h:190
enum unit_activity activity
Definition unit.h:156
int moves_left
Definition unit.h:149
int id
Definition unit.h:144
int ord_city
Definition unit.h:241
bool moved
Definition unit.h:172
int ord_map
Definition unit.h:240
int index
Definition unit.h:194
struct vision * vision
Definition unit.h:243
bool vigilant
Definition unit.h:196
int hp
Definition unit.h:150
int fuel
Definition unit.h:152
struct extra_type * changed_from_target
Definition unit.h:169
int current_form_turn
Definition unit.h:207
bool stay
Definition unit.h:204
enum direction8 facing
Definition unit.h:141
struct unit::@81::@84 server
struct extra_type * activity_target
Definition unit.h:163
int activity_count
Definition unit.h:161
struct unit_order * list
Definition unit.h:197
enum unit_activity changed_from
Definition unit.h:167
struct player * nationality
Definition unit.h:143
bool repeat
Definition unit.h:195
int homecity
Definition unit.h:145
bool paradropped
Definition unit.h:173
bool done_moving
Definition unit.h:180
int birth_turn
Definition unit.h:206
struct goods_type * carrying
Definition unit.h:185
struct tile * goto_tile
Definition unit.h:154
struct tile * action_decision_tile
Definition unit.h:202
int veteran
Definition unit.h:151
int changed_from_count
Definition unit.h:168
enum server_side_agent ssa_controller
Definition unit.h:171
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:384
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:468
struct team * team_new(struct team_slot *tslot)
Definition team.c:318
const struct player_list * team_members(const struct team *pteam)
Definition team.c:457
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:396
#define BATTLEGROUP_NONE
Definition unit.h:189
unit_orders
Definition unit.h:36
@ ORDER_ACTION_MOVE
Definition unit.h:44
@ ORDER_ACTIVITY
Definition unit.h:40
@ ORDER_FULL_MP
Definition unit.h:42
@ ORDER_MOVE
Definition unit.h:38
@ ORDER_LAST
Definition unit.h:48
@ ORDER_PERFORM_ACTION
Definition unit.h:46
#define unit_owner(_pu)
Definition unit.h:395
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:128
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24