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