Freeciv-3.4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
savegame3.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14/*
15 This file includes the definition of a new savegame format introduced with
16 3.0. It is defined by the mandatory option '+version3'. The main load
17 function checks if this option is present. If not, the old (pre-3.0)
18 loading routines are used.
19 The format version is also saved in the settings section of the savefile, as an
20 integer (savefile.version). The integer is used to determine the version
21 of the savefile.
22
23 Structure of this file:
24
25 - The main function for saving is savegame3_save().
26
27 - The real work is done by savegame3_load() and savegame3_save_real().
28 This function call all submodules (settings, players, etc.)
29
30 - The remaining part of this file is split into several sections:
31 * helper functions
32 * save / load functions for all submodules (and their subsubmodules)
33
34 - If possible, all functions for load / save submodules should exit in
35 pairs named sg_load_<submodule> and sg_save_<submodule>. If one is not
36 needed please add a comment why.
37
38 - The submodules can be further divided as:
39 sg_load_<submodule>_<subsubmodule>
40
41 - If needed (due to static variables in the *.c files) these functions
42 can be located in the corresponding source files (as done for the settings
43 and the event_cache).
44
45 Creating a savegame:
46
47 (nothing at the moment)
48
49 Loading a savegame:
50
51 - The status of the process is saved within the static variable
52 'sg_success'. This variable is set to TRUE within savegame3_load().
53 If you encounter an error use sg_failure_*() to set it to FALSE and
54 return an error message. Furthermore, sg_check_* should be used at the
55 start of each (submodule) function to return if previous functions failed.
56
57 - While the loading process dependencies between different modules exits.
58 They can be handled within the struct loaddata *loading which is used as
59 first argument for all sg_load_*() function. Please indicate the
60 dependencies within the definition of this struct.
61
62*/
63
64#ifdef HAVE_CONFIG_H
65#include <fc_config.h>
66#endif
67
68#include <ctype.h>
69#include <stdarg.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73
74/* utility */
75#include "bitvector.h"
76#include "fcintl.h"
77#include "idex.h"
78#include "log.h"
79#include "mem.h"
80#include "rand.h"
81#include "registry.h"
82#include "shared.h"
83#include "support.h" /* bool type */
84#include "timing.h"
85
86/* common */
87#include "achievements.h"
88#include "ai.h"
89#include "bitvector.h"
90#include "capability.h"
91#include "citizens.h"
92#include "city.h"
93#include "counters.h"
94#include "game.h"
95#include "government.h"
96#include "map.h"
97#include "mapimg.h"
98#include "movement.h"
99#include "multipliers.h"
100#include "packets.h"
101#include "research.h"
102#include "rgbcolor.h"
103#include "sex.h"
104#include "specialist.h"
105#include "unit.h"
106#include "unitlist.h"
107#include "version.h"
108
109/* server */
110#include "barbarian.h"
111#include "citizenshand.h"
112#include "citytools.h"
113#include "cityturn.h"
114#include "diplhand.h"
115#include "maphand.h"
116#include "meta.h"
117#include "notify.h"
118#include "plrhand.h"
119#include "report.h"
120#include "ruleload.h"
121#include "sanitycheck.h"
122#include "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[MAP_NATIVE_WIDTH + 1]; \
175 int _nat_x, _nat_y; \
176 \
177 for (_nat_y = 0; _nat_y < MAP_NATIVE_HEIGHT; _nat_y++) { \
178 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _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[MAP_NATIVE_WIDTH] = '\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 < MAP_NATIVE_HEIGHT; _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) != MAP_NATIVE_WIDTH) { \
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'", MAP_NATIVE_WIDTH, strlen(_line), buf); \
237 _printed_warning = TRUE; \
238 continue; \
239 } \
240 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _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_load_map_altitude(struct loaddata *loading);
354static void sg_save_map_tiles(struct savedata *saving);
355static void sg_save_map_altitude(struct savedata *saving);
356static void sg_load_map_tiles_extras(struct loaddata *loading);
357static void sg_save_map_tiles_extras(struct savedata *saving);
358
359static void sg_load_map_startpos(struct loaddata *loading);
360static void sg_save_map_startpos(struct savedata *saving);
361static void sg_load_map_owner(struct loaddata *loading);
362static void sg_save_map_owner(struct savedata *saving);
363static void sg_load_map_worked(struct loaddata *loading);
364static void sg_save_map_worked(struct savedata *saving);
365static void sg_load_map_known(struct loaddata *loading);
366static void sg_save_map_known(struct savedata *saving);
367
368static void sg_load_players_basic(struct loaddata *loading);
369static void sg_load_players(struct loaddata *loading);
370static void sg_load_player_main(struct loaddata *loading,
371 struct player *plr);
372static void sg_load_player_cities(struct loaddata *loading,
373 struct player *plr);
374static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
375 struct city *pcity, const char *citystr,
378 struct player *plr,
379 struct city *pcity,
380 const char *citystr);
381static void sg_load_player_units(struct loaddata *loading,
382 struct player *plr);
383static bool sg_load_player_unit(struct loaddata *loading,
384 struct player *plr, struct unit *punit,
386 const char *unitstr);
388 struct player *plr);
389static void sg_load_player_attributes(struct loaddata *loading,
390 struct player *plr);
391static void sg_load_player_vision(struct loaddata *loading,
392 struct player *plr);
394 struct player *plr,
395 struct vision_site *pdcity,
396 const char *citystr);
397static void sg_save_players(struct savedata *saving);
398static void sg_save_player_main(struct savedata *saving,
399 struct player *plr);
400static void sg_save_player_cities(struct savedata *saving,
401 struct player *plr);
402static void sg_save_player_units(struct savedata *saving,
403 struct player *plr);
404static void sg_save_player_attributes(struct savedata *saving,
405 struct player *plr);
406static void sg_save_player_vision(struct savedata *saving,
407 struct player *plr);
408
409static void sg_load_researches(struct loaddata *loading);
410static void sg_save_researches(struct savedata *saving);
411
412static void sg_load_event_cache(struct loaddata *loading);
413static void sg_save_event_cache(struct savedata *saving);
414
415static void sg_load_treaties(struct loaddata *loading);
416static void sg_save_treaties(struct savedata *saving);
417
418static void sg_load_history(struct loaddata *loading);
419static void sg_save_history(struct savedata *saving);
420
421static void sg_load_mapimg(struct loaddata *loading);
422static void sg_save_mapimg(struct savedata *saving);
423
424static void sg_load_sanitycheck(struct loaddata *loading);
425static void sg_save_sanitycheck(struct savedata *saving);
426
427
428/************************************************************************/
431void savegame3_save(struct section_file *sfile, const char *save_reason,
432 bool scenario)
433{
434 fc_assert_ret(sfile != NULL);
435
436#ifdef DEBUG_TIMERS
437 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
439#endif
440
441 log_verbose("saving game in new format ...");
442 savegame3_save_real(sfile, save_reason, scenario);
443
444#ifdef DEBUG_TIMERS
446 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
448#endif /* DEBUG_TIMERS */
449}
450
451/* =======================================================================
452 * Basic load / save functions.
453 * ======================================================================= */
454
455/************************************************************************/
458void savegame3_load(struct section_file *file)
459{
460 struct loaddata *loading;
462
463 /* initialise loading */
468
469 /* Load the savegame data. */
470 /* [compat] */
472 /* [scenario] */
474 /* [savefile] */
476 /* [game] */
478 /* [random] */
480 /* [settings] */
482 /* [ruledata] */
484 /* [players] (basic data) */
486 /* [map]; needs width and height loaded by [settings] */
488 /* [research] */
490 /* [player<i>] */
492 /* [counters] */
494 /* [event_cache] */
496 /* [treaties] */
498 /* [history] */
500 /* [mapimg] */
502 /* [script] -- must come last as may reference game objects */
504 /* [post_load_compat]; needs the game loaded by [savefile] */
506
507 /* Sanity checks for the loaded game. */
509
510 /* deinitialise loading */
514
515 if (!sg_success) {
516 log_error("Failure loading savegame!");
517 /* Try to get the server back to a vaguely sane state */
521 }
522}
523
524/************************************************************************/
528 const char *save_reason,
529 bool scenario)
530{
531 struct savedata *saving;
532
533 /* initialise loading */
536
537 /* [scenario] */
538 /* This should be first section so scanning through all scenarios just for
539 * names and descriptions would go faster. */
541 /* [savefile] */
543 /* [counters] */
545 /* [game] */
547 /* [random] */
549 /* [script] */
551 /* [settings] */
553 /* [ruledata] */
555 /* [map] */
557 /* [player<i>] */
559 /* [research] */
561 /* [event_cache] */
563 /* [treaty<i>] */
565 /* [history] */
567 /* [mapimg] */
569
570 /* Sanity checks for the saved game. */
572
573 /* deinitialise saving */
575
576 if (!sg_success) {
577 log_error("Failure saving savegame!");
578 }
579}
580
581/************************************************************************/
584static struct loaddata *loaddata_new(struct section_file *file)
585{
586 struct loaddata *loading = calloc(1, sizeof(*loading));
587 loading->file = file;
588 loading->secfile_options = NULL;
589
590 loading->improvement.order = NULL;
591 loading->improvement.size = -1;
592 loading->technology.order = NULL;
593 loading->technology.size = -1;
594 loading->activities.order = NULL;
595 loading->activities.size = -1;
596 loading->trait.order = NULL;
597 loading->trait.size = -1;
598 loading->extra.order = NULL;
599 loading->extra.size = -1;
600 loading->multiplier.order = NULL;
601 loading->multiplier.size = -1;
602 loading->specialist.order = NULL;
603 loading->specialist.size = -1;
604 loading->action.order = NULL;
605 loading->action.size = -1;
606 loading->act_dec.order = NULL;
607 loading->act_dec.size = -1;
608 loading->ssa.order = NULL;
609 loading->ssa.size = -1;
610 loading->coptions.order = NULL;
611 loading->coptions.size = -1;
612
613 loading->server_state = S_S_INITIAL;
614 loading->rstate = fc_rand_state();
615 loading->worked_tiles = NULL;
616
617 return loading;
618}
619
620/************************************************************************/
624{
625 if (loading->improvement.order != NULL) {
626 free(loading->improvement.order);
627 }
628
629 if (loading->technology.order != NULL) {
630 free(loading->technology.order);
631 }
632
633 if (loading->activities.order != NULL) {
634 free(loading->activities.order);
635 }
636
637 if (loading->trait.order != NULL) {
638 free(loading->trait.order);
639 }
640
641 if (loading->extra.order != NULL) {
642 free(loading->extra.order);
643 }
644
645 if (loading->multiplier.order != NULL) {
646 free(loading->multiplier.order);
647 }
648
649 if (loading->specialist.order != NULL) {
650 free(loading->specialist.order);
651 }
652
653 if (loading->action.order != NULL) {
654 free(loading->action.order);
655 }
656
657 if (loading->act_dec.order != NULL) {
658 free(loading->act_dec.order);
659 }
660
661 if (loading->ssa.order != NULL) {
662 free(loading->ssa.order);
663 }
664
665 if (loading->coptions.order != NULL) {
666 free(loading->coptions.order);
667 }
668
669 if (loading->worked_tiles != NULL) {
670 free(loading->worked_tiles);
671 }
672
673 free(loading);
674}
675
676/************************************************************************/
679static struct savedata *savedata_new(struct section_file *file,
680 const char *save_reason,
681 bool scenario)
682{
683 struct savedata *saving = calloc(1, sizeof(*saving));
684 saving->file = file;
685 saving->secfile_options[0] = '\0';
686
687 saving->save_reason = save_reason;
688 saving->scenario = scenario;
689
690 saving->save_players = FALSE;
691
692 return saving;
693}
694
695/************************************************************************/
698static void savedata_destroy(struct savedata *saving)
699{
700 free(saving);
701}
702
703/* =======================================================================
704 * Helper functions.
705 * ======================================================================= */
706
707/************************************************************************/
710static enum unit_orders char2order(char order)
711{
712 switch (order) {
713 case 'm':
714 case 'M':
715 return ORDER_MOVE;
716 case 'w':
717 case 'W':
718 return ORDER_FULL_MP;
719 case 'a':
720 case 'A':
721 return ORDER_ACTIVITY;
722 case 'x':
723 case 'X':
724 return ORDER_ACTION_MOVE;
725 case 'p':
726 case 'P':
728 }
729
730 /* This can happen if the savegame is invalid. */
731 return ORDER_LAST;
732}
733
734/************************************************************************/
737static char order2char(enum unit_orders order)
738{
739 switch (order) {
740 case ORDER_MOVE:
741 return 'm';
742 case ORDER_FULL_MP:
743 return 'w';
744 case ORDER_ACTIVITY:
745 return 'a';
747 return 'x';
749 return 'p';
750 case ORDER_LAST:
751 break;
752 }
753
755 return '?';
756}
757
758/************************************************************************/
761static enum direction8 char2dir(char dir)
762{
763 /* Numberpad values for the directions. */
764 switch (dir) {
765 case '1':
766 return DIR8_SOUTHWEST;
767 case '2':
768 return DIR8_SOUTH;
769 case '3':
770 return DIR8_SOUTHEAST;
771 case '4':
772 return DIR8_WEST;
773 case '6':
774 return DIR8_EAST;
775 case '7':
776 return DIR8_NORTHWEST;
777 case '8':
778 return DIR8_NORTH;
779 case '9':
780 return DIR8_NORTHEAST;
781 }
782
783 /* This can happen if the savegame is invalid. */
784 return direction8_invalid();
785}
786
787/************************************************************************/
790static char dir2char(enum direction8 dir)
791{
792 /* Numberpad values for the directions. */
793 switch (dir) {
794 case DIR8_NORTH:
795 return '8';
796 case DIR8_SOUTH:
797 return '2';
798 case DIR8_EAST:
799 return '6';
800 case DIR8_WEST:
801 return '4';
802 case DIR8_NORTHEAST:
803 return '9';
804 case DIR8_NORTHWEST:
805 return '7';
806 case DIR8_SOUTHEAST:
807 return '3';
808 case DIR8_SOUTHWEST:
809 return '1';
810 }
811
813
814 return '?';
815}
816
817/************************************************************************/
823static char activity2char(int activity)
824{
825 switch (activity) {
826 case ACTIVITY_IDLE:
827 return 'w';
828 case ACTIVITY_CLEAN:
829 return 'C';
831 return 'p';
832 case ACTIVITY_MINE:
833 return 'm';
834 case ACTIVITY_PLANT:
835 return 'M';
837 return 'i';
839 return 'I';
841 return 'f';
842 case ACTIVITY_SENTRY:
843 return 's';
844 case ACTIVITY_PILLAGE:
845 return 'e';
846 case ACTIVITY_GOTO:
847 return 'g';
848 case ACTIVITY_EXPLORE:
849 return 'x';
851 return 'o';
853 return 'y';
855 return 'u';
856 case ACTIVITY_BASE:
857 return 'b';
859 return 'R';
860 case ACTIVITY_CONVERT:
861 return 'c';
862 case ACTIVITY_LAST:
863 break;
864 }
865
867
868 return '?';
869}
870
871/************************************************************************/
874static enum unit_activity char2activity(char activity)
875{
876 enum unit_activity a;
877
878 for (a = 0; a < ACTIVITY_LAST_SAVEGAME3; a++) {
879 /* Skip ACTIVITY_LAST. The SAVEGAME3 specific values are after it. */
880 if (a != ACTIVITY_LAST) {
881 char achar = activity2char(a);
882
883 if (activity == achar) {
884 return a;
885 }
886 }
887 }
888
889 /* This can happen if the savegame is invalid. */
890 return ACTIVITY_LAST;
891}
892
893/************************************************************************/
897static char *quote_block(const void *const data, int length)
898{
899 char *buffer = fc_malloc(length * 3 + 10);
900 size_t offset;
901 int i;
902
903 sprintf(buffer, "%d:", length);
904 offset = strlen(buffer);
905
906 for (i = 0; i < length; i++) {
907 sprintf(buffer + offset, "%02x ", ((unsigned char *) data)[i]);
908 offset += 3;
909 }
910 return buffer;
911}
912
913/************************************************************************/
918static int unquote_block(const char *const quoted_, void *dest,
919 int dest_length)
920{
921 int i, length, parsed, tmp;
922 char *endptr;
923 const char *quoted = quoted_;
924
925 parsed = sscanf(quoted, "%d", &length);
926
927 if (parsed != 1) {
928 log_error(_("Syntax error in attribute block."));
929 return 0;
930 }
931
932 if (length > dest_length) {
933 return 0;
934 }
935
936 quoted = strchr(quoted, ':');
937
938 if (quoted == NULL) {
939 log_error(_("Syntax error in attribute block."));
940 return 0;
941 }
942
943 quoted++;
944
945 for (i = 0; i < length; i++) {
946 tmp = strtol(quoted, &endptr, 16);
947
948 if ((endptr - quoted) != 2
949 || *endptr != ' '
950 || (tmp & 0xff) != tmp) {
951 log_error(_("Syntax error in attribute block."));
952 return 0;
953 }
954
955 ((unsigned char *) dest)[i] = tmp;
956 quoted += 3;
957 }
958
959 return length;
960}
961
962/************************************************************************/
967 struct worklist *pwl, const char *path, ...)
968{
969 int i;
970 const char *kind;
971 const char *name;
972 char path_str[1024];
973 va_list ap;
974
975 /* The first part of the registry path is taken from the varargs to the
976 * function. */
977 va_start(ap, path);
978 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
979 va_end(ap);
980
983 "%s.wl_length", path_str);
984
985 for (i = 0; i < pwl->length; i++) {
986 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
987
988 /* We lookup the production value by name. An invalid entry isn't a
989 * fatal error; we just truncate the worklist. */
990 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
991 path_str, i);
992 pwl->entries[i] = universal_by_rule_name(kind, name);
993 if (pwl->entries[i].kind == universals_n_invalid()) {
994 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
995 name);
996 pwl->length = i;
997 break;
998 }
999 }
1000
1001 /* Padding entries */
1002 for (; i < wlist_max_length; i++) {
1003 (void) secfile_entry_lookup(file, "%s.wl_kind%d", path_str, i);
1004 (void) secfile_entry_lookup(file, "%s.wl_value%d", path_str, i);
1005 }
1006}
1007
1008/************************************************************************/
1012static void worklist_save(struct section_file *file,
1013 const struct worklist *pwl,
1014 int max_length, const char *path, ...)
1015{
1016 char path_str[1024];
1017 int i;
1018 va_list ap;
1019
1020 /* The first part of the registry path is taken from the varargs to the
1021 * function. */
1022 va_start(ap, path);
1023 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1024 va_end(ap);
1025
1026 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1027
1028 for (i = 0; i < pwl->length; i++) {
1029 const struct universal *entry = pwl->entries + i;
1031 "%s.wl_kind%d", path_str, i);
1033 "%s.wl_value%d", path_str, i);
1034 }
1035
1037
1038 /* We want to keep savegame in tabular format, so each line has to be
1039 * of equal length. Fill table up to maximum worklist size. */
1040 for (i = pwl->length ; i < max_length; i++) {
1041 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1042 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1043 }
1044}
1045
1046/************************************************************************/
1050static void unit_ordering_calc(void)
1051{
1052 int j;
1053
1054 players_iterate(pplayer) {
1055 /* to avoid junk values for unsupported units: */
1056 unit_list_iterate(pplayer->units, punit) {
1057 punit->server.ord_city = 0;
1059 city_list_iterate(pplayer->cities, pcity) {
1060 j = 0;
1061 unit_list_iterate(pcity->units_supported, punit) {
1062 punit->server.ord_city = j++;
1066
1067 whole_map_iterate(&(wld.map), ptile) {
1068 j = 0;
1069 unit_list_iterate(ptile->units, punit) {
1070 punit->server.ord_map = j++;
1073}
1074
1075/************************************************************************/
1079static void unit_ordering_apply(void)
1080{
1081 players_iterate(pplayer) {
1082 city_list_iterate(pplayer->cities, pcity) {
1083 unit_list_sort_ord_city(pcity->units_supported);
1084 }
1087
1088 whole_map_iterate(&(wld.map), ptile) {
1089 unit_list_sort_ord_map(ptile->units);
1091}
1092
1093/************************************************************************/
1100static void sg_extras_set_dbv(struct dbv *extras, char ch,
1101 struct extra_type **idx)
1102{
1103 int i, bin;
1104 const char *pch = strchr(hex_chars, ch);
1105
1106 if (!pch || ch == '\0') {
1107 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1108 bin = 0;
1109 } else {
1110 bin = pch - hex_chars;
1111 }
1112
1113 for (i = 0; i < 4; i++) {
1114 struct extra_type *pextra = idx[i];
1115
1116 if (pextra == NULL) {
1117 continue;
1118 }
1119 if ((bin & (1 << i))
1120 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1121 dbv_set(extras, extra_index(pextra));
1122 }
1123 }
1124}
1125
1126/************************************************************************/
1134 struct extra_type **idx)
1135{
1136 int i, bin;
1137 const char *pch = strchr(hex_chars, ch);
1138
1139 if (!pch || ch == '\0') {
1140 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1141 bin = 0;
1142 } else {
1143 bin = pch - hex_chars;
1144 }
1145
1146 for (i = 0; i < 4; i++) {
1147 struct extra_type *pextra = idx[i];
1148
1149 if (pextra == NULL) {
1150 continue;
1151 }
1152 if ((bin & (1 << i))
1153 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1154 BV_SET(*extras, extra_index(pextra));
1155 }
1156 }
1157}
1158
1159/************************************************************************/
1165static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1166 const int *idx)
1167{
1168 int i, bin = 0;
1169 int max = dbv_bits(extras);
1170
1171 for (i = 0; i < 4; i++) {
1172 int extra = idx[i];
1173
1174 if (extra < 0) {
1175 break;
1176 }
1177
1178 if (extra < max
1179 && (dbv_isset(extras, extra)
1180 /* An invalid resource, a resource that can't exist at the tile's
1181 * current terrain, isn't in the bit extra vector. Save it so it
1182 * can return if the tile's terrain changes to something it can
1183 * exist on. */
1184 || extra_by_number(extra) == presource)) {
1185 bin |= (1 << i);
1186 }
1187 }
1188
1189 return hex_chars[bin];
1190}
1191
1192/************************************************************************/
1198static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1199 const int *idx)
1200{
1201 int i, bin = 0;
1202
1203 for (i = 0; i < 4; i++) {
1204 int extra = idx[i];
1205
1206 if (extra < 0) {
1207 break;
1208 }
1209
1210 if (BV_ISSET(extras, extra)
1211 /* An invalid resource, a resource that can't exist at the tile's
1212 * current terrain, isn't in the bit extra vector. Save it so it
1213 * can return if the tile's terrain changes to something it can
1214 * exist on. */
1215 || extra_by_number(extra) == presource) {
1216 bin |= (1 << i);
1217 }
1218 }
1219
1220 return hex_chars[bin];
1221}
1222
1223/************************************************************************/
1227static struct terrain *char2terrain(char ch)
1228{
1229 /* terrain_by_identifier plus fatal error */
1231 return T_UNKNOWN;
1232 }
1233 terrain_type_iterate(pterrain) {
1234 if (pterrain->identifier_load == ch) {
1235 return pterrain;
1236 }
1238
1239 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1240
1242
1244}
1245
1246/************************************************************************/
1250static char terrain2char(const struct terrain *pterrain)
1251{
1252 if (pterrain == T_UNKNOWN) {
1254 } else {
1255 return pterrain->identifier;
1256 }
1257}
1258
1259/************************************************************************/
1264 const char *path, int plrno)
1265{
1266 char path_with_name[128];
1267 const char *name;
1268 struct advance *padvance;
1269
1271 "%s_name", path);
1272
1274
1275 if (!name || name[0] == '\0') {
1276 /* Used by researching_saved */
1277 return A_UNKNOWN;
1278 }
1279 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1280 return A_FUTURE;
1281 }
1282 if (fc_strcasecmp(name, "A_NONE") == 0) {
1283 return A_NONE;
1284 }
1285 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1286 return A_UNSET;
1287 }
1288
1291 "%s: unknown technology \"%s\".", path_with_name, name);
1292
1293 return advance_number(padvance);
1294}
1295
1296/************************************************************************/
1299static void technology_save(struct section_file *file,
1300 const char *path, int plrno, Tech_type_id tech)
1301{
1302 char path_with_name[128];
1303 const char *name;
1304
1306 "%s_name", path);
1307
1308 switch (tech) {
1309 case A_UNKNOWN: /* Used by researching_saved */
1310 name = "";
1311 break;
1312 case A_NONE:
1313 name = "A_NONE";
1314 break;
1315 case A_UNSET:
1316 name = "A_UNSET";
1317 break;
1318 case A_FUTURE:
1319 name = "A_FUTURE";
1320 break;
1321 default:
1323 break;
1324 }
1325
1327}
1328
1329/* =======================================================================
1330 * Load / save savefile data.
1331 * ======================================================================= */
1332
1333/************************************************************************/
1337{
1338 int i;
1339 const char *terr_name;
1340 bool ruleset_datafile;
1342 const char *str;
1343
1344 /* Check status and return if not OK (sg_success FALSE). */
1345 sg_check_ret();
1346
1347 /* Load savefile options. */
1348 loading->secfile_options
1349 = secfile_lookup_str(loading->file, "savefile.options");
1350
1351 /* We don't need these entries, but read them anyway to avoid
1352 * warnings about unread secfile entries. */
1353 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1354 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1355
1356 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1358
1359 if (game.scenario.datafile[0] != '\0') {
1361 } else {
1363 }
1364
1367 const char *req_caps;
1368
1371 /* Failed to load correct ruleset */
1372 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1374 }
1375
1376 req_caps = secfile_lookup_str_default(loading->file, "",
1377 "scenario.ruleset_caps");
1378 strncpy(game.scenario.req_caps, req_caps,
1379 sizeof(game.scenario.req_caps) - 1);
1380 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1381
1382 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1383 /* Current ruleset lacks required capabilities. */
1384 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1385 log_normal(_("Ruleset has capabilities: %s"),
1387 /* TRANS: ... ruleset dir ... scenario name ... */
1388 log_error(_("Current ruleset %s not compatible with the scenario %s."
1389 " Trying to switch to the ruleset specified by the"
1390 " scenario."),
1392
1394 }
1395 }
1396
1399 const char *ruleset, *alt_dir;
1400
1403 "savefile.rulesetdir");
1404
1405 /* Load ruleset. */
1407 if (!strcmp("default", game.server.rulesetdir)) {
1408 /* Here 'default' really means current default.
1409 * Saving happens with real ruleset name, so savegames containing this
1410 * are special scenarios. */
1412 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1414 }
1415
1416 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1417 "savefile.ruleset_alt_dir");
1418
1419 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1420 if (alt_dir) {
1422 _("Failed to load either of rulesets '%s' or '%s' "
1423 "needed for savegame."),
1424 ruleset, alt_dir);
1425 } else {
1427 _("Failed to load ruleset '%s' needed for savegame."),
1428 ruleset);
1429 }
1430 }
1431
1433 /* TRANS: ruleset dir */
1434 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1435 }
1436 }
1437
1438 /* Remove all aifill players. Correct number of them get created later
1439 * with correct skill level etc. */
1440 (void) aifill(0);
1441
1442 /* Time to load scenario specific luadata */
1443 if (game.scenario.datafile[0] != '\0') {
1444 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1446 } else {
1447 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1448 const struct strvec **path;
1449 const char *found = NULL;
1450 char testfile[MAX_LEN_PATH];
1451 struct section_file *secfile;
1452
1453 for (path = paths; found == NULL && *path != NULL; path++) {
1454 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1455
1456 found = fileinfoname(*path, testfile);
1457 }
1458
1459 if (found == NULL) {
1460 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1461 sg_success = FALSE;
1462 return;
1463 }
1464
1465 secfile = secfile_load(found, FALSE);
1466 if (secfile == NULL) {
1467 log_error(_("Failed to load scenario luadata file %s.luadata"),
1469 sg_success = FALSE;
1470 return;
1471 }
1472
1473 game.server.luadata = secfile;
1474 }
1475 }
1476
1478 "savefile.dbid");
1479
1480 /* This is in the savegame only if the game has been started before savegame3.c time,
1481 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1483 "savefile.last_updated_as_year");
1484
1485 /* Load improvements. */
1486 loading->improvement.size
1488 "savefile.improvement_size");
1489 if (loading->improvement.size) {
1490 loading->improvement.order
1491 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1492 "savefile.improvement_vector");
1493 sg_failure_ret(loading->improvement.size != 0,
1494 "Failed to load improvement order: %s",
1495 secfile_error());
1496 }
1497
1498 /* Load technologies. */
1499 loading->technology.size
1501 "savefile.technology_size");
1502 if (loading->technology.size) {
1503 loading->technology.order
1504 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1505 "savefile.technology_vector");
1506 sg_failure_ret(loading->technology.size != 0,
1507 "Failed to load technology order: %s",
1508 secfile_error());
1509 }
1510
1511 /* Load Activities. */
1512 loading->activities.size
1514 "savefile.activities_size");
1515 if (loading->activities.size) {
1516 loading->activities.order
1517 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1518 "savefile.activities_vector");
1519 sg_failure_ret(loading->activities.size != 0,
1520 "Failed to load activity order: %s",
1521 secfile_error());
1522 }
1523
1524 /* Load traits. */
1525 loading->trait.size
1527 "savefile.trait_size");
1528 if (loading->trait.size) {
1529 loading->trait.order
1530 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1531 "savefile.trait_vector");
1532 sg_failure_ret(loading->trait.size != 0,
1533 "Failed to load trait order: %s",
1534 secfile_error());
1535 }
1536
1537 /* Load extras. */
1538 loading->extra.size
1540 "savefile.extras_size");
1541 if (loading->extra.size) {
1542 const char **modname;
1543 size_t nmod;
1544 int j;
1545
1546 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1547 "savefile.extras_vector");
1548 sg_failure_ret(loading->extra.size != 0,
1549 "Failed to load extras order: %s",
1550 secfile_error());
1552 "Number of extras defined by the ruleset (= %d) are "
1553 "lower than the number in the savefile (= %d).",
1554 game.control.num_extra_types, (int)loading->extra.size);
1555 /* make sure that the size of the array is divisible by 4 */
1556 nmod = 4 * ((loading->extra.size + 3) / 4);
1557 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1558 for (j = 0; j < loading->extra.size; j++) {
1559 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1560 }
1561 free(modname);
1562 for (; j < nmod; j++) {
1563 loading->extra.order[j] = NULL;
1564 }
1565 }
1566
1567 /* Load multipliers. */
1568 loading->multiplier.size
1570 "savefile.multipliers_size");
1571 if (loading->multiplier.size) {
1572 const char **modname;
1573 int j;
1574
1575 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1576 "savefile.multipliers_vector");
1577 sg_failure_ret(loading->multiplier.size != 0,
1578 "Failed to load multipliers order: %s",
1579 secfile_error());
1580 /* It's OK for the set of multipliers in the savefile to differ
1581 * from those in the ruleset. */
1582 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1583 sizeof(*loading->multiplier.order));
1584 for (j = 0; j < loading->multiplier.size; j++) {
1585 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1586 if (!loading->multiplier.order[j]) {
1587 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1588 "discarding", modname[j]);
1589 }
1590 }
1591 free(modname);
1592 }
1593
1594 /* Load specialists. */
1595 loading->specialist.size
1597 "savefile.specialists_size");
1598 if (loading->specialist.size) {
1599 const char **modname;
1600 size_t nmod;
1601 int j;
1602
1603 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1604 "savefile.specialists_vector");
1605 sg_failure_ret(loading->specialist.size != 0,
1606 "Failed to load specialists order: %s",
1607 secfile_error());
1609 "Number of specialists defined by the ruleset (= %d) are "
1610 "lower than the number in the savefile (= %d).",
1611 game.control.num_specialist_types, (int)loading->specialist.size);
1612 /* make sure that the size of the array is divisible by 4 */
1613 /* That's not really needed with specialists at the moment, but done this way
1614 * for consistency with other types, and to be prepared for the time it needs
1615 * to be this way. */
1616 nmod = 4 * ((loading->specialist.size + 3) / 4);
1617 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1618 for (j = 0; j < loading->specialist.size; j++) {
1619 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1620 }
1621 free(modname);
1622 for (; j < nmod; j++) {
1623 loading->specialist.order[j] = NULL;
1624 }
1625 }
1626
1627 /* Load action order. */
1628 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1629 "savefile.action_size");
1630
1631 sg_failure_ret(loading->action.size > 0,
1632 "Failed to load action order: %s",
1633 secfile_error());
1634
1635 if (loading->action.size) {
1636 const char **modname;
1637 int j;
1638
1639 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1640 "savefile.action_vector");
1641
1642 loading->action.order = fc_calloc(loading->action.size,
1643 sizeof(*loading->action.order));
1644
1645 for (j = 0; j < loading->action.size; j++) {
1647
1648 if (real_action) {
1649 loading->action.order[j] = real_action->id;
1650 } else {
1651 log_sg("Unknown action \'%s\'", modname[j]);
1652 loading->action.order[j] = ACTION_NONE;
1653 }
1654 }
1655
1656 free(modname);
1657 }
1658
1659 /* Load action decision order. */
1660 loading->act_dec.size
1662 "savefile.action_decision_size");
1663
1664 sg_failure_ret(loading->act_dec.size > 0,
1665 "Failed to load action decision order: %s",
1666 secfile_error());
1667
1668 if (loading->act_dec.size) {
1669 const char **modname;
1670 int j;
1671
1672 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1673 "savefile.action_decision_vector");
1674
1675 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1676 sizeof(*loading->act_dec.order));
1677
1678 for (j = 0; j < loading->act_dec.size; j++) {
1679 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1681 }
1682
1683 free(modname);
1684 }
1685
1686 /* Load server side agent order. */
1687 loading->ssa.size
1689 "savefile.server_side_agent_size");
1690
1691 sg_failure_ret(loading->ssa.size > 0,
1692 "Failed to load server side agent order: %s",
1693 secfile_error());
1694
1695 if (loading->ssa.size) {
1696 const char **modname;
1697 int j;
1698
1699 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1700 "savefile.server_side_agent_list");
1701
1702 loading->ssa.order = fc_calloc(loading->ssa.size,
1703 sizeof(*loading->ssa.order));
1704
1705 for (j = 0; j < loading->ssa.size; j++) {
1706 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1708 }
1709
1710 free(modname);
1711 }
1712
1713 /* Load city options order. */
1714 loading->coptions.size
1716 "savefile.city_options_size");
1717
1718 sg_failure_ret(loading->coptions.size > 0,
1719 "Failed to load city options order: %s",
1720 secfile_error());
1721
1722 if (loading->coptions.size) {
1723 const char **modname;
1724 int j;
1725
1726 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1727 "savefile.city_options_vector");
1728
1729 loading->coptions.order = fc_calloc(loading->coptions.size,
1730 sizeof(*loading->coptions.order));
1731
1732 for (j = 0; j < loading->coptions.size; j++) {
1733 loading->coptions.order[j] = city_options_by_name(modname[j],
1735 }
1736
1737 free(modname);
1738 }
1739
1740 /* Terrain identifiers */
1742 pterr->identifier_load = '\0';
1744
1745 i = 0;
1747 "savefile.terrident%d.name", i)) != NULL) {
1749
1750 if (pterr != NULL) {
1751 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1752 "savefile.terrident%d.identifier", i);
1753
1754 pterr->identifier_load = *iptr;
1755 } else {
1756 log_error("Identifier for unknown terrain type %s.", terr_name);
1757 }
1758 i++;
1759 }
1760
1763 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1764 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1765 "%s and %s share a saved identifier",
1767 }
1770}
1771
1772/************************************************************************/
1776{
1777 int i;
1778
1779 /* Check status and return if not OK (sg_success FALSE). */
1780 sg_check_ret();
1781
1782 /* Save savefile options. */
1784
1785 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1786
1787 /* Save reason of the savefile generation. */
1788 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1789
1790 /* Save as accurate freeciv revision information as possible */
1791 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1792
1793 /* Freeciv version used in the very first launch of this game -
1794 * or even saving in pregame. */
1796 "savefile.orig_version");
1797
1798 /* Save rulesetdir at this point as this ruleset is required by this
1799 * savefile. */
1800 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1801
1802 if (game.control.version[0] != '\0') {
1803 /* Current ruleset has version information, save it.
1804 * This is never loaded, but exist in savegame file only for debugging purposes. */
1805 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1806 }
1807
1808 if (game.control.alt_dir[0] != '\0') {
1809 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1810 }
1811
1813 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1814 }
1815
1816 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1817
1818 /* Save improvement order in savegame, so we are not dependent on ruleset
1819 * order. If the game isn't started improvements aren't loaded so we can
1820 * not save the order. */
1822 "savefile.improvement_size");
1823 if (improvement_count() > 0) {
1824 const char *buf[improvement_count()];
1825
1826 improvement_iterate(pimprove) {
1827 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1829
1831 "savefile.improvement_vector");
1832 }
1833
1834 /* Save technology order in savegame, so we are not dependent on ruleset
1835 * order. If the game isn't started advances aren't loaded so we can not
1836 * save the order. */
1838 "savefile.technology_size");
1839 if (game.control.num_tech_types > 0) {
1840 const char *buf[game.control.num_tech_types];
1841
1842 buf[A_NONE] = "A_NONE";
1843 advance_iterate(a) {
1847 "savefile.technology_vector");
1848 }
1849
1850 /* Save activities order in the savegame. */
1852 "savefile.activities_size");
1853 if (ACTIVITY_LAST > 0) {
1854 const char **modname;
1855 int j;
1856
1857 i = 0;
1858
1860
1861 for (j = 0; j < ACTIVITY_LAST; j++) {
1863 }
1864
1867 "savefile.activities_vector");
1868 free(modname);
1869 }
1870
1871 /* Save specialists order in the savegame. */
1873 "savefile.specialists_size");
1874 {
1875 const char **modname;
1876
1877 i = 0;
1879
1883
1885 "savefile.specialists_vector");
1886
1887 free(modname);
1888 }
1889
1890 /* Save trait order in savegame. */
1892 "savefile.trait_size");
1893 {
1894 const char **modname;
1895 enum trait tr;
1896 int j;
1897
1898 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1899
1900 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1901 modname[j] = trait_name(tr);
1902 }
1903
1905 "savefile.trait_vector");
1906 free(modname);
1907 }
1908
1909 /* Save extras order in the savegame. */
1911 "savefile.extras_size");
1912 if (game.control.num_extra_types > 0) {
1913 const char **modname;
1914
1915 i = 0;
1917
1918 extra_type_iterate(pextra) {
1919 modname[i++] = extra_rule_name(pextra);
1921
1924 "savefile.extras_vector");
1925 free(modname);
1926 }
1927
1928 /* Save multipliers order in the savegame. */
1930 "savefile.multipliers_size");
1931 if (multiplier_count() > 0) {
1932 const char **modname;
1933
1935
1936 multipliers_iterate(pmul) {
1939
1942 "savefile.multipliers_vector");
1943 free(modname);
1944 }
1945
1946 /* Save city_option order in the savegame. */
1948 "savefile.city_options_size");
1949 if (CITYO_LAST > 0) {
1950 const char **modname;
1951 int j;
1952
1953 i = 0;
1954 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1955
1956 for (j = 0; j < CITYO_LAST; j++) {
1957 modname[i++] = city_options_name(j);
1958 }
1959
1961 CITYO_LAST,
1962 "savefile.city_options_vector");
1963 free(modname);
1964 }
1965
1966 /* Save action order in the savegame. */
1968 "savefile.action_size");
1969 if (NUM_ACTIONS > 0) {
1970 const char **modname;
1971 int j;
1972
1973 i = 0;
1974 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1975
1976 for (j = 0; j < NUM_ACTIONS; j++) {
1978 }
1979
1982 "savefile.action_vector");
1983 free(modname);
1984 }
1985
1986 /* Save action decision order in the savegame. */
1988 "savefile.action_decision_size");
1989 if (ACT_DEC_COUNT > 0) {
1990 const char **modname;
1991 int j;
1992
1993 i = 0;
1995
1996 for (j = 0; j < ACT_DEC_COUNT; j++) {
1998 }
1999
2002 "savefile.action_decision_vector");
2003 free(modname);
2004 }
2005
2006 /* Save server side agent order in the savegame. */
2008 "savefile.server_side_agent_size");
2009 if (SSA_COUNT > 0) {
2010 const char **modname;
2011 int j;
2012
2013 i = 0;
2014 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2015
2016 for (j = 0; j < SSA_COUNT; j++) {
2018 }
2019
2021 SSA_COUNT,
2022 "savefile.server_side_agent_list");
2023 free(modname);
2024 }
2025
2026 /* Save terrain character mapping in the savegame. */
2027 i = 0;
2029 char buf[2];
2030
2031 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2033 buf[1] = '\0';
2034 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2036}
2037
2038/************************************************************************/
2042 const char *option)
2043{
2044 /* Check status and return if not OK (sg_success FALSE). */
2045 sg_check_ret();
2046
2047 if (option == NULL) {
2048 /* no additional option */
2049 return;
2050 }
2051
2052 sz_strlcat(saving->secfile_options, option);
2053 secfile_replace_str(saving->file, saving->secfile_options,
2054 "savefile.options");
2055}
2056
2057/* =======================================================================
2058 * Load / save game status.
2059 * ======================================================================= */
2060
2061/************************************************************************/
2065{
2066 int i;
2067 const char *name;
2068
2069 /* Check status and return if not OK (sg_success FALSE). */
2070 sg_check_ret();
2071
2072 for (i = 0;
2074 "ruledata.government%d.name", i));
2075 i++) {
2077
2078 if (gov != NULL) {
2080 "ruledata.government%d.changes", i);
2081 }
2082 }
2083}
2084
2085/************************************************************************/
2088static void sg_load_game(struct loaddata *loading)
2089{
2090 const char *str;
2091 int i;
2092
2093 /* Check status and return if not OK (sg_success FALSE). */
2094 sg_check_ret();
2095
2096 /* Load server state. */
2097 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2098 "game.server_state");
2099 loading->server_state = server_states_by_name(str, strcmp);
2100 if (!server_states_is_valid(loading->server_state)) {
2101 /* Don't take any risk! */
2102 loading->server_state = S_S_INITIAL;
2103 }
2104
2106 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2107
2110 "game.meta_patches");
2112
2114 /* Do not overwrite this if the user requested a specific metaserver
2115 * from the command line (option --Metaserver). */
2119 "game.meta_server"));
2120 }
2121
2122 if ('\0' == srvarg.serverid[0]) {
2123 /* Do not overwrite this if the user requested a specific metaserver
2124 * from the command line (option --serverid). */
2127 "game.serverid"));
2128 }
2129 sz_strlcpy(server.game_identifier,
2130 secfile_lookup_str_default(loading->file, "", "game.id"));
2131 /* We are not checking game_identifier legality just yet.
2132 * That's done when we are sure that rand seed has been initialized,
2133 * so that we can generate new game_identifier, if needed.
2134 * See sq_load_sanitycheck(). */
2135
2137 "game.phase_mode");
2138 if (str != NULL) {
2141 log_error("Illegal phase mode \"%s\"", str);
2143 }
2144 } else {
2145 log_error("Phase mode missing");
2146 }
2147
2149 "game.phase_mode_stored");
2150 if (str != NULL) {
2153 log_error("Illegal stored phase mode \"%s\"", str);
2155 }
2156 } else {
2157 log_error("Stored phase mode missing");
2158 }
2161 "game.phase");
2165 "game.scoreturn");
2166
2169 "game.timeoutint");
2172 "game.timeoutintinc");
2175 "game.timeoutinc");
2178 "game.timeoutincmult");
2181 "game.timeoutcounter");
2182
2183 game.info.turn
2184 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2186 "game.year"), "%s", secfile_error());
2188 "game.world_peace_start"), "%s", secfile_error());
2190 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2191
2193 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2195 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2197 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2198
2200 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2202 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2204 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2205
2206 /* Savegame may have stored random_seed for documentation purposes only,
2207 * but we want to keep it for resaving. */
2208 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2209
2210 /* Global advances. */
2212 "game.global_advances");
2213 if (str != NULL) {
2214 sg_failure_ret(strlen(str) == loading->technology.size,
2215 "Invalid length of 'game.global_advances' ("
2216 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2217 strlen(str), loading->technology.size);
2218 for (i = 0; i < loading->technology.size; i++) {
2219 sg_failure_ret(str[i] == '1' || str[i] == '0',
2220 "Undefined value '%c' within 'game.global_advances'.",
2221 str[i]);
2222 if (str[i] == '1') {
2223 struct advance *padvance =
2224 advance_by_rule_name(loading->technology.order[i]);
2225
2226 if (padvance != NULL) {
2228 }
2229 }
2230 }
2231 }
2232
2234 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2235
2237 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2238}
2239
2240/************************************************************************/
2244{
2245 int set_count = 0;
2246
2248 char path[256];
2249
2250 fc_snprintf(path, sizeof(path),
2251 "ruledata.government%d", set_count++);
2252
2254 "%s.name", path);
2255 secfile_insert_int(saving->file, pgov->changed_to_times,
2256 "%s.changes", path);
2258}
2259
2260/************************************************************************/
2263static void sg_save_game(struct savedata *saving)
2264{
2266 char global_advances[game.control.num_tech_types + 1];
2267 int i;
2268
2269 /* Check status and return if not OK (sg_success FALSE). */
2270 sg_check_ret();
2271
2272 /* Game state: once the game is no longer a new game (ie, has been
2273 * started the first time), it should always be considered a running
2274 * game for savegame purposes. */
2275 if (saving->scenario && !game.scenario.players) {
2277 } else {
2279 }
2281 "game.server_state");
2282
2283 if (game.server.phase_timer != NULL) {
2287 "game.phase_seconds");
2288 }
2289
2291 "game.meta_patches");
2292 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2293
2294 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2295 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2296
2299 "game.phase_mode");
2302 "game.phase_mode_stored");
2304 "game.phase");
2306 "game.scoreturn");
2307
2309 "game.timeoutint");
2311 "game.timeoutintinc");
2313 "game.timeoutinc");
2315 "game.timeoutincmult");
2317 "game.timeoutcounter");
2318
2319 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2320 secfile_insert_int(saving->file, game.info.year, "game.year");
2321 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2323 "game.year_0_hack");
2324
2326 "game.globalwarming");
2328 "game.heating");
2330 "game.warminglevel");
2331
2333 "game.nuclearwinter");
2335 "game.cooling");
2337 "game.coolinglevel");
2338 /* For debugging purposes only.
2339 * Do not save it if it's 0 (not known);
2340 * this confuses people reading this 'document' less than
2341 * saving 0. */
2342 if (game.server.seed != 0) {
2344 "game.random_seed");
2345 }
2346
2347 /* Global advances. */
2348 for (i = 0; i < game.control.num_tech_types; i++) {
2349 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2350 }
2351 global_advances[i] = '\0';
2352 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2353
2354 if (!game_was_started()) {
2355 saving->save_players = FALSE;
2356 } else {
2357 if (saving->scenario) {
2358 saving->save_players = game.scenario.players;
2359 } else {
2360 saving->save_players = TRUE;
2361 }
2362#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2364 "game.last_turn_change_time");
2365#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2367 "game.last_turn_change_time");
2368#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2369 }
2370 secfile_insert_bool(saving->file, saving->save_players,
2371 "game.save_players");
2372
2373 if (srv_state != S_S_INITIAL) {
2374 const char *ainames[ai_type_get_count()];
2375
2376 i = 0;
2377 ai_type_iterate(ait) {
2378 ainames[i] = ait->name;
2379 i++;
2381
2383 "game.ai_types");
2384 }
2385}
2386
2387/* =======================================================================
2388 * Load / save random status.
2389 * ======================================================================= */
2390
2391/************************************************************************/
2394static void sg_load_random(struct loaddata *loading)
2395{
2396 /* Check status and return if not OK (sg_success FALSE). */
2397 sg_check_ret();
2398
2399 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2400 const char *str;
2401 int i;
2402
2404 "random.index_J"), "%s", secfile_error());
2406 "random.index_K"), "%s", secfile_error());
2408 "random.index_X"), "%s", secfile_error());
2409
2410 for (i = 0; i < 8; i++) {
2411 str = secfile_lookup_str(loading->file, "random.table%d",i);
2412 sg_failure_ret(NULL != str, "%s", secfile_error());
2413 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2414 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2415 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2416 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2417 }
2418 loading->rstate.is_init = TRUE;
2419 fc_rand_set_state(loading->rstate);
2420 } else {
2421 /* No random values - mark the setting. */
2422 (void) secfile_entry_by_path(loading->file, "random.saved");
2423
2424 /* We're loading a game without a seed (which is okay, if it's a scenario).
2425 * We need to generate the game seed now because it will be needed later
2426 * during the load. */
2428 loading->rstate = fc_rand_state();
2429 }
2430}
2431
2432/************************************************************************/
2435static void sg_save_random(struct savedata *saving)
2436{
2437 /* Check status and return if not OK (sg_success FALSE). */
2438 sg_check_ret();
2439
2440 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2441 int i;
2442 RANDOM_STATE rstate = fc_rand_state();
2443
2444 secfile_insert_bool(saving->file, TRUE, "random.saved");
2445 fc_assert(rstate.is_init);
2446
2447 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2448 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2449 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2450
2451 for (i = 0; i < 8; i++) {
2452 char vec[100];
2453
2454 fc_snprintf(vec, sizeof(vec),
2455 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2456 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2457 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2458 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2459 secfile_insert_str(saving->file, vec, "random.table%d", i);
2460 }
2461 } else {
2462 secfile_insert_bool(saving->file, FALSE, "random.saved");
2463 }
2464}
2465
2466/* =======================================================================
2467 * Load / save lua script data.
2468 * ======================================================================= */
2469
2470/************************************************************************/
2473static void sg_load_script(struct loaddata *loading)
2474{
2475 /* Check status and return if not OK (sg_success FALSE). */
2476 sg_check_ret();
2477
2479}
2480
2481/************************************************************************/
2484static void sg_save_script(struct savedata *saving)
2485{
2486 /* Check status and return if not OK (sg_success FALSE). */
2487 sg_check_ret();
2488
2490}
2491
2492/* =======================================================================
2493 * Load / save scenario data.
2494 * ======================================================================= */
2495
2496/************************************************************************/
2500{
2501 const char *buf;
2502 int game_version;
2503
2504 /* Check status and return if not OK (sg_success FALSE). */
2505 sg_check_ret();
2506
2507 /* Load version. */
2509 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2510 /* We require at least version 2.90.99 - and at that time we saved version
2511 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2512 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2513 "version 2.90.99 required.");
2514
2515 loading->full_version = game_version;
2516
2517 game.scenario.datafile[0] = '\0';
2518
2520 "scenario.is_scenario"), "%s", secfile_error());
2521 if (!game.scenario.is_scenario) {
2522 return;
2523 }
2524
2525 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2526 if (buf[0] != '\0') {
2528 }
2529
2531 "scenario.authors");
2532 if (buf[0] != '\0') {
2534 } else {
2535 game.scenario.authors[0] = '\0';
2536 }
2537
2539 "scenario.description");
2540 if (buf[0] != '\0') {
2542 } else {
2543 game.scenario_desc.description[0] = '\0';
2544 }
2546 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2548 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2551 "scenario.startpos_nations");
2554 "scenario.prevent_new_cities");
2557 "scenario.lake_flooding");
2560 "scenario.handmade");
2563 "scenario.allow_ai_type_fallback");
2564
2567 "scenario.ruleset_locked");
2568
2570 "scenario.datafile");
2571 if (buf[0] != '\0') {
2573 }
2574
2575 sg_failure_ret(loading->server_state == S_S_INITIAL
2576 || (loading->server_state == S_S_RUNNING
2577 && game.scenario.players),
2578 "Invalid scenario definition (server state '%s' and "
2579 "players are %s).",
2580 server_states_name(loading->server_state),
2581 game.scenario.players ? "saved" : "not saved");
2582}
2583
2584/************************************************************************/
2588{
2589 struct entry *mod_entry;
2590 int game_version;
2591
2592 /* Check status and return if not OK (sg_success FALSE). */
2593 sg_check_ret();
2594
2595 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2596#ifdef EMERGENCY_VERSION
2598#endif /* EMERGENCY_VERSION */
2599 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2600
2601 if (!saving->scenario || !game.scenario.is_scenario) {
2602 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2603 return;
2604 }
2605
2606 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2607
2608 /* Name is mandatory to the level that is saved even if empty. */
2609 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2611
2612 /* Authors list is saved only if it exist */
2613 if (game.scenario.authors[0] != '\0') {
2615 "scenario.authors");
2617 }
2618
2619 /* Description is saved only if it exist */
2620 if (game.scenario_desc.description[0] != '\0') {
2622 "scenario.description");
2624 }
2625
2626 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2627 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2629 "scenario.startpos_nations");
2632 "scenario.prevent_new_cities");
2633 }
2635 "scenario.lake_flooding");
2636 if (game.scenario.handmade) {
2638 "scenario.handmade");
2639 }
2642 "scenario.allow_ai_type_fallback");
2643 }
2644
2645 if (game.scenario.datafile[0] != '\0') {
2647 "scenario.datafile");
2648 }
2650 "scenario.ruleset_locked");
2651 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2653 "scenario.ruleset_caps");
2654 }
2655}
2656
2657/* =======================================================================
2658 * Load / save game settings.
2659 * ======================================================================= */
2660
2661/************************************************************************/
2665{
2666 /* Check status and return if not OK (sg_success FALSE). */
2667 sg_check_ret();
2668
2669 settings_game_load(loading->file, "settings");
2670
2671 /* Save current status of fogofwar. */
2673
2674 /* Add all compatibility settings here. */
2675}
2676
2677/************************************************************************/
2681{
2683
2684 /* Check status and return if not OK (sg_success FALSE). */
2685 sg_check_ret();
2686
2687 if (saving->scenario) {
2688 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2689 }
2690
2691 settings_game_save(saving->file, "settings");
2692 /* Restore real map generator. */
2694
2695 /* Add all compatibility settings here. */
2696}
2697
2698
2699/************************************************************************/
2703{
2704 struct city *pcity;
2705 int i, j;
2706 size_t length, length2;
2707 int *city_count;
2709 "savefile.city_counters_order_size");
2710
2711 if (0==length) {
2712
2713 return;
2714 }
2715
2716 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2717
2718 sg_failure_ret(loading->counter.order != 0,
2719 "Failed to load counter's ruleset order: %s",
2720 secfile_error());
2721 sg_failure_ret(loading->counter.size = length,
2722 "Counter vector in savegame have bad size: %s",
2723 secfile_error());
2724
2725 int corder[length];
2726
2727 for (i = 0; i < length; i++) {
2728
2729 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2731 }
2732
2733 i = 0;
2734 while (NULL != (city_count =
2736 "counters.c%d", i))) {
2737
2738 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);
2739
2741
2742 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2743
2744 for (j = 0; j < length; j++) {
2745
2746 pcity->counter_values[corder[j]] = city_count[j+1];
2747 }
2748 i++;
2749 }
2750}
2751
2752/************************************************************************/
2756{
2757 /* Check status and return if not OK (sg_success FALSE). */
2758 sg_check_ret();
2759
2760 const char **countnames;
2761 int *countvalues;
2762 int i, j, count;
2763
2765
2766 secfile_insert_int(saving->file, count,
2767 "savefile.city_counters_order_size");
2768
2769 if (0 == count) {
2770
2771 return;
2772 }
2773
2774 countnames = fc_calloc(count, sizeof(*countnames));
2775 for (j = 0; j < count; j++) {
2777 }
2778
2780 "savefile.city_counters_order_vector");
2781
2783
2784 // Saving city's counters
2785
2786 j = 0;
2787 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2788
2790
2791 city_list_iterate(_pplayer->cities, pcity) {
2792
2793 countvalues[0] = pcity->id;
2794 for (i = 0; i < count; ++i) {
2795
2796 countvalues[i+1] = pcity->counter_values[i];
2797 }
2798
2799 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2800 ++j;
2803
2805}
2806
2807/* =======================================================================
2808 * Load / save the main map.
2809 * ======================================================================= */
2810
2811/************************************************************************/
2814static void sg_load_map(struct loaddata *loading)
2815{
2816 /* Check status and return if not OK (sg_success FALSE). */
2817 sg_check_ret();
2818
2819 /* This defaults to TRUE even if map has not been generated.
2820 * We rely on that
2821 * 1) scenario maps have it explicitly right.
2822 * 2) when map is actually generated, it re-initialize this to FALSE. */
2824 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2825
2827 "map.altitude"),
2828 "%s", secfile_error());
2829
2831 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2832
2834
2835 /* Savegame may have stored random_seed for documentation purposes only,
2836 * but we want to keep it for resaving. */
2838 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2839
2840 if (S_S_INITIAL == loading->server_state
2842 /* Generator MAPGEN_SCENARIO is used;
2843 * this map was done with the map editor. */
2844
2845 /* Load tiles. */
2849
2850 /* Nothing more needed for a scenario. */
2851 secfile_entry_ignore(loading->file, "game.save_known");
2852
2853 return;
2854 }
2855
2856 if (S_S_INITIAL == loading->server_state) {
2857 /* Nothing more to do if it is not a scenario but in initial state. */
2858 return;
2859 }
2860
2862 if (wld.map.altitude_info) {
2864 }
2870}
2871
2872/************************************************************************/
2875static void sg_save_map(struct savedata *saving)
2876{
2877 /* Check status and return if not OK (sg_success FALSE). */
2878 sg_check_ret();
2879
2880 if (map_is_empty()) {
2881 /* No map. */
2882 return;
2883 }
2884
2885 if (saving->scenario) {
2887 "map.have_huts");
2889 "map.have_resources");
2890 } else {
2891 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2892 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2893 }
2894
2895 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2896
2897 /* For debugging purposes only.
2898 * Do not save it if it's 0 (not known);
2899 * this confuses people reading this 'document' less than
2900 * saving 0. */
2901 if (wld.map.server.seed != 0) {
2903 "map.random_seed");
2904 }
2905
2907 if (wld.map.altitude_info) {
2909 }
2915}
2916
2917/************************************************************************/
2921{
2922 /* Check status and return if not OK (sg_success FALSE). */
2923 sg_check_ret();
2924
2925 /* Initialize the map for the current topology. 'map.xsize' and
2926 * 'map.ysize' must be set. */
2928
2929 /* Allocate map. */
2931
2932 /* get the terrain type */
2933 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2934 "map.t%04d");
2936
2937 /* Check for special tile sprites. */
2938 whole_map_iterate(&(wld.map), ptile) {
2939 const char *spec_sprite;
2940 const char *label;
2941 int nat_x, nat_y;
2942
2944 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2945 nat_x, nat_y);
2946 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2947 nat_x, nat_y);
2948 if (NULL != ptile->spec_sprite) {
2949 ptile->spec_sprite = fc_strdup(spec_sprite);
2950 }
2951 if (label != NULL) {
2952 tile_set_label(ptile, label);
2953 }
2955}
2956
2957/************************************************************************/
2961{
2962 /* Check status and return if not OK (sg_success FALSE). */
2963 sg_check_ret();
2964
2965 /* Save the terrain type. */
2966 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2967 "map.t%04d");
2968
2969 /* Save special tile sprites. */
2970 whole_map_iterate(&(wld.map), ptile) {
2971 int nat_x, nat_y;
2972
2974 if (ptile->spec_sprite) {
2975 secfile_insert_str(saving->file, ptile->spec_sprite,
2976 "map.spec_sprite_%d_%d", nat_x, nat_y);
2977 }
2978 if (ptile->label != NULL) {
2979 secfile_insert_str(saving->file, ptile->label,
2980 "map.label_%d_%d", nat_x, nat_y);
2981 }
2983}
2984
2985/************************************************************************/
2989{
2990 int y;
2991
2992 /* Check status and return if not OK (sg_success FALSE). */
2993 sg_check_ret();
2994
2995 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
2996 const char *buffer = secfile_lookup_str(loading->file,
2997 "map.alt%04d", y);
2998 const char *ptr = buffer;
2999 int x;
3000
3001 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3002
3003 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3004 char token[TOKEN_SIZE];
3005 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3006 int number;
3007
3008 scanin(&ptr, ",", token, sizeof(token));
3009 sg_failure_ret(token[0] != '\0',
3010 "Map size not correct (map.alt%d).", y);
3011 sg_failure_ret(str_to_int(token, &number),
3012 "Got map alt %s in (%d, %d).", token, x, y);
3013 ptile->altitude = number;
3014 }
3015 }
3016}
3017
3018/************************************************************************/
3022{
3023 int y;
3024
3025 /* Check status and return if not OK (sg_success FALSE). */
3026 sg_check_ret();
3027
3028 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3030 int x;
3031
3032 line[0] = '\0';
3033 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3034 char token[TOKEN_SIZE];
3035 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3036
3037 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3038
3039 strcat(line, token);
3040 if (x + 1 < MAP_NATIVE_WIDTH) {
3041 strcat(line, ",");
3042 }
3043 }
3044
3045 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3046 }
3047}
3048
3049/************************************************************************/
3053{
3054 /* Check status and return if not OK (sg_success FALSE). */
3055 sg_check_ret();
3056
3057 /* Load extras. */
3058 halfbyte_iterate_extras(j, loading->extra.size) {
3059 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3060 loading->extra.order + 4 * j),
3061 loading->file, "map.e%02d_%04d", j);
3063
3064 if (S_S_INITIAL != loading->server_state
3067 whole_map_iterate(&(wld.map), ptile) {
3069 if (tile_has_extra(ptile, pres)) {
3070 tile_set_resource(ptile, pres);
3071
3072 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3073 BV_CLR(ptile->extras, extra_index(pres));
3074 }
3075 }
3078 }
3079}
3080
3081/************************************************************************/
3085{
3086 /* Check status and return if not OK (sg_success FALSE). */
3087 sg_check_ret();
3088
3089 /* Save extras. */
3091 int mod[4];
3092 int l;
3093
3094 for (l = 0; l < 4; l++) {
3095 if (4 * j + 1 > game.control.num_extra_types) {
3096 mod[l] = -1;
3097 } else {
3098 mod[l] = 4 * j + l;
3099 }
3100 }
3101 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3102 saving->file, "map.e%02d_%04d", j);
3104}
3105
3106/************************************************************************/
3111{
3112 struct nation_type *pnation;
3113 struct startpos *psp;
3114 struct tile *ptile;
3115 const char SEPARATOR = '#';
3116 const char *nation_names;
3117 int nat_x, nat_y;
3118 bool exclude;
3119 int i, startpos_count;
3120
3121 /* Check status and return if not OK (sg_success FALSE). */
3122 sg_check_ret();
3123
3125 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3126
3127 if (0 == startpos_count) {
3128 /* Nothing to do. */
3129 return;
3130 }
3131
3132 for (i = 0; i < startpos_count; i++) {
3133 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3134 || !secfile_lookup_int(loading->file, &nat_y,
3135 "map.startpos%d.y", i)) {
3136 log_sg("Warning: Undefined coordinates for startpos %d", i);
3137 continue;
3138 }
3139
3140 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3141 if (NULL == ptile) {
3142 log_error("Start position native coordinates (%d, %d) do not exist "
3143 "in this map. Skipping...", nat_x, nat_y);
3144 continue;
3145 }
3146
3147 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3148 "map.startpos%d.exclude", i);
3149
3150 psp = map_startpos_new(ptile);
3151
3153 "map.startpos%d.nations", i);
3154 if (NULL != nation_names && '\0' != nation_names[0]) {
3155 const size_t size = strlen(nation_names) + 1;
3156 char buf[size], *start, *end;
3157
3159 for (start = buf - 1; NULL != start; start = end) {
3160 start++;
3161 if ((end = strchr(start, SEPARATOR))) {
3162 *end = '\0';
3163 }
3164
3165 pnation = nation_by_rule_name(start);
3166 if (NO_NATION_SELECTED != pnation) {
3167 if (exclude) {
3168 startpos_disallow(psp, pnation);
3169 } else {
3170 startpos_allow(psp, pnation);
3171 }
3172 } else {
3173 log_verbose("Missing nation \"%s\".", start);
3174 }
3175 }
3176 }
3177 }
3178
3179 if (0 < map_startpos_count()
3180 && loading->server_state == S_S_INITIAL
3182 log_verbose("Number of starts (%d) are lower than rules.max_players "
3183 "(%d), lowering rules.max_players.",
3186 }
3187
3188 /* Re-initialize nation availability in light of start positions.
3189 * This has to be after loading [scenario] and [map].startpos and
3190 * before we seek nations for players. */
3192}
3193
3194/************************************************************************/
3198{
3199 struct tile *ptile;
3200 const char SEPARATOR = '#';
3201 int i = 0;
3202
3203 /* Check status and return if not OK (sg_success FALSE). */
3204 sg_check_ret();
3205
3207 return;
3208 }
3209
3211 "map.startpos_count");
3212
3214 int nat_x, nat_y;
3215
3216 ptile = startpos_tile(psp);
3217
3219 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3220 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3221
3223 "map.startpos%d.exclude", i);
3224 if (startpos_allows_all(psp)) {
3225 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3226 } else {
3227 const struct nation_hash *nations = startpos_raw_nations(psp);
3229
3230 nation_names[0] = '\0';
3231 nation_hash_iterate(nations, pnation) {
3232 if ('\0' == nation_names[0]) {
3234 sizeof(nation_names));
3235 } else {
3237 "%c%s", SEPARATOR, nation_rule_name(pnation));
3238 }
3241 "map.startpos%d.nations", i);
3242 }
3243 i++;
3245
3247}
3248
3249/************************************************************************/
3253{
3254 int y;
3255 struct tile *claimer = NULL;
3256 struct extra_type *placing = NULL;
3257
3258 /* Check status and return if not OK (sg_success FALSE). */
3259 sg_check_ret();
3260
3261 if (game.info.is_new_game) {
3262 /* No owner/source information for a new game / scenario. */
3263 return;
3264 }
3265
3266 /* Owner, ownership source, and infra turns are stored as plain numbers */
3267 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3268 const char *buffer1 = secfile_lookup_str(loading->file,
3269 "map.owner%04d", y);
3270 const char *buffer2 = secfile_lookup_str(loading->file,
3271 "map.source%04d", y);
3272 const char *buffer3 = secfile_lookup_str(loading->file,
3273 "map.eowner%04d", y);
3275 NULL,
3276 "map.placing%04d", y);
3278 NULL,
3279 "map.infra_turns%04d", y);
3280 const char *ptr1 = buffer1;
3281 const char *ptr2 = buffer2;
3282 const char *ptr3 = buffer3;
3283 const char *ptr_placing = buffer_placing;
3284 const char *ptr_turns = buffer_turns;
3285 int x;
3286
3290
3291 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3292 char token1[TOKEN_SIZE];
3293 char token2[TOKEN_SIZE];
3294 char token3[TOKEN_SIZE];
3296 char token_turns[TOKEN_SIZE];
3297 struct player *owner = NULL;
3298 struct player *eowner = NULL;
3299 int turns;
3300 int number;
3301 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3302
3303 scanin(&ptr1, ",", token1, sizeof(token1));
3304 sg_failure_ret(token1[0] != '\0',
3305 "Map size not correct (map.owner%d).", y);
3306 if (strcmp(token1, "-") == 0) {
3307 owner = NULL;
3308 } else {
3310 "Got map owner %s in (%d, %d).", token1, x, y);
3311 owner = player_by_number(number);
3312 }
3313
3314 scanin(&ptr2, ",", token2, sizeof(token2));
3315 sg_failure_ret(token2[0] != '\0',
3316 "Map size not correct (map.source%d).", y);
3317 if (strcmp(token2, "-") == 0) {
3318 claimer = NULL;
3319 } else {
3321 "Got map source %s in (%d, %d).", token2, x, y);
3322 claimer = index_to_tile(&(wld.map), number);
3323 }
3324
3325 scanin(&ptr3, ",", token3, sizeof(token3));
3326 sg_failure_ret(token3[0] != '\0',
3327 "Map size not correct (map.eowner%d).", y);
3328 if (strcmp(token3, "-") == 0) {
3329 eowner = NULL;
3330 } else {
3332 "Got base owner %s in (%d, %d).", token3, x, y);
3333 eowner = player_by_number(number);
3334 }
3335
3336 if (ptr_placing != NULL) {
3338 sg_failure_ret(token_placing[0] != '\0',
3339 "Map size not correct (map.placing%d).", y);
3340 if (strcmp(token_placing, "-") == 0) {
3341 placing = NULL;
3342 } else {
3344 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3345 placing = extra_by_number(number);
3346 }
3347 } else {
3348 placing = NULL;
3349 }
3350
3351 if (ptr_turns != NULL) {
3352 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3353 sg_failure_ret(token_turns[0] != '\0',
3354 "Map size not correct (map.infra_turns%d).", y);
3356 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3357 turns = number;
3358 } else {
3359 turns = 1;
3360 }
3361
3363 tile_claim_bases(ptile, eowner);
3364 ptile->placing = placing;
3365 ptile->infra_turns = turns;
3366 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3367 }
3368 }
3369}
3370
3371/************************************************************************/
3375{
3376 int y;
3377
3378 /* Check status and return if not OK (sg_success FALSE). */
3379 sg_check_ret();
3380
3381 if (saving->scenario && !saving->save_players) {
3382 /* Nothing to do for a scenario without saved players. */
3383 return;
3384 }
3385
3386 /* Store owner and ownership source as plain numbers. */
3387 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3389 int x;
3390
3391 line[0] = '\0';
3392 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3393 char token[TOKEN_SIZE];
3394 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3395
3396 if (!saving->save_players || tile_owner(ptile) == NULL) {
3397 strcpy(token, "-");
3398 } else {
3399 fc_snprintf(token, sizeof(token), "%d",
3400 player_number(tile_owner(ptile)));
3401 }
3402 strcat(line, token);
3403 if (x + 1 < MAP_NATIVE_WIDTH) {
3404 strcat(line, ",");
3405 }
3406 }
3407
3408 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3409 }
3410
3411 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3413 int x;
3414
3415 line[0] = '\0';
3416 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3417 char token[TOKEN_SIZE];
3418 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3419
3420 if (ptile->claimer == NULL) {
3421 strcpy(token, "-");
3422 } else {
3423 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3424 }
3425 strcat(line, token);
3426 if (x + 1 < MAP_NATIVE_WIDTH) {
3427 strcat(line, ",");
3428 }
3429 }
3430
3431 secfile_insert_str(saving->file, line, "map.source%04d", y);
3432 }
3433
3434 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3436 int x;
3437
3438 line[0] = '\0';
3439 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3440 char token[TOKEN_SIZE];
3441 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3442
3443 if (!saving->save_players || extra_owner(ptile) == NULL) {
3444 strcpy(token, "-");
3445 } else {
3446 fc_snprintf(token, sizeof(token), "%d",
3447 player_number(extra_owner(ptile)));
3448 }
3449 strcat(line, token);
3450 if (x + 1 < MAP_NATIVE_WIDTH) {
3451 strcat(line, ",");
3452 }
3453 }
3454
3455 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3456 }
3457
3458 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3460 int x;
3461
3462 line[0] = '\0';
3463 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3464 char token[TOKEN_SIZE];
3465 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3466
3467 if (ptile->placing == NULL) {
3468 strcpy(token, "-");
3469 } else {
3470 fc_snprintf(token, sizeof(token), "%d",
3471 extra_number(ptile->placing));
3472 }
3473 strcat(line, token);
3474 if (x + 1 < MAP_NATIVE_WIDTH) {
3475 strcat(line, ",");
3476 }
3477 }
3478
3479 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3480 }
3481
3482 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3484 int x;
3485
3486 line[0] = '\0';
3487 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3488 char token[TOKEN_SIZE];
3489 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3490
3491 if (ptile->placing != NULL) {
3492 fc_snprintf(token, sizeof(token), "%d",
3493 ptile->infra_turns);
3494 } else {
3495 fc_snprintf(token, sizeof(token), "0");
3496 }
3497 strcat(line, token);
3498 if (x + 1 < MAP_NATIVE_WIDTH) {
3499 strcat(line, ",");
3500 }
3501 }
3502
3503 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3504 }
3505}
3506
3507/************************************************************************/
3511{
3512 int x, y;
3513
3514 /* Check status and return if not OK (sg_success FALSE). */
3515 sg_check_ret();
3516
3517 sg_failure_ret(loading->worked_tiles == NULL,
3518 "City worked map not loaded!");
3519
3520 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3521 sizeof(*loading->worked_tiles));
3522
3523 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3524 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3525 y);
3526 const char *ptr = buffer;
3527
3528 sg_failure_ret(NULL != buffer,
3529 "Savegame corrupt - map line %d not found.", y);
3530 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3531 char token[TOKEN_SIZE];
3532 int number;
3533 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3534
3535 scanin(&ptr, ",", token, sizeof(token));
3536 sg_failure_ret('\0' != token[0],
3537 "Savegame corrupt - map size not correct.");
3538 if (strcmp(token, "-") == 0) {
3539 number = -1;
3540 } else {
3541 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3542 "Savegame corrupt - got tile worked by city "
3543 "id=%s in (%d, %d).", token, x, y);
3544 }
3545
3546 loading->worked_tiles[ptile->index] = number;
3547 }
3548 }
3549}
3550
3551/************************************************************************/
3555{
3556 int x, y;
3557
3558 /* Check status and return if not OK (sg_success FALSE). */
3559 sg_check_ret();
3560
3561 if (saving->scenario && !saving->save_players) {
3562 /* Nothing to do for a scenario without saved players. */
3563 return;
3564 }
3565
3566 /* Additionally save the tiles worked by the cities */
3567 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3569
3570 line[0] = '\0';
3571 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3572 char token[TOKEN_SIZE];
3573 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3574 struct city *pcity = tile_worked(ptile);
3575
3576 if (pcity == NULL) {
3577 strcpy(token, "-");
3578 } else {
3579 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3580 }
3581 strcat(line, token);
3582 if (x < MAP_NATIVE_WIDTH) {
3583 strcat(line, ",");
3584 }
3585 }
3586 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3587 }
3588}
3589
3590/************************************************************************/
3594{
3595 /* Check status and return if not OK (sg_success FALSE). */
3596 sg_check_ret();
3597
3598 players_iterate(pplayer) {
3599 /* Allocate player private map here; it is needed in different modules
3600 * besides this one ((i.e. sg_load_player_*()). */
3601 player_map_init(pplayer);
3603
3605 "game.save_known")) {
3606 int lines = player_slot_max_used_number() / 32 + 1;
3607 int j, p, l, i;
3608 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3609
3610 for (l = 0; l < lines; l++) {
3611 for (j = 0; j < 8; j++) {
3612 for (i = 0; i < 4; i++) {
3613 /* Only bother trying to load the map for this halfbyte if at least
3614 * one of the corresponding player slots is in use. */
3615 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3616 LOAD_MAP_CHAR(ch, ptile,
3617 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3618 |= ascii_hex2bin(ch, j),
3619 loading->file, "map.k%02d_%04d", l * 8 + j);
3620 break;
3621 }
3622 }
3623 }
3624 }
3625
3626 players_iterate(pplayer) {
3627 dbv_clr_all(&pplayer->tile_known);
3629
3630 /* HACK: we read the known data from hex into 32-bit integers, and
3631 * now we convert it to the known tile data of each player. */
3632 whole_map_iterate(&(wld.map), ptile) {
3633 players_iterate(pplayer) {
3634 p = player_index(pplayer);
3635 l = player_index(pplayer) / 32;
3636
3637 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3638 map_set_known(ptile, pplayer);
3639 }
3642
3643 FC_FREE(known);
3644 }
3645}
3646
3647/************************************************************************/
3651{
3652 /* Check status and return if not OK (sg_success FALSE). */
3653 sg_check_ret();
3654
3655 if (!saving->save_players) {
3656 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3657 return;
3658 } else {
3659 int lines = player_slot_max_used_number() / 32 + 1;
3660
3662 "game.save_known");
3664 int j, p, l, i;
3665 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3666
3667 /* HACK: we convert the data into a 32-bit integer, and then save it as
3668 * hex. */
3669
3670 whole_map_iterate(&(wld.map), ptile) {
3671 players_iterate(pplayer) {
3672 if (map_is_known(ptile, pplayer)) {
3673 p = player_index(pplayer);
3674 l = p / 32;
3675 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3676 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3677 }
3680
3681 for (l = 0; l < lines; l++) {
3682 for (j = 0; j < 8; j++) {
3683 for (i = 0; i < 4; i++) {
3684 /* Only bother saving the map for this halfbyte if at least one
3685 * of the corresponding player slots is in use */
3686 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3687 /* put 4-bit segments of the 32-bit "known" field */
3689 + tile_index(ptile)], j),
3690 saving->file, "map.k%02d_%04d", l * 8 + j);
3691 break;
3692 }
3693 }
3694 }
3695 }
3696
3697 FC_FREE(known);
3698 }
3699 }
3700}
3701
3702/* =======================================================================
3703 * Load / save player data.
3704 *
3705 * This is split into two parts as some data can only be loaded if the
3706 * number of players is known and the corresponding player slots are
3707 * defined.
3708 * ======================================================================= */
3709
3710/************************************************************************/
3714{
3715 int i, k, nplayers;
3716 const char *str;
3717 bool shuffle_loaded = TRUE;
3718
3719 /* Check status and return if not OK (sg_success FALSE). */
3720 sg_check_ret();
3721
3722 if (S_S_INITIAL == loading->server_state
3723 || game.info.is_new_game) {
3724 /* Nothing more to do. */
3725 return;
3726 }
3727
3728 /* Load destroyed wonders: */
3730 "players.destroyed_wonders");
3731 sg_failure_ret(str != NULL, "%s", secfile_error());
3732 sg_failure_ret(strlen(str) == loading->improvement.size,
3733 "Invalid length for 'players.destroyed_wonders' ("
3734 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3735 strlen(str), loading->improvement.size);
3736 for (k = 0; k < loading->improvement.size; k++) {
3737 sg_failure_ret(str[k] == '1' || str[k] == '0',
3738 "Undefined value '%c' within "
3739 "'players.destroyed_wonders'.", str[k]);
3740
3741 if (str[k] == '1') {
3742 struct impr_type *pimprove =
3743 improvement_by_rule_name(loading->improvement.order[k]);
3744 if (pimprove) {
3747 }
3748 }
3749 }
3750
3751 server.identity_number
3752 = secfile_lookup_int_default(loading->file, server.identity_number,
3753 "players.identity_number_used");
3754
3755 /* First remove all defined players. */
3756 players_iterate(pplayer) {
3757 server_remove_player(pplayer);
3759
3760 /* Now, load the players from the savefile. */
3761 player_slots_iterate(pslot) {
3762 struct player *pplayer;
3763 struct rgbcolor *prgbcolor = NULL;
3764 int pslot_id = player_slot_index(pslot);
3765
3766 if (NULL == secfile_section_lookup(loading->file, "player%d",
3767 pslot_id)) {
3768 continue;
3769 }
3770
3771 /* Get player AI type. */
3772 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3773 player_slot_index(pslot));
3774 sg_failure_ret(str != NULL, "%s", secfile_error());
3775
3776 /* Get player color */
3777 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3778 pslot_id)) {
3779 if (game_was_started()) {
3780 log_sg("Game has started, yet player %d has no color defined.",
3781 pslot_id);
3782 /* This will be fixed up later */
3783 } else {
3784 log_verbose("No color defined for player %d.", pslot_id);
3785 /* Colors will be assigned on game start, or at end of savefile
3786 * loading if game has already started */
3787 }
3788 }
3789
3790 /* Create player. */
3791 pplayer = server_create_player(player_slot_index(pslot), str,
3792 prgbcolor,
3795 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3796
3797 server_player_init(pplayer, FALSE, FALSE);
3798
3799 /* Free the color definition. */
3801
3802 /* Multipliers (policies) */
3803
3804 /* First initialise player values with ruleset defaults; this will
3805 * cover any in the ruleset not known when the savefile was created. */
3806 multipliers_iterate(pmul) {
3807 pplayer->multipliers[multiplier_index(pmul)].value
3808 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3810
3811 /* Now override with any values from the savefile. */
3812 for (k = 0; k < loading->multiplier.size; k++) {
3813 const struct multiplier *pmul = loading->multiplier.order[k];
3814
3815 if (pmul) {
3817 int val =
3819 "player%d.multiplier%d.val",
3820 player_slot_index(pslot), k);
3821 int rval = (((CLIP(pmul->start, val, pmul->stop)
3822 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3823
3824 if (rval != val) {
3825 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3826 "was %d, clamped to %d", pslot_id,
3827 multiplier_rule_name(pmul), val, rval);
3828 }
3829 pplayer->multipliers[idx].value = rval;
3830
3831 val =
3833 pplayer->multipliers[idx].value,
3834 "player%d.multiplier%d.target",
3835 player_slot_index(pslot), k);
3836 rval = (((CLIP(pmul->start, val, pmul->stop)
3837 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3838
3839 if (rval != val) {
3840 log_verbose("Player %d had illegal value for multiplier_target "
3841 " \"%s\": was %d, clamped to %d", pslot_id,
3842 multiplier_rule_name(pmul), val, rval);
3843 }
3844 pplayer->multipliers[idx].target = rval;
3845
3846 pplayer->multipliers[idx].changed
3848 "player%d.multiplier%d.changed",
3849 player_slot_index(pslot), k);
3850 } /* else silently discard multiplier not in current ruleset */
3851 }
3852
3853 /* Must be loaded before tile owner is set. */
3854 pplayer->server.border_vision =
3856 "player%d.border_vision",
3857 player_slot_index(pslot));
3858
3860 "player%d.autoselect_weight",
3861 pslot_id);
3863
3864 /* check number of players */
3865 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3866 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3867 "(%d) from the loaded game does not match the number of "
3868 "players present (%d).", nplayers, player_count());
3869
3870 /* Load team information. */
3871 players_iterate(pplayer) {
3872 int team;
3873 struct team_slot *tslot = NULL;
3874
3876 "player%d.team_no",
3877 player_number(pplayer))
3879 "Invalid team definition for player %s (nb %d).",
3880 player_name(pplayer), player_number(pplayer));
3881 /* Should never fail when slot given is not nullptr */
3882 team_add_player(pplayer, team_new(tslot));
3884
3885 /* Loading the shuffle list is quite complex. At the time of saving the
3886 * shuffle data is saved as
3887 * shuffled_player_<number> = player_slot_id
3888 * where number is an increasing number and player_slot_id is a number
3889 * between 0 and the maximum number of player slots. Now we have to create
3890 * a list
3891 * shuffler_players[number] = player_slot_id
3892 * where all player slot IDs are used exactly one time. The code below
3893 * handles this ... */
3894 if (secfile_lookup_int_default(loading->file, -1,
3895 "players.shuffled_player_%d", 0) >= 0) {
3896 int slots = player_slot_count();
3897 int plrcount = player_count();
3900
3901 for (i = 0; i < slots; i++) {
3902 /* Array to save used numbers. */
3904 /* List of all player IDs (needed for set_shuffled_players()). It is
3905 * initialised with the value -1 to indicate that no value is set. */
3906 shuffled_players[i] = -1;
3907 }
3908
3909 /* Load shuffled player list. */
3910 for (i = 0; i < plrcount; i++) {
3911 int shuffle
3913 "players.shuffled_player_%d", i);
3914
3915 if (shuffle == -1) {
3916 log_sg("Missing player shuffle information (index %d) "
3917 "- reshuffle player list!", i);
3919 break;
3920 } else if (shuffled_player_set[shuffle]) {
3921 log_sg("Player shuffle %d used two times "
3922 "- reshuffle player list!", shuffle);
3924 break;
3925 }
3926 /* Set this ID as used. */
3928
3929 /* Save the player ID in the shuffle list. */
3931 }
3932
3933 if (shuffle_loaded) {
3934 /* Insert missing numbers. */
3935 int shuffle_index = plrcount;
3936
3937 for (i = 0; i < slots; i++) {
3938 if (!shuffled_player_set[i]) {
3940 }
3941
3942 /* shuffle_index must not grow higher than size of shuffled_players. */
3944 "Invalid player shuffle data!");
3945 }
3946
3947#ifdef FREECIV_DEBUG
3948 log_debug("[load shuffle] player_count() = %d", player_count());
3949 player_slots_iterate(pslot) {
3950 int plrid = player_slot_index(pslot);
3951
3952 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3954 shuffled_player_set[plrid] ? "is used" : "-");
3956#endif /* FREECIV_DEBUG */
3957
3958 /* Set shuffle list from savegame. */
3960 }
3961 }
3962
3963 if (!shuffle_loaded) {
3964 /* No shuffled players included or error loading them, so shuffle them
3965 * (this may include scenarios). */
3967 }
3968}
3969
3970/************************************************************************/
3974{
3975 /* Check status and return if not OK (sg_success FALSE). */
3976 sg_check_ret();
3977
3978 if (game.info.is_new_game) {
3979 /* Nothing to do. */
3980 return;
3981 }
3982
3983 players_iterate(pplayer) {
3984 sg_load_player_main(loading, pplayer);
3986 sg_load_player_units(loading, pplayer);
3988
3989 /* Check the success of the functions above. */
3990 sg_check_ret();
3991
3992 /* Print out some information */
3993 if (is_ai(pplayer)) {
3994 log_normal(_("%s has been added as %s level AI-controlled player "
3995 "(%s)."), player_name(pplayer),
3996 ai_level_translated_name(pplayer->ai_common.skill_level),
3997 ai_name(pplayer->ai));
3998 } else {
3999 log_normal(_("%s has been added as human player."),
4000 player_name(pplayer));
4001 }
4003
4004 /* Also load the transport status of the units here. It must be a special
4005 * case as all units must be known (unit on an allied transporter). */
4006 players_iterate(pplayer) {
4007 /* Load unit transport status. */
4010
4011 /* Savegame may contain nation assignments that are incompatible with the
4012 * current nationset. Ensure they are compatible, one way or another. */
4014
4015 /* Some players may have invalid nations in the ruleset. Once all players
4016 * are loaded, pick one of the remaining nations for them. */
4017 players_iterate(pplayer) {
4018 if (pplayer->nation == NO_NATION_SELECTED) {
4021 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4022 log_sg(_("%s had invalid nation; changing to %s."),
4023 player_name(pplayer), nation_plural_for_player(pplayer));
4024
4025 ai_traits_init(pplayer);
4026 }
4028
4029 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4032 if (pplayers_allied(plr, aplayer)) {
4034 DS_ALLIANCE);
4035
4038 log_sg("Illegal alliance structure detected: "
4039 "%s alliance to %s reduced to peace treaty.",
4044 }
4045 }
4048
4049 /* Update cached city illness. This can depend on trade routes,
4050 * so can't be calculated until all players have been loaded. */
4051 if (game.info.illness_on) {
4053 pcity->server.illness
4055 &(pcity->illness_trade), NULL);
4057 }
4058
4059 /* Update all city information. This must come after all cities are
4060 * loaded (in player_load) but before player (dumb) cities are loaded
4061 * in player_load_vision(). */
4062 players_iterate(plr) {
4063 city_list_iterate(plr->cities, pcity) {
4066 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4069
4070 /* Since the cities must be placed on the map to put them on the
4071 player map we do this afterwards */
4072 players_iterate(pplayer) {
4074 /* Check the success of the function above. */
4075 sg_check_ret();
4077
4078 /* Check shared vision and tiles. */
4079 players_iterate(pplayer) {
4080 BV_CLR_ALL(pplayer->gives_shared_vision);
4081 BV_CLR_ALL(pplayer->gives_shared_tiles);
4082 BV_CLR_ALL(pplayer->server.really_gives_vision);
4084
4085 /* Set up shared vision... */
4086 players_iterate(pplayer) {
4087 int plr1 = player_index(pplayer);
4088
4090 int plr2 = player_index(pplayer2);
4091
4093 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4094 give_shared_vision(pplayer, pplayer2);
4095 }
4097 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4098 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4099 }
4102
4103 /* ...and check it */
4106 /* TODO: Is there a good reason player is not marked as
4107 * giving shared vision to themselves -> really_gives_vision()
4108 * returning FALSE when pplayer1 == pplayer2 */
4109 if (pplayer1 != pplayer2
4112 sg_regr(3000900,
4113 _("%s did not give shared vision to team member %s."),
4116 }
4118 sg_regr(3000900,
4119 _("%s did not give shared vision to team member %s."),
4122 }
4123 }
4126
4129
4130 /* All vision is ready; this calls city_thaw_workers_queue(). */
4132
4133 /* Make sure everything is consistent. */
4134 players_iterate(pplayer) {
4135 unit_list_iterate(pplayer->units, punit) {
4137 struct tile *ptile = unit_tile(punit);
4138
4139 log_sg("%s doing illegal activity in savegame!",
4141 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4145 : "missing",
4146 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4148 }
4151
4154 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4156
4157 /* Player colors are always needed once game has started. Pre-2.4 savegames
4158 * lack them. This cannot be in compatibility conversion layer as we need
4159 * all the player data available to be able to assign best colors. */
4160 if (game_was_started()) {
4162 }
4163}
4164
4165/************************************************************************/
4168static void sg_save_players(struct savedata *saving)
4169{
4170 /* Check status and return if not OK (sg_success FALSE). */
4171 sg_check_ret();
4172
4173 if ((saving->scenario && !saving->save_players)
4174 || !game_was_started()) {
4175 /* Nothing to do for a scenario without saved players or a game in
4176 * INITIAL state. */
4177 return;
4178 }
4179
4180 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4181
4182 /* Save destroyed wonders as bitvector. Note that improvement order
4183 * is saved in 'savefile.improvement.order'. */
4184 {
4185 char destroyed[B_LAST+1];
4186
4187 improvement_iterate(pimprove) {
4188 if (is_great_wonder(pimprove)
4189 && great_wonder_is_destroyed(pimprove)) {
4190 destroyed[improvement_index(pimprove)] = '1';
4191 } else {
4192 destroyed[improvement_index(pimprove)] = '0';
4193 }
4195 destroyed[improvement_count()] = '\0';
4197 "players.destroyed_wonders");
4198 }
4199
4200 secfile_insert_int(saving->file, server.identity_number,
4201 "players.identity_number_used");
4202
4203 /* Save player order. */
4204 {
4205 int i = 0;
4206 shuffled_players_iterate(pplayer) {
4207 secfile_insert_int(saving->file, player_number(pplayer),
4208 "players.shuffled_player_%d", i);
4209 i++;
4211 }
4212
4213 /* Sort units. */
4215
4216 /* Save players. */
4217 players_iterate(pplayer) {
4218 sg_save_player_main(saving, pplayer);
4219 sg_save_player_cities(saving, pplayer);
4220 sg_save_player_units(saving, pplayer);
4222 sg_save_player_vision(saving, pplayer);
4224}
4225
4226/************************************************************************/
4230 struct player *plr)
4231{
4232 const char **slist;
4233 int i, plrno = player_number(plr);
4234 const char *str;
4235 struct government *gov;
4236 const char *level;
4237 const char *barb_str;
4238 size_t nval;
4239 const char *kind;
4240
4241 /* Check status and return if not OK (sg_success FALSE). */
4242 sg_check_ret();
4243
4244 /* Basic player data. */
4245 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4246 sg_failure_ret(str != NULL, "%s", secfile_error());
4248 sz_strlcpy(plr->username,
4250 "player%d.username", plrno));
4252 "player%d.unassigned_user", plrno),
4253 "%s", secfile_error());
4256 "player%d.orig_username", plrno));
4259 "player%d.ranked_username",
4260 plrno));
4262 "player%d.unassigned_ranked", plrno),
4263 "%s", secfile_error());
4265 "player%d.delegation_username",
4266 plrno);
4267 /* Defaults to no delegation. */
4268 if (strlen(str)) {
4270 }
4271
4272 /* Player flags */
4273 BV_CLR_ALL(plr->flags);
4274 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4275 for (i = 0; i < nval; i++) {
4276 const char *sval = slist[i];
4278
4279 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4280
4281 BV_SET(plr->flags, fid);
4282 }
4283 free(slist);
4284
4285 /* Nation */
4286 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4288 if (plr->nation != NULL) {
4289 ai_traits_init(plr);
4290 }
4291
4292 /* Government */
4293 str = secfile_lookup_str(loading->file, "player%d.government_name",
4294 plrno);
4296 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4297 plrno, str);
4298 plr->government = gov;
4299
4300 /* Target government */
4302 "player%d.target_government_name", plrno);
4303 if (str != NULL) {
4305 } else {
4306 plr->target_government = NULL;
4307 }
4310 "player%d.revolution_finishes", plrno);
4311
4312 /* Load diplomatic data (diplstate + embassy + vision).
4313 * Shared vision is loaded in sg_load_players(). */
4315 players_iterate(pplayer) {
4316 char buf[32];
4317 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4318 i = player_index(pplayer);
4319
4320 /* Load diplomatic status */
4321 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4322
4323 ds->type =
4325 diplstate_type, "%s.current", buf);
4326 ds->max_state =
4328 diplstate_type, "%s.closest", buf);
4329
4330 /* FIXME: If either party is barbarian, we cannot enforce below check */
4331#if 0
4332 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4333 sg_regr(3020000,
4334 "Player%d: War with player %d who has never been met. "
4335 "Reverted to No Contact state.", plrno, i);
4336 ds->type = DS_NO_CONTACT;
4337 }
4338#endif
4339
4340 if (valid_dst_closest(ds) != ds->max_state) {
4341 sg_regr(3020000,
4342 "Player%d: closest diplstate to player %d less than current. "
4343 "Updated.", plrno, i);
4344 ds->max_state = ds->type;
4345 }
4346
4347 ds->first_contact_turn =
4349 "%s.first_contact_turn", buf);
4350 ds->turns_left =
4351 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4352 ds->has_reason_to_cancel =
4354 "%s.has_reason_to_cancel", buf);
4355 ds->contact_turns_left =
4357 "%s.contact_turns_left", buf);
4358
4359 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4360 buf)) {
4361 BV_SET(plr->real_embassy, i);
4362 }
4363 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4364 * must be known. */
4366
4367 /* load ai data */
4369 char buf[32];
4370
4371 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4373
4375 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4376 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4378
4380 "player%d.adv.wonder_city",
4381 plrno);
4382
4383 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4384
4385 /* Some sane defaults */
4386 plr->ai_common.fuzzy = 0;
4387 plr->ai_common.expand = 100;
4388 plr->ai_common.science_cost = 100;
4389
4390
4392 "player%d.ai.level", plrno);
4393 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4394 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4396 } else {
4398 }
4399
4401 log_sg("Player%d: Invalid AI level \"%s\". "
4402 "Changed to \"%s\".", plrno, level,
4405 }
4406
4408 "player%d.ai.barb_type", plrno);
4410
4412 log_sg("Player%d: Invalid barbarian type \"%s\". "
4413 "Changed to \"None\".", plrno, barb_str);
4415 }
4416
4417 if (is_barbarian(plr)) {
4418 server.nbarbarians++;
4419 }
4420
4421 if (is_ai(plr)) {
4423 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4424 }
4425
4426 /* Load nation style. */
4427 {
4428 struct nation_style *style;
4429
4430 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4431
4432 sg_failure_ret(str != NULL, "%s", secfile_error());
4433 style = style_by_rule_name(str);
4434 if (style == NULL) {
4435 style = style_by_number(0);
4436 log_sg("Player%d: unsupported city_style_name \"%s\". "
4437 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4438 }
4439 plr->style = style;
4440 }
4441
4443 "player%d.idle_turns", plrno),
4444 "%s", secfile_error());
4445 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4446 if (sex_by_name(kind) == SEX_MALE) {
4447 plr->is_male = TRUE;
4448 } else {
4449 plr->is_male = FALSE;
4450 }
4452 "player%d.is_alive", plrno),
4453 "%s", secfile_error());
4455 "player%d.turns_alive", plrno),
4456 "%s", secfile_error());
4458 "player%d.last_war", plrno),
4459 "%s", secfile_error());
4461 "player%d.phase_done", plrno);
4463 "player%d.gold", plrno),
4464 "%s", secfile_error());
4466 "player%d.rates.tax", plrno),
4467 "%s", secfile_error());
4469 "player%d.rates.science", plrno),
4470 "%s", secfile_error());
4472 "player%d.rates.luxury", plrno),
4473 "%s", secfile_error());
4475 "player%d.infrapts",
4476 plrno);
4477 plr->server.bulbs_last_turn =
4479 "player%d.research.bulbs_last_turn", plrno);
4480
4481 /* Traits */
4482 if (plr->nation) {
4483 for (i = 0; i < loading->trait.size; i++) {
4484 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4485
4486 if (trait_is_valid(tr)) {
4487 int val;
4488
4489 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4490 plrno, i),
4491 "%s", secfile_error());
4492 plr->ai_common.traits[tr].val = val;
4493
4495 "player%d.trait%d.mod", plrno, i),
4496 "%s", secfile_error());
4497 plr->ai_common.traits[tr].mod = val;
4498 }
4499 }
4500 }
4501
4502 /* Achievements */
4503 {
4504 int count;
4505
4506 count = secfile_lookup_int_default(loading->file, -1,
4507 "player%d.achievement_count", plrno);
4508
4509 if (count > 0) {
4510 for (i = 0; i < count; i++) {
4511 const char *name;
4512 struct achievement *pach;
4513 bool first;
4514
4516 "player%d.achievement%d.name", plrno, i);
4518
4520 "Unknown achievement \"%s\".", name);
4521
4523 "player%d.achievement%d.first",
4524 plrno, i),
4525 "achievement error: %s", secfile_error());
4526
4527 sg_failure_ret(pach->first == NULL || !first,
4528 "Multiple players listed as first to get achievement \"%s\".",
4529 name);
4530
4531 BV_SET(pach->achievers, player_index(plr));
4532
4533 if (first) {
4534 pach->first = plr;
4535 }
4536 }
4537 }
4538 }
4539
4540 /* Player score. */
4541 plr->score.happy =
4543 "score%d.happy", plrno);
4544 plr->score.content =
4546 "score%d.content", plrno);
4547 plr->score.unhappy =
4549 "score%d.unhappy", plrno);
4550 plr->score.angry =
4552 "score%d.angry", plrno);
4553
4554 /* Make sure that the score about specialists in current ruleset that
4555 * were not present at saving time are set to zero. */
4557 plr->score.specialists[sp] = 0;
4559
4560 for (i = 0; i < loading->specialist.size; i++) {
4561 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4563 "score%d.specialists%d", plrno, i);
4564 }
4565
4566 plr->score.wonders =
4568 "score%d.wonders", plrno);
4569 plr->score.techs =
4571 "score%d.techs", plrno);
4572 plr->score.techout =
4574 "score%d.techout", plrno);
4575 plr->score.landarea =
4577 "score%d.landarea", plrno);
4578 plr->score.settledarea =
4580 "score%d.settledarea", plrno);
4581 plr->score.population =
4583 "score%d.population", plrno);
4584 plr->score.cities =
4586 "score%d.cities", plrno);
4587 plr->score.units =
4589 "score%d.units", plrno);
4590 plr->score.pollution =
4592 "score%d.pollution", plrno);
4593 plr->score.literacy =
4595 "score%d.literacy", plrno);
4596 plr->score.bnp =
4598 "score%d.bnp", plrno);
4599 plr->score.mfg =
4601 "score%d.mfg", plrno);
4602 plr->score.spaceship =
4604 "score%d.spaceship", plrno);
4605 plr->score.units_built =
4607 "score%d.units_built", plrno);
4608 plr->score.units_killed =
4610 "score%d.units_killed", plrno);
4611 plr->score.units_lost =
4613 "score%d.units_lost", plrno);
4614 plr->score.units_used =
4616 "score%d.units_used", plrno);
4617 plr->score.culture =
4619 "score%d.culture", plrno);
4620 plr->score.game =
4622 "score%d.total", plrno);
4623
4624 /* Load space ship data. */
4625 {
4626 struct player_spaceship *ship = &plr->spaceship;
4627 char prefix[32];
4628 const char *st;
4629 int ei;
4630
4631 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4634 &ei,
4635 "%s.state", prefix),
4636 "%s", secfile_error());
4637 ship->state = ei;
4638
4639 if (ship->state != SSHIP_NONE) {
4640 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4641 "%s.structurals", prefix),
4642 "%s", secfile_error());
4643 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4644 "%s.components", prefix),
4645 "%s", secfile_error());
4647 "%s.modules", prefix),
4648 "%s", secfile_error());
4650 "%s.fuel", prefix),
4651 "%s", secfile_error());
4652 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4653 "%s.propulsion", prefix),
4654 "%s", secfile_error());
4655 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4656 "%s.habitation", prefix),
4657 "%s", secfile_error());
4658 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4659 "%s.life_support", prefix),
4660 "%s", secfile_error());
4661 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4662 "%s.solar_panels", prefix),
4663 "%s", secfile_error());
4664
4665 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4666 sg_failure_ret(st != NULL, "%s", secfile_error())
4667 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4668 sg_failure_ret(st[i] == '1' || st[i] == '0',
4669 "Undefined value '%c' within '%s.structure'.", st[i],
4670 prefix)
4671
4672 if (!(st[i] == '0')) {
4673 BV_SET(ship->structure, i);
4674 }
4675 }
4676 if (ship->state >= SSHIP_LAUNCHED) {
4677 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4678 "%s.launch_year", prefix),
4679 "%s", secfile_error());
4680 }
4682 }
4683 }
4684
4685 /* Load lost wonder data. */
4686 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4687 /* If not present, probably an old savegame; nothing to be done */
4688 if (str != NULL) {
4689 int k;
4690
4691 sg_failure_ret(strlen(str) == loading->improvement.size,
4692 "Invalid length for 'player%d.lost_wonders' ("
4693 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4694 plrno, strlen(str), loading->improvement.size);
4695 for (k = 0; k < loading->improvement.size; k++) {
4696 sg_failure_ret(str[k] == '1' || str[k] == '0',
4697 "Undefined value '%c' within "
4698 "'player%d.lost_wonders'.", plrno, str[k]);
4699
4700 if (str[k] == '1') {
4701 struct impr_type *pimprove =
4702 improvement_by_rule_name(loading->improvement.order[k]);
4703 if (pimprove) {
4704 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4705 }
4706 }
4707 }
4708 }
4709
4710 plr->history =
4711 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4712 plr->server.huts =
4713 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4714}
4715
4716/************************************************************************/
4720 struct player *plr)
4721{
4722 int i, k, plrno = player_number(plr);
4723 struct player_spaceship *ship = &plr->spaceship;
4724 const char *flag_names[PLRF_COUNT];
4725 int set_count;
4726
4727 /* Check status and return if not OK (sg_success FALSE). */
4728 sg_check_ret();
4729
4730 set_count = 0;
4731 for (i = 0; i < PLRF_COUNT; i++) {
4732 if (player_has_flag(plr, i)) {
4734 }
4735 }
4736
4738 "player%d.flags", plrno);
4739
4740 secfile_insert_str(saving->file, ai_name(plr->ai),
4741 "player%d.ai_type", plrno);
4743 "player%d.name", plrno);
4745 "player%d.username", plrno);
4747 "player%d.unassigned_user", plrno);
4748 if (plr->rgb != NULL) {
4749 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4750 } else {
4751 /* Colorless players are ok in pregame */
4752 if (game_was_started()) {
4753 log_sg("Game has started, yet player %d has no color defined.", plrno);
4754 }
4755 }
4757 "player%d.ranked_username", plrno);
4759 "player%d.unassigned_ranked", plrno);
4761 "player%d.orig_username", plrno);
4764 : "",
4765 "player%d.delegation_username", plrno);
4767 "player%d.nation", plrno);
4768 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4769 "player%d.team_no", plrno);
4770
4773 "player%d.government_name", plrno);
4774
4775 if (plr->target_government) {
4778 "player%d.target_government_name", plrno);
4779 }
4780
4782 "player%d.style_by_name", plrno);
4783
4785 "player%d.idle_turns", plrno);
4786 if (plr->is_male) {
4788 "player%d.kind", plrno);
4789 } else {
4791 "player%d.kind", plrno);
4792 }
4794 "player%d.is_alive", plrno);
4796 "player%d.turns_alive", plrno);
4798 "player%d.last_war", plrno);
4800 "player%d.phase_done", plrno);
4801
4802 players_iterate(pplayer) {
4803 char buf[32];
4804 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4805
4806 i = player_index(pplayer);
4807
4808 /* save diplomatic state */
4809 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4810
4811 secfile_insert_enum(saving->file, ds->type,
4812 diplstate_type, "%s.current", buf);
4813 secfile_insert_enum(saving->file, ds->max_state,
4814 diplstate_type, "%s.closest", buf);
4815 secfile_insert_int(saving->file, ds->first_contact_turn,
4816 "%s.first_contact_turn", buf);
4817 secfile_insert_int(saving->file, ds->turns_left,
4818 "%s.turns_left", buf);
4819 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4820 "%s.has_reason_to_cancel", buf);
4821 secfile_insert_int(saving->file, ds->contact_turns_left,
4822 "%s.contact_turns_left", buf);
4824 "%s.embassy", buf);
4825 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4826 "%s.gives_shared_vision", buf);
4827 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4828 "%s.gives_shared_tiles", buf);
4830
4833 /* save ai data */
4835 "player%d.ai%d.love", plrno, i);
4836 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4838
4840 "player%d.adv.wonder_city", plrno);
4841
4842 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4843
4844 /* Multipliers (policies) */
4845 i = multiplier_count();
4846
4847 for (k = 0; k < i; k++) {
4849 "player%d.multiplier%d.val", plrno, k);
4851 "player%d.multiplier%d.target", plrno, k);
4853 "player%d.multiplier%d.changed", plrno, k);
4854 }
4855
4857 "player%d.ai.level", plrno);
4859 "player%d.ai.barb_type", plrno);
4861 "player%d.gold", plrno);
4863 "player%d.rates.tax", plrno);
4865 "player%d.rates.science", plrno);
4867 "player%d.rates.luxury", plrno);
4869 "player%d.infrapts", plrno);
4871 "player%d.research.bulbs_last_turn", plrno);
4872
4873 /* Save traits */
4874 {
4875 enum trait tr;
4876 int j;
4877
4878 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4880 "player%d.trait%d.val", plrno, j);
4882 "player%d.trait%d.mod", plrno, j);
4883 }
4884 }
4885
4886 /* Save achievements */
4887 {
4888 int j = 0;
4889
4891 if (achievement_player_has(pach, plr)) {
4893 "player%d.achievement%d.name", plrno, j);
4894 if (pach->first == plr) {
4896 "player%d.achievement%d.first", plrno, j);
4897 } else {
4899 "player%d.achievement%d.first", plrno, j);
4900 }
4901
4902 j++;
4903 }
4905
4906 secfile_insert_int(saving->file, j,
4907 "player%d.achievement_count", plrno);
4908 }
4909
4911 "player%d.revolution_finishes", plrno);
4912
4913 /* Player score */
4915 "score%d.happy", plrno);
4917 "score%d.content", plrno);
4919 "score%d.unhappy", plrno);
4921 "score%d.angry", plrno);
4924 "score%d.specialists%d", plrno, sp);
4927 "score%d.wonders", plrno);
4929 "score%d.techs", plrno);
4931 "score%d.techout", plrno);
4933 "score%d.landarea", plrno);
4935 "score%d.settledarea", plrno);
4937 "score%d.population", plrno);
4939 "score%d.cities", plrno);
4941 "score%d.units", plrno);
4943 "score%d.pollution", plrno);
4945 "score%d.literacy", plrno);
4946 secfile_insert_int(saving->file, plr->score.bnp,
4947 "score%d.bnp", plrno);
4948 secfile_insert_int(saving->file, plr->score.mfg,
4949 "score%d.mfg", plrno);
4951 "score%d.spaceship", plrno);
4953 "score%d.units_built", plrno);
4955 "score%d.units_killed", plrno);
4957 "score%d.units_lost", plrno);
4959 "score%d.units_used", plrno);
4961 "score%d.culture", plrno);
4962 secfile_insert_int(saving->file, plr->score.game,
4963 "score%d.total", plrno);
4964
4965 /* Save space ship status. */
4966 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4967 plrno);
4968 if (ship->state != SSHIP_NONE) {
4969 char buf[32];
4970 char st[NUM_SS_STRUCTURALS+1];
4971 int ssi;
4972
4973 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4974
4975 secfile_insert_int(saving->file, ship->structurals,
4976 "%s.structurals", buf);
4977 secfile_insert_int(saving->file, ship->components,
4978 "%s.components", buf);
4979 secfile_insert_int(saving->file, ship->modules,
4980 "%s.modules", buf);
4981 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4982 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4983 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4984 secfile_insert_int(saving->file, ship->life_support,
4985 "%s.life_support", buf);
4986 secfile_insert_int(saving->file, ship->solar_panels,
4987 "%s.solar_panels", buf);
4988
4989 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4990 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4991 }
4992 st[ssi] = '\0';
4993 secfile_insert_str(saving->file, st, "%s.structure", buf);
4994 if (ship->state >= SSHIP_LAUNCHED) {
4995 secfile_insert_int(saving->file, ship->launch_year,
4996 "%s.launch_year", buf);
4997 }
4998 }
4999
5000 /* Save lost wonders info. */
5001 {
5002 char lost[B_LAST+1];
5003
5004 improvement_iterate(pimprove) {
5005 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5006 lost[improvement_index(pimprove)] = '1';
5007 } else {
5008 lost[improvement_index(pimprove)] = '0';
5009 }
5011 lost[improvement_count()] = '\0';
5013 "player%d.lost_wonders", plrno);
5014 }
5015
5016 secfile_insert_int(saving->file, plr->history,
5017 "player%d.history", plrno);
5019 "player%d.hut_count", plrno);
5020
5022 "player%d.border_vision", plrno);
5023
5024 if (saving->scenario) {
5025 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5026 int def = 1; /* We want users to get a player in a scenario */
5027
5029 /* This isn't usable player */
5030 def = 0;
5031 }
5032
5033 secfile_insert_int(saving->file, def,
5034 "player%d.autoselect_weight", plrno);
5035 } else {
5037 "player%d.autoselect_weight", plrno);
5038 }
5039 }
5040}
5041
5042/************************************************************************/
5046 struct player *plr)
5047{
5048 int ncities, i, plrno = player_number(plr);
5049 bool tasks_handled;
5051
5052 /* Check status and return if not OK (sg_success FALSE). */
5053 sg_check_ret();
5054
5056 "player%d.ncities", plrno),
5057 "%s", secfile_error());
5058
5059 if (!plr->is_alive && ncities > 0) {
5060 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5061 ncities = 0;
5062 }
5063
5065 "player%d.wl_max_length",
5066 plrno);
5068 "player%d.routes_max_length", plrno);
5069
5070 /* Load all cities of the player. */
5071 for (i = 0; i < ncities; i++) {
5072 char buf[32];
5073 struct city *pcity;
5074
5075 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5076
5077 /* Create a dummy city. */
5084 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5085 }
5086
5089
5090 /* Load the information about the nationality of citizens. This is done
5091 * here because the city sanity check called by citizens_update() requires
5092 * that the city is registered. */
5094
5095 /* After everything is loaded, but before vision. */
5097
5098 /* adding the city contribution to fog-of-war */
5102
5104 }
5105
5107 for (i = 0; !tasks_handled; i++) {
5108 int city_id;
5109 struct city *pcity = NULL;
5110
5111 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5112 plrno, i);
5113
5114 if (city_id != -1) {
5115 pcity = player_city_by_number(plr, city_id);
5116 }
5117
5118 if (pcity != NULL) {
5119 const char *str;
5120 int nat_x, nat_y;
5121 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5122
5123 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5124 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5125
5126 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5127
5128 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5130
5132 "Unknown workertask activity %s", str);
5133
5134 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5135
5136 if (strcmp("-", str)) {
5138
5139 sg_failure_ret(ptask->tgt != NULL,
5140 "Unknown workertask target %s", str);
5141 } else {
5142 ptask->tgt = NULL;
5143
5144 if (ptask->act == ACTIVITY_IRRIGATE) {
5146 } else if (ptask->act == ACTIVITY_MINE) {
5147 ptask->act = ACTIVITY_MINE;
5148 }
5149 }
5150
5151 ptask->want = secfile_lookup_int_default(loading->file, 1,
5152 "player%d.task%d.want", plrno, i);
5153
5154 worker_task_list_append(pcity->task_reqs, ptask);
5155 } else {
5157 }
5158 }
5159}
5160
5161/************************************************************************/
5164static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5165 struct city *pcity, const char *citystr,
5167{
5168 struct player *past;
5169 const char *kind, *name, *str;
5170 int id, i, repair, sp_count = 0, workers = 0, value;
5171 int nat_x, nat_y;
5172 citizens size;
5173 const char *stylename;
5174 int partner;
5175 int want;
5176 int tmp_int;
5177 const struct civ_map *nmap = &(wld.map);
5178
5180 FALSE, "%s", secfile_error());
5182 FALSE, "%s", secfile_error());
5185 "%s has invalid center tile (%d, %d)",
5186 citystr, nat_x, nat_y);
5188 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5189
5190 /* Instead of dying, use 'citystr' string for damaged name. */
5192 "%s.name", citystr));
5193
5195 citystr), FALSE, "%s", secfile_error());
5196
5198 "%s.original", citystr);
5199 past = player_by_number(id);
5200 if (NULL != past) {
5201 pcity->original = past;
5202 }
5203
5204 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5205 citystr), FALSE, "%s", secfile_error());
5206 size = (citizens)value; /* set the correct type */
5207 sg_warn_ret_val(value == (int)size, FALSE,
5208 "Invalid city size: %d, set to %d", value, size);
5210
5211 for (i = 0; i < loading->specialist.size; i++) {
5212 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5213 citystr, i),
5214 FALSE, "%s", secfile_error());
5215 pcity->specialists[specialist_index(loading->specialist.order[i])]
5216 = (citizens)value;
5217 sp_count += value;
5218 }
5219
5220 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5221 for (i = 0; partner != 0; i++) {
5222 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5223 const char *dir;
5224 const char *good_str;
5225
5226 /* Append to routes list immediately, so the pointer can be found for freeing
5227 * even if we abort */
5229
5230 proute->partner = partner;
5231 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5233 "No traderoute direction found for %s", citystr);
5236 "Illegal route direction %s", dir);
5237 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5239 "No good found for %s", citystr);
5241 sg_warn_ret_val(proute->goods != NULL, FALSE,
5242 "Illegal good %s", good_str);
5243
5244 /* Next one */
5246 "%s.traderoute%d", citystr, i + 1);
5247 }
5248
5249 for (; i < routes_max; i++) {
5250 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5251 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5252 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5253 }
5254
5255 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5256 "%s.food_stock", citystr),
5257 FALSE, "%s", secfile_error());
5258 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5259 "%s.shield_stock", citystr),
5260 FALSE, "%s", secfile_error());
5261 pcity->history =
5262 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5263
5264 pcity->airlift =
5265 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5266 pcity->was_happy =
5267 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5268 citystr);
5269 pcity->had_famine =
5270 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5271 citystr);
5272
5273 pcity->turn_plague =
5274 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5275
5277 "%s.anarchy", citystr),
5278 FALSE, "%s", secfile_error());
5279 pcity->rapture =
5280 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5281 pcity->steal =
5282 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5283
5284 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5285 "%s.turn_founded", citystr),
5286 FALSE, "%s", secfile_error());
5288 "%s.acquire_t", citystr),
5289 FALSE, "%s", secfile_error());
5290 pcity->acquire_t = tmp_int;
5291 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5292 citystr), FALSE, "%s", secfile_error());
5293 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5294 citystr), FALSE, "%s", secfile_error());
5295
5296 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5297 "%s.turn_last_built", citystr),
5298 FALSE, "%s", secfile_error());
5299
5300 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5301 citystr);
5302 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5303 citystr);
5304 pcity->production = universal_by_rule_name(kind, name);
5305 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5306 "%s.currently_building: unknown \"%s\" \"%s\".",
5307 citystr, kind, name);
5308
5309 want = secfile_lookup_int_default(loading->file, 0,
5310 "%s.current_want", citystr);
5311 if (pcity->production.kind == VUT_IMPROVEMENT) {
5312 pcity->server.adv->
5313 building_want[improvement_index(pcity->production.value.building)]
5314 = want;
5315 }
5316
5317 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5318 citystr);
5319 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5320 citystr);
5323 "%s.changed_from: unknown \"%s\" \"%s\".",
5324 citystr, kind, name);
5325
5326 pcity->before_change_shields =
5327 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5328 "%s.before_change_shields", citystr);
5329 pcity->caravan_shields =
5331 "%s.caravan_shields", citystr);
5332 pcity->disbanded_shields =
5334 "%s.disbanded_shields", citystr);
5335 pcity->last_turns_shield_surplus =
5337 "%s.last_turns_shield_surplus",
5338 citystr);
5339
5341 "%s.style", citystr);
5342 if (stylename != NULL) {
5344 } else {
5345 pcity->style = 0;
5346 }
5347 if (pcity->style < 0) {
5348 pcity->style = city_style(pcity);
5349 }
5350
5351 pcity->server.synced = FALSE; /* Must re-sync with clients */
5352
5353 /* Initialise list of city improvements. */
5354 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5355 pcity->built[i].turn = I_NEVER;
5356 }
5357
5358 /* Load city improvements. */
5359 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5361 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5362 "Invalid length of '%s.improvements' ("
5363 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5364 citystr, strlen(str), loading->improvement.size);
5365 for (i = 0; i < loading->improvement.size; i++) {
5366 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5367 "Undefined value '%c' within '%s.improvements'.",
5368 str[i], citystr)
5369
5370 if (str[i] == '1') {
5371 struct impr_type *pimprove
5372 = improvement_by_rule_name(loading->improvement.order[i]);
5373
5374 if (pimprove) {
5375 city_add_improvement(pcity, pimprove);
5376 }
5377 }
5378 }
5379
5380 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5381 "No worked tiles map defined.");
5382
5384
5385 /* Load new savegame with variable (squared) city radius and worked
5386 * tiles map */
5387
5388 int radius_sq
5389 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5390 citystr);
5391 city_map_radius_sq_set(pcity, radius_sq);
5392
5394 if (loading->worked_tiles[ptile->index] == pcity->id) {
5395 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5396 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5397 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5398 TILE_XY(pcity->tile), TILE_XY(ptile));
5399 pcity->specialists[DEFAULT_SPECIALIST]++;
5400 sp_count++;
5401 } else {
5402 tile_set_worked(ptile, pcity);
5403 workers++;
5404 }
5405
5406#ifdef FREECIV_DEBUG
5407 /* Set this tile to unused; a check for not reset tiles is
5408 * included in game_load_internal() */
5409 loading->worked_tiles[ptile->index] = -1;
5410#endif /* FREECIV_DEBUG */
5411 }
5413
5414 if (tile_worked(city_tile(pcity)) != pcity) {
5415 struct city *pwork = tile_worked(city_tile(pcity));
5416
5417 if (NULL != pwork) {
5418 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5419 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5422
5423 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5424 pwork->specialists[DEFAULT_SPECIALIST]++;
5426 } else {
5427 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5430 }
5431
5432 /* Repair pcity */
5435 }
5436
5438 if (0 != repair) {
5439 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5440 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5442 workers, FREE_WORKED_TILES, sp_count);
5443
5444 /* Repair pcity */
5446 }
5447
5448 /* worklist_init() done in create_city_virtual() */
5449 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5450
5451 /* Load city options. */
5452 BV_CLR_ALL(pcity->city_options);
5453 for (i = 0; i < loading->coptions.size; i++) {
5454 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5455 citystr, i)) {
5456 BV_SET(pcity->city_options, loading->coptions.order[i]);
5457 }
5458 }
5460 "%s.wlcb", citystr),
5461 FALSE, "%s", secfile_error());
5462 pcity->wlcb = tmp_int;
5463
5464 /* Load the city rally point. */
5465 {
5466 int len = secfile_lookup_int_default(loading->file, 0,
5467 "%s.rally_point_length", citystr);
5468 int unconverted;
5469
5470 pcity->rally_point.length = len;
5471 if (len > 0) {
5473
5474 pcity->rally_point.orders
5475 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5476 pcity->rally_point.persistent
5478 "%s.rally_point_persistent", citystr);
5479 pcity->rally_point.vigilant
5481 "%s.rally_point_vigilant", citystr);
5482
5485 "%s.rally_point_orders", citystr);
5488 "%s.rally_point_dirs", citystr);
5491 "%s.rally_point_activities", citystr);
5492
5493 for (i = 0; i < len; i++) {
5494 struct unit_order *order = &pcity->rally_point.orders[i];
5495
5496 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5497 || rally_activities[i] == '\0') {
5498 log_sg("Invalid rally point.");
5499 free(pcity->rally_point.orders);
5500 pcity->rally_point.orders = NULL;
5501 pcity->rally_point.length = 0;
5502 break;
5503 }
5504 order->order = char2order(rally_orders[i]);
5505 order->dir = char2dir(rally_dirs[i]);
5506 order->activity = char2activity(rally_activities[i]);
5507
5509 "%s.rally_point_action_vec,%d",
5510 citystr, i);
5511
5512 if (unconverted == -1) {
5513 order->action = ACTION_NONE;
5514 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5515 /* Look up what action id the unconverted number represents. */
5516 order->action = loading->action.order[unconverted];
5517 } else {
5518 if (order->order == ORDER_PERFORM_ACTION) {
5519 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5520 pcity->id);
5521 }
5522
5523 order->action = ACTION_NONE;
5524 }
5525
5526 order->target
5528 "%s.rally_point_tgt_vec,%d",
5529 citystr, i);
5530 order->sub_target
5532 "%s.rally_point_sub_tgt_vec,%d",
5533 citystr, i);
5534 }
5535 } else {
5536 pcity->rally_point.orders = NULL;
5537
5538 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5539 citystr);
5540 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5541 citystr);
5542 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5543 citystr);
5544 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5545 citystr);
5546 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5547 citystr);
5548 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5549 citystr);
5551 "%s.rally_point_tgt_vec", citystr);
5553 "%s.rally_point_sub_tgt_vec", citystr);
5554 }
5555 }
5556
5557 /* Load the city manager parameters. */
5558 {
5559 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5560 "%s.cma_enabled", citystr);
5561 if (enabled) {
5562 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5563
5564 for (i = 0; i < O_LAST; i++) {
5566 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5568 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5569 }
5570
5572 loading->file, FALSE, "%s.max_growth", citystr);
5574 loading->file, FALSE, "%s.require_happy", citystr);
5576 loading->file, FALSE, "%s.allow_disorder", citystr);
5578 loading->file, FALSE, "%s.allow_specialists", citystr);
5580 loading->file, 0, "%s.happy_factor", citystr);
5581 pcity->cm_parameter = param;
5582 } else {
5583 pcity->cm_parameter = NULL;
5584
5585 for (i = 0; i < O_LAST; i++) {
5587 "%s.cma_minimal_surplus,%d", citystr, i);
5589 "%s.cma_factor,%d", citystr, i);
5590 }
5591
5592 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5593 citystr);
5594 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5595 citystr);
5596 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5597 citystr);
5598 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5599 citystr);
5600 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5601 citystr);
5602 }
5603 }
5604
5605 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5606
5607 return TRUE;
5608}
5609
5610/************************************************************************/
5614 struct player *plr,
5615 struct city *pcity,
5616 const char *citystr)
5617{
5619 citizens size;
5620
5622 player_slots_iterate(pslot) {
5623 int nationality;
5624
5625 nationality = secfile_lookup_int_default(loading->file, -1,
5626 "%s.citizen%d", citystr,
5627 player_slot_index(pslot));
5628 if (nationality > 0 && !player_slot_is_used(pslot)) {
5629 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5631 continue;
5632 }
5633
5634 if (nationality != -1 && player_slot_is_used(pslot)) {
5635 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5636 "Invalid value for citizens of player %d in %s: %d.",
5637 player_slot_index(pslot), city_name_get(pcity), nationality);
5638 citizens_nation_set(pcity, pslot, nationality);
5639 }
5641 /* Sanity check. */
5643 if (size != city_size_get(pcity)) {
5644 if (size != 0) {
5645 /* size == 0 can be result from the fact that ruleset had no
5646 * nationality enabled at saving time, so no citizens at all
5647 * were saved. But something more serious must be going on if
5648 * citizens have been saved partially - if some of them are there. */
5649 log_sg("City size and number of citizens does not match in %s "
5650 "(%d != %d)! Repairing ...", city_name_get(pcity),
5652 }
5654 }
5655 }
5656}
5657
5658/************************************************************************/
5662 struct player *plr)
5663{
5665 int i = 0;
5666 int plrno = player_number(plr);
5668
5669 /* Check status and return if not OK (sg_success FALSE). */
5670 sg_check_ret();
5671
5673 "player%d.ncities", plrno);
5674
5676 /* Initialise the nation list for the citizens information. */
5677 player_slots_iterate(pslot) {
5680 }
5681
5682 /* First determine length of longest worklist, rally point order, and the
5683 * nationalities we have. */
5685 int routes;
5686
5687 /* Check the sanity of the city. */
5690
5691 if (pcity->worklist.length > wlist_max_length) {
5692 wlist_max_length = pcity->worklist.length;
5693 }
5694
5695 if (pcity->rally_point.length > rally_point_max_length) {
5696 rally_point_max_length = pcity->rally_point.length;
5697 }
5698
5699 routes = city_num_trade_routes(pcity);
5700 if (routes > routes_max) {
5701 routes_max = routes;
5702 }
5703
5705 /* Find all nations of the citizens,*/
5706 players_iterate(pplayer) {
5707 if (!nations[player_index(pplayer)]
5708 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5709 nations[player_index(pplayer)] = TRUE;
5710 }
5712 }
5714
5716 "player%d.wl_max_length", plrno);
5718 "player%d.routes_max_length", plrno);
5719
5721 struct tile *pcenter = city_tile(pcity);
5722 char impr_buf[B_LAST + 1];
5723 char buf[32];
5724 int j, nat_x, nat_y;
5725
5726 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5727
5728
5730 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5731 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5732
5733 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5734
5735 if (pcity->original != NULL) {
5736 secfile_insert_int(saving->file, player_number(pcity->original),
5737 "%s.original", buf);
5738 } else {
5739 secfile_insert_int(saving->file, -1, "%s.original", buf);
5740 }
5741 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5742
5743 j = 0;
5745 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5746 buf, j++);
5748
5749 j = 0;
5751 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5752 buf, j);
5754 "%s.route_direction%d", buf, j);
5756 "%s.route_good%d", buf, j);
5757 j++;
5759
5760 /* Save dummy values to keep tabular format happy */
5761 for (; j < routes_max; j++) {
5762 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5764 "%s.route_direction%d", buf, j);
5766 "%s.route_good%d", buf, j);
5767 }
5768
5769 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5770 buf);
5771 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5772 buf);
5773 secfile_insert_int(saving->file, pcity->history, "%s.history",
5774 buf);
5775
5776 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5777 buf);
5778 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5779 buf);
5780 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5781 buf);
5782 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5783 buf);
5784
5785 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5786 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5787 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5788 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5789 buf);
5790 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5791 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5792 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5793 secfile_insert_int(saving->file, pcity->turn_last_built,
5794 "%s.turn_last_built", buf);
5795
5796 /* For visual debugging, variable length strings together here */
5797 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5798
5800 "%s.currently_building_kind", buf);
5802 "%s.currently_building_name", buf);
5803
5804 if (pcity->production.kind == VUT_IMPROVEMENT) {
5806 pcity->server.adv->
5807 building_want[improvement_index(pcity->production.value.building)],
5808 "%s.current_want", buf);
5809 } else {
5810 secfile_insert_int(saving->file, 0,
5811 "%s.current_want", buf);
5812 }
5813
5815 "%s.changed_from_kind", buf);
5817 "%s.changed_from_name", buf);
5818
5819 secfile_insert_int(saving->file, pcity->before_change_shields,
5820 "%s.before_change_shields", buf);
5821 secfile_insert_int(saving->file, pcity->caravan_shields,
5822 "%s.caravan_shields", buf);
5823 secfile_insert_int(saving->file, pcity->disbanded_shields,
5824 "%s.disbanded_shields", buf);
5825 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5826 "%s.last_turns_shield_surplus", buf);
5827
5829 "%s.style", buf);
5830
5831 /* Save the squared city radius and all tiles within the corresponding
5832 * city map. */
5833 secfile_insert_int(saving->file, pcity->city_radius_sq,
5834 "player%d.c%d.city_radius_sq", plrno, i);
5835 /* The tiles worked by the city are saved using the main map.
5836 * See also sg_save_map_worked(). */
5837
5838 /* Save improvement list as bytevector. Note that improvement order
5839 * is saved in savefile.improvement_order. */
5840 improvement_iterate(pimprove) {
5841 impr_buf[improvement_index(pimprove)]
5842 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5843 : '1';
5845 impr_buf[improvement_count()] = '\0';
5846
5848 "Invalid size of the improvement vector (%s.improvements: "
5849 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5850 strlen(impr_buf), sizeof(impr_buf));
5851 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5852
5853 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5854 buf);
5855
5856 for (j = 0; j < CITYO_LAST; j++) {
5857 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5858 "%s.option%d", buf, j);
5859 }
5860 secfile_insert_int(saving->file, pcity->wlcb,
5861 "%s.wlcb", buf);
5862
5863 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5864
5866 /* Save nationality of the citizens,*/
5867 players_iterate(pplayer) {
5868 if (nations[player_index(pplayer)]) {
5870 citizens_nation_get(pcity, pplayer->slot),
5871 "%s.citizen%d", buf, player_index(pplayer));
5872 }
5874 }
5875
5876 secfile_insert_int(saving->file, pcity->rally_point.length,
5877 "%s.rally_point_length", buf);
5878 if (pcity->rally_point.length) {
5879 int len = pcity->rally_point.length;
5880 char orders[len + 1], dirs[len + 1], activities[len + 1];
5881 int actions[len];
5882 int targets[len];
5883 int sub_targets[len];
5884
5885 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5886 "%s.rally_point_persistent", buf);
5887 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5888 "%s.rally_point_vigilant", buf);
5889
5890 for (j = 0; j < len; j++) {
5891 orders[j] = order2char(pcity->rally_point.orders[j].order);
5892 dirs[j] = '?';
5893 activities[j] = '?';
5894 targets[j] = NO_TARGET;
5895 sub_targets[j] = NO_TARGET;
5896 actions[j] = -1;
5897 switch (pcity->rally_point.orders[j].order) {
5898 case ORDER_MOVE:
5899 case ORDER_ACTION_MOVE:
5900 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5901 break;
5902 case ORDER_ACTIVITY:
5903 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5904 activities[j]
5905 = activity2char(pcity->rally_point.orders[j].activity);
5906 actions[j]
5907 = pcity->rally_point.orders[j].action;
5908 break;
5910 actions[j] = pcity->rally_point.orders[j].action;
5911 targets[j] = pcity->rally_point.orders[j].target;
5912 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5913 break;
5914 case ORDER_FULL_MP:
5915 case ORDER_LAST:
5916 break;
5917 }
5918
5919 if (actions[j] == ACTION_NONE) {
5920 actions[j] = -1;
5921 }
5922 }
5923 orders[len] = dirs[len] = activities[len] = '\0';
5924
5925 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5926 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5927 secfile_insert_str(saving->file, activities,
5928 "%s.rally_point_activities", buf);
5929
5931 "%s.rally_point_action_vec", buf);
5932 /* Fill in dummy values for order targets so the registry will save
5933 * the unit table in a tabular format. */
5934 for (j = len; j < rally_point_max_length; j++) {
5935 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5936 buf, j);
5937 }
5938
5939 secfile_insert_int_vec(saving->file, targets, len,
5940 "%s.rally_point_tgt_vec", buf);
5941 /* Fill in dummy values for order targets so the registry will save
5942 * the unit table in a tabular format. */
5943 for (j = len; j < rally_point_max_length; j++) {
5945 "%s.rally_point_tgt_vec,%d", buf, j);
5946 }
5947
5948 secfile_insert_int_vec(saving->file, sub_targets, len,
5949 "%s.rally_point_sub_tgt_vec", buf);
5950 /* Fill in dummy values for order targets so the registry will save
5951 * the unit table in a tabular format. */
5952 for (j = len; j < rally_point_max_length; j++) {
5953 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5954 buf, j);
5955 }
5956 } else {
5957 /* Put all the same fields into the savegame - otherwise the
5958 * registry code can't correctly use a tabular format and the
5959 * savegame will be bigger. */
5960 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5961 buf);
5962 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5963 buf);
5964 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5965 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5966 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5967 buf);
5968
5969 /* Fill in dummy values for order targets so the registry will save
5970 * the unit table in a tabular format. */
5971
5972 /* The start of a vector has no number. */
5973 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5974 buf);
5975 for (j = 1; j < rally_point_max_length; j++) {
5976 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5977 buf, j);
5978 }
5979
5980 /* The start of a vector has no number. */
5981 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5982 buf);
5983 for (j = 1; j < rally_point_max_length; j++) {
5985 "%s.rally_point_tgt_vec,%d", buf, j);
5986 }
5987
5988 /* The start of a vector has no number. */
5989 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5990 buf);
5991 for (j = 1; j < rally_point_max_length; j++) {
5992 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5993 buf, j);
5994 }
5995 }
5996
5997 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5998 "%s.cma_enabled", buf);
5999 if (pcity->cm_parameter) {
6001 pcity->cm_parameter->minimal_surplus, O_LAST,
6002 "%s.cma_minimal_surplus", buf);
6004 pcity->cm_parameter->factor, O_LAST,
6005 "%s.cma_factor", buf);
6006 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6007 "%s.max_growth", buf);
6008 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6009 "%s.require_happy", buf);
6010 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6011 "%s.allow_disorder", buf);
6013 pcity->cm_parameter->allow_specialists,
6014 "%s.allow_specialists", buf);
6015 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6016 "%s.happy_factor", buf);
6017 } else {
6018 int zeros[O_LAST];
6019
6020 memset(zeros, 0, sizeof(zeros));
6022 "%s.cma_minimal_surplus", buf);
6024 "%s.cma_factor", buf);
6025 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6026 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6027 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6028 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6029 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6030 }
6031
6032 i++;
6034
6035 i = 0;
6037 worker_task_list_iterate(pcity->task_reqs, ptask) {
6038 int nat_x, nat_y;
6039
6041 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6042 plrno, i);
6043 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6044 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6046 "player%d.task%d.activity",
6047 plrno, i);
6048 if (ptask->tgt != NULL) {
6050 "player%d.task%d.target",
6051 plrno, i);
6052 } else {
6053 secfile_insert_str(saving->file, "-",
6054 "player%d.task%d.target",
6055 plrno, i);
6056 }
6057 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6058
6059 i++;
6062}
6063
6064/************************************************************************/
6068 struct player *plr)
6069{
6070 int nunits, i, plrno = player_number(plr);
6071 size_t orders_max_length;
6072
6073 /* Check status and return if not OK (sg_success FALSE). */
6074 sg_check_ret();
6075
6077 "player%d.nunits", plrno),
6078 "%s", secfile_error());
6079 if (!plr->is_alive && nunits > 0) {
6080 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6081 nunits = 0; /* Some old savegames may be buggy. */
6082 }
6083
6085 "player%d.orders_max_length",
6086 plrno);
6087
6088 for (i = 0; i < nunits; i++) {
6089 struct unit *punit;
6090 struct city *pcity;
6091 const char *name;
6092 char buf[32];
6093 struct unit_type *type;
6094 struct tile *ptile;
6095
6096 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6097
6098 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6100 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6101
6102 /* Create a dummy unit. */
6103 punit = unit_virtual_create(plr, NULL, type, 0);
6106 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6107 }
6108
6111
6113 unit_list_prepend(pcity->units_supported, punit);
6114 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6115 log_sg("%s: bad home city %d.", buf, punit->homecity);
6117 }
6118
6119 ptile = unit_tile(punit);
6120
6121 /* allocate the unit's contribution to fog of war */
6124 /* NOTE: There used to be some map_set_known calls here. These were
6125 * unneeded since unfogging the tile when the unit sees it will
6126 * automatically reveal that tile. */
6127
6130 }
6131}
6132
6133/************************************************************************/
6137 struct player *plr, struct unit *punit,
6139 const char *unitstr)
6140{
6141 enum unit_activity activity;
6142 int nat_x, nat_y;
6143 struct extra_type *pextra = NULL;
6144 struct tile *ptile;
6145 int extra_id;
6146 int ei;
6147 const char *facing_str;
6148 int natnbr;
6149 int unconverted;
6150 const char *str;
6151 enum gen_action action;
6152
6154 unitstr), FALSE, "%s", secfile_error());
6156 FALSE, "%s", secfile_error());
6158 FALSE, "%s", secfile_error());
6159
6160 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6161 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6162 unitstr, nat_x, nat_y);
6163 unit_tile_set(punit, ptile);
6164
6167 "%s.facing", unitstr);
6168 if (facing_str[0] != 'x') {
6169 /* We don't touch punit->facing if savegame does not contain that
6170 * information. Initial orientation set by unit_virtual_create()
6171 * is as good as any. */
6172 enum direction8 facing = char2dir(facing_str[0]);
6173
6174 if (direction8_is_valid(facing)) {
6175 punit->facing = facing;
6176 } else {
6177 log_error("Illegal unit orientation '%s'", facing_str);
6178 }
6179 }
6180
6181 /* If savegame has unit nationality, it doesn't hurt to
6182 * internally set it even if nationality rules are disabled. */
6184 player_number(plr),
6185 "%s.nationality", unitstr);
6186
6188 if (punit->nationality == NULL) {
6189 punit->nationality = plr;
6190 }
6191
6193 "%s.homecity", unitstr), FALSE,
6194 "%s", secfile_error());
6196 "%s.moves", unitstr), FALSE,
6197 "%s", secfile_error());
6199 "%s.fuel", unitstr), FALSE,
6200 "%s", secfile_error());
6202 "%s.activity", unitstr), FALSE,
6203 "%s", secfile_error());
6204 activity = unit_activity_by_name(loading->activities.order[ei],
6207 "%s.action", unitstr), FALSE,
6208 "%s", secfile_error());
6209 if (ei == -1) {
6211 } else if (ei >= 0 && ei < loading->action.size) {
6212 action = loading->action.order[ei];
6213 } else {
6214 log_sg("Invalid action id for unit %d", punit->id);
6216 }
6217
6220 "%s.born", unitstr);
6223 "%s.current_form_turn", unitstr);
6224
6226 "%s.activity_tgt", unitstr);
6227
6228 if (extra_id != -2) {
6229 if (extra_id >= 0 && extra_id < loading->extra.size) {
6230 pextra = loading->extra.order[extra_id];
6231 set_unit_activity_targeted(punit, activity, pextra, action);
6232 } else if (activity == ACTIVITY_IRRIGATE) {
6236 punit);
6237 if (tgt != NULL) {
6239 } else {
6241 }
6242 } else if (activity == ACTIVITY_MINE) {
6244 EC_MINE,
6246 punit);
6247 if (tgt != NULL) {
6249 } else {
6251 }
6252 } else {
6253 set_unit_activity(punit, activity, action);
6254 }
6255 } else {
6257 } /* activity_tgt == NULL */
6258
6260 "%s.activity_count", unitstr), FALSE,
6261 "%s", secfile_error());
6262
6265 "%s.changed_from", unitstr);
6266
6268 "%s.changed_from_tgt", unitstr), FALSE,
6269 "%s", secfile_error());
6270
6271 if (extra_id >= 0 && extra_id < loading->extra.size) {
6272 punit->changed_from_target = loading->extra.order[extra_id];
6273 } else {
6275 }
6276
6279 "%s.changed_from_count", unitstr);
6280
6281 /* Special case: for a long time, we accidentally incremented
6282 * activity_count while a unit was sentried, so it could increase
6283 * without bound (bug #20641) and be saved in old savefiles.
6284 * We zero it to prevent potential trouble overflowing the range
6285 * in network packets, etc. */
6286 if (activity == ACTIVITY_SENTRY) {
6287 punit->activity_count = 0;
6288 }
6291 }
6292
6293 punit->veteran
6294 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6295 {
6296 /* Protect against change in veteran system in ruleset */
6297 const int levels = utype_veteran_levels(unit_type_get(punit));
6298
6299 if (punit->veteran >= levels) {
6300 fc_assert(levels >= 1);
6301 punit->veteran = levels - 1;
6302 }
6303 }
6306 "%s.done_moving", unitstr);
6309 "%s.battlegroup", unitstr);
6310
6312 "%s.go", unitstr)) {
6313 int gnat_x, gnat_y;
6314
6316 "%s.goto_x", unitstr), FALSE,
6317 "%s", secfile_error());
6319 "%s.goto_y", unitstr), FALSE,
6320 "%s", secfile_error());
6321
6323 } else {
6324 punit->goto_tile = NULL;
6325
6326 /* These variables are not used but needed for saving the unit table.
6327 * Load them to prevent unused variables errors. */
6328 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6329 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6330 }
6331
6332 /* Load AI data of the unit. */
6333 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6334
6337 "%s.server_side_agent",
6338 unitstr);
6339 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6340 /* Look up what server side agent the unconverted number represents. */
6341 punit->ssa_controller = loading->ssa.order[unconverted];
6342 } else {
6343 log_sg("Invalid server side agent %d for unit %d",
6344 unconverted, punit->id);
6345
6347 }
6348
6350 "%s.hp", unitstr), FALSE,
6351 "%s", secfile_error());
6352
6354 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6356 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6357 punit->moved
6358 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6361 "%s.paradropped", unitstr);
6362 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6363 if (str[0] != '\0') {
6365 }
6366
6367 /* The transport status (punit->transported_by) is loaded in
6368 * sg_player_units_transport(). */
6369
6370 /* Initialize upkeep values: these are hopefully initialized
6371 * elsewhere before use (specifically, in city_support(); but
6372 * fixme: check whether always correctly initialized?).
6373 * Below is mainly for units which don't have homecity --
6374 * otherwise these don't get initialized (and AI calculations
6375 * etc may use junk values). */
6379
6381 "%s.action_decision", unitstr),
6382 FALSE, "%s", secfile_error());
6383
6384 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6385 /* Look up what action decision want the unconverted number
6386 * represents. */
6387 punit->action_decision_want = loading->act_dec.order[unconverted];
6388 } else {
6389 log_sg("Invalid action decision want for unit %d", punit->id);
6390
6392 }
6393
6395 /* Load the tile to act against. */
6396 int adwt_x, adwt_y;
6397
6398 if (secfile_lookup_int(loading->file, &adwt_x,
6399 "%s.action_decision_tile_x", unitstr)
6401 "%s.action_decision_tile_y", unitstr)) {
6403 adwt_x, adwt_y);
6404 } else {
6407 log_sg("Bad action_decision_tile for unit %d", punit->id);
6408 }
6409 } else {
6410 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6411 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6413 }
6414
6416
6417 /* Load the unit orders */
6418 {
6419 int len = secfile_lookup_int_default(loading->file, 0,
6420 "%s.orders_length", unitstr);
6421
6422 if (len > 0) {
6423 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6424 int j;
6425
6426 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6430 "%s.orders_index", unitstr);
6433 "%s.orders_repeat", unitstr);
6436 "%s.orders_vigilant", unitstr);
6437
6440 "%s.orders_list", unitstr);
6443 "%s.dir_list", unitstr);
6446 "%s.activity_list", unitstr);
6447
6449
6450 for (j = 0; j < len; j++) {
6451 struct unit_order *order = &punit->orders.list[j];
6453 int order_sub_tgt;
6454
6455 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6456 || act_unitstr[j] == '\0') {
6457 log_sg("Invalid unit orders.");
6459 break;
6460 }
6461 order->order = char2order(orders_unitstr[j]);
6462 order->dir = char2dir(dir_unitstr[j]);
6463 order->activity = char2activity(act_unitstr[j]);
6464
6466 "%s.action_vec,%d",
6467 unitstr, j);
6468
6469 if (unconverted == -1) {
6470 order->action = ACTION_NONE;
6471 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6472 /* Look up what action id the unconverted number represents. */
6473 order->action = loading->action.order[unconverted];
6474 } else {
6475 if (order->order == ORDER_PERFORM_ACTION) {
6476 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6477 }
6478
6479 order->action = ACTION_NONE;
6480 }
6481
6482 if (order->order == ORDER_LAST
6483 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6484 || (order->order == ORDER_ACTION_MOVE
6485 && !direction8_is_valid(order->dir))
6486 || (order->order == ORDER_PERFORM_ACTION
6487 && !action_id_exists(order->action))
6488 || (order->order == ORDER_ACTIVITY
6489 && (order->activity == ACTIVITY_LAST
6490 || !action_id_exists(order->action)))) {
6491 /* An invalid order. Just drop the orders for this unit. */
6493 punit->orders.list = NULL;
6495 break;
6496 }
6497
6499 "%s.tgt_vec,%d",
6500 unitstr, j);
6502 "%s.sub_tgt_vec,%d",
6503 unitstr, j);
6504
6505 if (order->order == ORDER_PERFORM_ACTION) {
6506 /* Validate sub target */
6507 switch (action_id_get_sub_target_kind(order->action)) {
6508 case ASTK_BUILDING:
6509 /* Sub target is a building. */
6511 /* Sub target is invalid. */
6512 log_sg("Cannot find building %d for %s to %s",
6515 order->sub_target = B_LAST;
6516 } else {
6517 order->sub_target = order_sub_tgt;
6518 }
6519 break;
6520 case ASTK_TECH:
6521 /* Sub target is a technology. */
6522 if (order_sub_tgt == A_NONE
6524 && order_sub_tgt != A_FUTURE)) {
6525 /* Target tech is invalid. */
6526 log_sg("Cannot find tech %d for %s to steal",
6528 order->sub_target = A_NONE;
6529 } else {
6530 order->sub_target = order_sub_tgt;
6531 }
6532 break;
6533 case ASTK_EXTRA:
6535 /* These take an extra. */
6537 break;
6538 case ASTK_NONE:
6539 /* None of these can take a sub target. */
6541 "Specified sub target for action %d unsupported.",
6542 order->action);
6543 order->sub_target = NO_TARGET;
6544 break;
6545 case ASTK_COUNT:
6547 "Bad action action %d.",
6548 order->action);
6549 order->sub_target = NO_TARGET;
6550 break;
6551 }
6552 }
6553
6554 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6555 enum unit_activity act;
6556
6558 if (order_sub_tgt != EXTRA_NONE) {
6559 log_sg("Cannot find extra %d for %s to build",
6561 }
6562
6563 order->sub_target = EXTRA_NONE;
6564 } else {
6565 order->sub_target = order_sub_tgt;
6566 }
6567
6568 /* An action or an activity may require an extra target. */
6569 if (action_wants_extra) {
6570 act = action_id_get_activity(order->action);
6571 } else {
6572 act = order->activity;
6573 }
6574
6575 if (unit_activity_is_valid(act)
6577 && order->sub_target == EXTRA_NONE) {
6578 /* Missing required action extra target. */
6580 punit->orders.list = NULL;
6582 break;
6583 }
6584 } else if (order->order != ORDER_PERFORM_ACTION) {
6585 if (order_sub_tgt != -1) {
6586 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6587 order_sub_tgt, -1, order->order);
6588 }
6589 order->sub_target = NO_TARGET;
6590 }
6591 }
6592
6593 for (; j < orders_max_length; j++) {
6595 "%s.action_vec,%d", unitstr, j);
6597 "%s.tgt_vec,%d", unitstr, j);
6599 "%s.sub_tgt_vec,%d", unitstr, j);
6600 }
6601 } else {
6602 int j;
6603
6605 punit->orders.list = NULL;
6606
6607 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6608 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6609 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6610 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6611 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6612 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6613 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6614 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6615 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6616
6617 for (j = 1; j < orders_max_length; j++) {
6619 "%s.action_vec,%d", unitstr, j);
6621 "%s.tgt_vec,%d", unitstr, j);
6623 "%s.sub_tgt_vec,%d", unitstr, j);
6624 }
6625 }
6626 }
6627
6628 return TRUE;
6629}
6630
6631/************************************************************************/
6636 struct player *plr)
6637{
6638 int nunits, i, plrno = player_number(plr);
6639
6640 /* Check status and return if not OK (sg_success FALSE). */
6641 sg_check_ret();
6642
6643 /* Recheck the number of units for the player. This is a copied from
6644 * sg_load_player_units(). */
6646 "player%d.nunits", plrno),
6647 "%s", secfile_error());
6648 if (!plr->is_alive && nunits > 0) {
6649 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6650 nunits = 0; /* Some old savegames may be buggy. */
6651 }
6652
6653 for (i = 0; i < nunits; i++) {
6654 int id_unit, id_trans;
6655 struct unit *punit, *ptrans;
6656
6658 "player%d.u%d.id",
6659 plrno, i);
6661 fc_assert_action(punit != NULL, continue);
6662
6664 "player%d.u%d.transported_by",
6665 plrno, i);
6666 if (id_trans == -1) {
6667 /* Not transported. */
6668 continue;
6669 }
6670
6672 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6673
6674 if (ptrans) {
6675#ifndef FREECIV_NDEBUG
6676 bool load_success =
6677#endif
6679
6680 fc_assert_action(load_success, continue);
6681 }
6682 }
6683}
6684
6685/************************************************************************/
6689 struct player *plr)
6690{
6691 int i = 0;
6692 int longest_order = 0;
6693 int plrno = player_number(plr);
6694
6695 /* Check status and return if not OK (sg_success FALSE). */
6696 sg_check_ret();
6697
6699 "player%d.nunits", plrno);
6700
6701 /* Find the longest unit order so different order length won't break
6702 * storing units in the tabular format. */
6704 if (punit->has_orders) {
6705 if (longest_order < punit->orders.length) {
6707 }
6708 }
6710
6712 "player%d.orders_max_length", plrno);
6713
6715 char buf[32];
6716 char dirbuf[2] = " ";
6717 int nat_x, nat_y;
6718 int last_order, j;
6719
6720 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6721 dirbuf[0] = dir2char(punit->facing);
6722 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6723
6725 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6726 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6727
6728 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6731 "%s.nationality", buf);
6732 }
6733 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6734 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6735 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6737 "%s.type_by_name", buf);
6738
6739 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6741 "%s.activity_count", buf);
6742 if (punit->action == ACTION_NONE) {
6743 secfile_insert_int(saving->file, -1, "%s.action", buf);
6744 } else {
6745 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6746 }
6747 if (punit->activity_target == NULL) {
6748 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6749 } else {
6751 "%s.activity_tgt", buf);
6752 }
6753
6755 "%s.changed_from", buf);
6757 "%s.changed_from_count", buf);
6758 if (punit->changed_from_target == NULL) {
6759 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6760 } else {
6762 "%s.changed_from_tgt", buf);
6763 }
6764
6766 "%s.done_moving", buf);
6767 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6768 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6770 "%s.born", buf);
6772 "%s.current_form_turn", buf);
6774 "%s.battlegroup", buf);
6775
6776 if (punit->goto_tile) {
6778 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6779 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6780 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6781 } else {
6782 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6783 /* Set this values to allow saving it as table. */
6784 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6785 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6786 }
6787
6789 "%s.server_side_agent", buf);
6790
6791 /* Save AI data of the unit. */
6792 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6793
6795 "%s.ord_map", buf);
6797 "%s.ord_city", buf);
6798 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6800 "%s.paradropped", buf);
6802 ? unit_transport_get(punit)->id : -1,
6803 "%s.transported_by", buf);
6804 if (punit->carrying != NULL) {
6806 "%s.carrying", buf);
6807 } else {
6808 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6809 }
6810
6812 "%s.action_decision", buf);
6813
6814 /* Stored as tile rather than direction to make sure the target tile is
6815 * sane. */
6820 "%s.action_decision_tile_x", buf);
6822 "%s.action_decision_tile_y", buf);
6823 } else {
6824 /* Dummy values to get tabular format. */
6825 secfile_insert_int(saving->file, -1,
6826 "%s.action_decision_tile_x", buf);
6827 secfile_insert_int(saving->file, -1,
6828 "%s.action_decision_tile_y", buf);
6829 }
6830
6832 "%s.stay", buf);
6833
6834 if (punit->has_orders) {
6835 int len = punit->orders.length;
6836 char orders_buf[len + 1], dir_buf[len + 1];
6837 char act_buf[len + 1];
6838 int action_buf[len];
6839 int tgt_vec[len];
6840 int sub_tgt_vec[len];
6841
6842 last_order = len;
6843
6844 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6846 "%s.orders_index", buf);
6848 "%s.orders_repeat", buf);
6850 "%s.orders_vigilant", buf);
6851
6852 for (j = 0; j < len; j++) {
6854 dir_buf[j] = '?';
6855 act_buf[j] = '?';
6856 tgt_vec[j] = NO_TARGET;
6857 sub_tgt_vec[j] = -1;
6858 action_buf[j] = -1;
6859 switch (punit->orders.list[j].order) {
6860 case ORDER_MOVE:
6861 case ORDER_ACTION_MOVE:
6862 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6863 break;
6864 case ORDER_ACTIVITY:
6868 break;
6871 tgt_vec[j] = punit->orders.list[j].target;
6873 break;
6874 case ORDER_FULL_MP:
6875 case ORDER_LAST:
6876 break;
6877 }
6878
6879 if (action_buf[j] == ACTION_NONE) {
6880 action_buf[j] = -1;
6881 }
6882 }
6883 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6884
6885 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6886 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6887 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6888
6890 "%s.action_vec", buf);
6891 /* Fill in dummy values for order targets so the registry will save
6892 * the unit table in a tabular format. */
6893 for (j = last_order; j < longest_order; j++) {
6894 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6895 }
6896
6898 "%s.tgt_vec", buf);
6899 /* Fill in dummy values for order targets so the registry will save
6900 * the unit table in a tabular format. */
6901 for (j = last_order; j < longest_order; j++) {
6902 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6903 }
6904
6906 "%s.sub_tgt_vec", buf);
6907 /* Fill in dummy values for order targets so the registry will save
6908 * the unit table in a tabular format. */
6909 for (j = last_order; j < longest_order; j++) {
6910 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6911 }
6912 } else {
6913
6914 /* Put all the same fields into the savegame - otherwise the
6915 * registry code can't correctly use a tabular format and the
6916 * savegame will be bigger. */
6917 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6918 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6919 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6920 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6921 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6922 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6923 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6924
6925 /* Fill in dummy values for order targets so the registry will save
6926 * the unit table in a tabular format. */
6927
6928 /* The start of a vector has no number. */
6929 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6930 for (j = 1; j < longest_order; j++) {
6931 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6932 }
6933
6934 /* The start of a vector has no number. */
6935 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6936 for (j = 1; j < longest_order; j++) {
6937 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6938 }
6939
6940 /* The start of a vector has no number. */
6941 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6942 for (j = 1; j < longest_order; j++) {
6943 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6944 }
6945 }
6946
6947 i++;
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 /* Toss any existing attribute_block (should not exist) */
6963 if (plr->attribute_block.data) {
6965 plr->attribute_block.data = NULL;
6966 }
6967
6968 /* This is a big heap of opaque data for the client, check everything! */
6970 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6971
6972 if (0 > plr->attribute_block.length) {
6973 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6974 plr->attribute_block.length);
6975 plr->attribute_block.length = 0;
6976 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6977 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6979 plr->attribute_block.length = 0;
6980 } else if (0 < plr->attribute_block.length) {
6981 int part_nr, parts;
6982 int quoted_length;
6983 char *quoted;
6984#ifndef FREECIV_NDEBUG
6985 size_t actual_length;
6986#endif
6987
6990 "player%d.attribute_v2_block_length_quoted",
6991 plrno), "%s", secfile_error());
6994 "player%d.attribute_v2_block_parts", plrno),
6995 "%s", secfile_error());
6996
6998 quoted[0] = '\0';
7000 for (part_nr = 0; part_nr < parts; part_nr++) {
7001 const char *current =
7003 "player%d.attribute_v2_block_data.part%d",
7004 plrno, part_nr);
7005 if (!current) {
7006 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7007 break;
7008 }
7009 log_debug("attribute_v2_block_length_quoted=%d"
7010 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7011 quoted_length, strlen(quoted), strlen(current));
7012 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7013 strcat(quoted, current);
7014 }
7016 "attribute_v2_block_length_quoted=%d"
7017 " actual=" SIZE_T_PRINTF,
7019
7020#ifndef FREECIV_NDEBUG
7022#endif
7024 plr->attribute_block.data,
7025 plr->attribute_block.length);
7027 free(quoted);
7028 }
7029}
7030
7031/************************************************************************/
7035 struct player *plr)
7036{
7037 int plrno = player_number(plr);
7038
7039 /* Check status and return if not OK (sg_success FALSE). */
7040 sg_check_ret();
7041
7042 /* This is a big heap of opaque data from the client. Although the binary
7043 * format is not user editable, keep the lines short enough for debugging,
7044 * and hope that data compression will keep the file a reasonable size.
7045 * Note that the "quoted" format is a multiple of 3.
7046 */
7047#define PART_SIZE (3*256)
7048#define PART_ADJUST (3)
7049 if (plr->attribute_block.data) {
7050 char part[PART_SIZE + PART_ADJUST];
7051 int parts;
7052 int current_part_nr;
7054 plr->attribute_block.length);
7055 char *quoted_at = strchr(quoted, ':');
7056 size_t bytes_left = strlen(quoted);
7057 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7059
7061 "player%d.attribute_v2_block_length", plrno);
7063 "player%d.attribute_v2_block_length_quoted", plrno);
7064
7065 /* Try to wring some compression efficiencies out of the "quoted" format.
7066 * The first line has a variable length decimal, mis-aligning triples.
7067 */
7068 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7069 /* first line can be longer */
7070 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7071 } else {
7072 parts = 1;
7073 }
7074
7076 "player%d.attribute_v2_block_parts", plrno);
7077
7078 if (parts > 1) {
7080
7081 /* first line can be longer */
7083 part[size_of_current_part] = '\0';
7085 "player%d.attribute_v2_block_data.part%d",
7086 plrno, 0);
7089 current_part_nr = 1;
7090 } else {
7091 quoted_at = quoted;
7092 current_part_nr = 0;
7093 }
7094
7097
7099 part[size_of_current_part] = '\0';
7101 "player%d.attribute_v2_block_data.part%d",
7102 plrno,
7106 }
7107 fc_assert(bytes_left == 0);
7108 free(quoted);
7109 }
7110#undef PART_ADJUST
7111#undef PART_SIZE
7112}
7113
7114/************************************************************************/
7118 struct player *plr)
7119{
7120 int plrno = player_number(plr);
7121 int total_ncities =
7123 "player%d.dc_total", plrno);
7124 int i;
7125 bool someone_alive = FALSE;
7126
7127 /* Check status and return if not OK (sg_success FALSE). */
7128 sg_check_ret();
7129
7132 if (pteam_member->is_alive) {
7134 break;
7135 }
7137
7138 if (!someone_alive) {
7139 /* Reveal all for completely dead teams. */
7141 }
7142 }
7143
7144 if (-1 == total_ncities
7145 || !game.info.fogofwar
7147 "game.save_private_map")) {
7148 /* We have:
7149 * - a dead player;
7150 * - fogged cities are not saved for any reason;
7151 * - a savegame with fog of war turned off;
7152 * - or game.save_private_map is not set to FALSE in the scenario /
7153 * savegame. The players private knowledge is set to be what they could
7154 * see without fog of war. */
7155 whole_map_iterate(&(wld.map), ptile) {
7156 if (map_is_known(ptile, plr)) {
7157 struct city *pcity = tile_city(ptile);
7158
7159 update_player_tile_last_seen(plr, ptile);
7160 update_player_tile_knowledge(plr, ptile);
7161
7162 if (NULL != pcity) {
7163 update_dumb_city(plr, pcity);
7164 }
7165 }
7167
7168 /* Nothing more to do; */
7169 return;
7170 }
7171
7172 /* Load player map (terrain). */
7173 LOAD_MAP_CHAR(ch, ptile,
7174 map_get_player_tile(ptile, plr)->terrain
7175 = char2terrain(ch), loading->file,
7176 "player%d.map_t%04d", plrno);
7177
7178 /* Load player map (extras). */
7179 halfbyte_iterate_extras(j, loading->extra.size) {
7180 LOAD_MAP_CHAR(ch, ptile,
7182 ch, loading->extra.order + 4 * j),
7183 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7185
7186 whole_map_iterate(&(wld.map), ptile) {
7187 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7188
7190 if (BV_ISSET(plrtile->extras, extra_number(pres))) {
7191 plrtile->resource = pres;
7192 if (!terrain_has_resource(plrtile->terrain, pres)) {
7193 BV_CLR(plrtile->extras, extra_number(pres));
7194 }
7195 }
7198
7200 /* Load player map (border). */
7201 int x, y;
7202
7203 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7204 const char *buffer
7205 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7206 plrno, y);
7207 const char *buffer2
7208 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7209 plrno, y);
7210 const char *ptr = buffer;
7211 const char *ptr2 = buffer2;
7212
7213 sg_failure_ret(NULL != buffer,
7214 "Savegame corrupt - map line %d not found.", y);
7215 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7216 char token[TOKEN_SIZE];
7217 char token2[TOKEN_SIZE];
7218 int number;
7219 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7220
7221 scanin(&ptr, ",", token, sizeof(token));
7222 sg_failure_ret('\0' != token[0],
7223 "Savegame corrupt - map size not correct.");
7224 if (strcmp(token, "-") == 0) {
7225 map_get_player_tile(ptile, plr)->owner = NULL;
7226 } else {
7227 sg_failure_ret(str_to_int(token, &number),
7228 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7229 token, x, y);
7230 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7231 }
7232
7233 scanin(&ptr2, ",", token2, sizeof(token2));
7234 sg_failure_ret('\0' != token2[0],
7235 "Savegame corrupt - map size not correct.");
7236 if (strcmp(token2, "-") == 0) {
7237 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7238 } else {
7240 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7241 token, x, y);
7242 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7243 }
7244 }
7245 }
7246 }
7247
7248 /* Load player map (update time). */
7249 for (i = 0; i < 4; i++) {
7250 /* put 4-bit segments of 16-bit "updated" field */
7251 if (i == 0) {
7252 LOAD_MAP_CHAR(ch, ptile,
7253 map_get_player_tile(ptile, plr)->last_updated
7254 = ascii_hex2bin(ch, i),
7255 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7256 } else {
7257 LOAD_MAP_CHAR(ch, ptile,
7258 map_get_player_tile(ptile, plr)->last_updated
7259 |= ascii_hex2bin(ch, i),
7260 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7261 }
7262 }
7263
7264 /* Load player map known cities. */
7265 for (i = 0; i < total_ncities; i++) {
7266 struct vision_site *pdcity;
7267 char buf[32];
7268 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7269
7273 pdcity);
7275 } else {
7276 /* Error loading the data. */
7277 log_sg("Skipping seen city %d for player %d.", i, plrno);
7278 if (pdcity != NULL) {
7280 }
7281 }
7282 }
7283
7284 /* Repair inconsistent player maps. */
7285 whole_map_iterate(&(wld.map), ptile) {
7286 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7287 struct city *pcity = tile_city(ptile);
7288
7289 update_player_tile_knowledge(plr, ptile);
7290 reality_check_city(plr, ptile);
7291
7292 if (NULL != pcity) {
7293 update_dumb_city(plr, pcity);
7294 }
7295 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7296 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7297 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7298
7299 plrtile->owner = tile_owner(ptile);
7300 }
7302}
7303
7304/************************************************************************/
7308 struct player *plr,
7309 struct vision_site *pdcity,
7310 const char *citystr)
7311{
7312 const char *str;
7313 int i, id, size;
7314 citizens city_size;
7315 int nat_x, nat_y;
7316 const char *stylename;
7317 enum capital_type cap;
7318 const char *vname;
7319
7321 citystr),
7322 FALSE, "%s", secfile_error());
7324 citystr),
7325 FALSE, "%s", secfile_error());
7326 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7327 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7328 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7329
7330 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7331 citystr),
7332 FALSE, "%s", secfile_error());
7333 pdcity->owner = player_by_number(id);
7334 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7335 "%s has invalid owner (%d); skipping.", citystr, id);
7336
7337 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7338 citystr),
7339 FALSE, "%s", secfile_error());
7340 if (id >= 0) {
7341 pdcity->original = player_by_number(id);
7342 sg_warn_ret_val(NULL != pdcity->original, FALSE,
7343 "%s has invalid original owner (%d); skipping.", citystr, id);
7344 } else {
7345 pdcity->original = nullptr;
7346 }
7347
7349 "%s.id", citystr),
7350 FALSE, "%s", secfile_error());
7352 "%s has invalid id (%d); skipping.", citystr, id);
7353
7355 "%s.size", citystr),
7356 FALSE, "%s", secfile_error());
7357 city_size = (citizens)size; /* set the correct type */
7358 sg_warn_ret_val(size == (int)city_size, FALSE,
7359 "Invalid city size: %d; set to %d.", size, city_size);
7360 vision_site_size_set(pdcity, city_size);
7361
7362 /* Initialise list of improvements */
7363 BV_CLR_ALL(pdcity->improvements);
7364 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7366 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7367 "Invalid length of '%s.improvements' ("
7368 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7369 citystr, strlen(str), loading->improvement.size);
7370 for (i = 0; i < loading->improvement.size; i++) {
7371 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7372 "Undefined value '%c' within '%s.improvements'.",
7373 str[i], citystr)
7374
7375 if (str[i] == '1') {
7376 struct impr_type *pimprove =
7377 improvement_by_rule_name(loading->improvement.order[i]);
7378 if (pimprove) {
7379 BV_SET(pdcity->improvements, improvement_index(pimprove));
7380 }
7381 }
7382 }
7383
7385 "%s.name", citystr);
7386
7387 if (vname != NULL) {
7388 pdcity->name = fc_strdup(vname);
7389 }
7390
7392 "%s.occupied", citystr);
7394 "%s.walls", citystr);
7396 "%s.happy", citystr);
7398 "%s.unhappy", citystr);
7400 "%s.style", citystr);
7401 if (stylename != NULL) {
7403 } else {
7404 pdcity->style = 0;
7405 }
7406 if (pdcity->style < 0) {
7407 pdcity->style = 0;
7408 }
7409
7410 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7411 "%s.city_image", citystr);
7412
7414 "%s.capital", citystr),
7416
7418 pdcity->capital = cap;
7419 } else {
7420 pdcity->capital = CAPITAL_NOT;
7421 }
7422
7423 return TRUE;
7424}
7425
7426/************************************************************************/
7430 struct player *plr)
7431{
7432 int i, plrno = player_number(plr);
7433
7434 /* Check status and return if not OK (sg_success FALSE). */
7435 sg_check_ret();
7436
7438 /* The player can see all, there's no reason to save the private map. */
7439 return;
7440 }
7441
7442 /* Save the map (terrain). */
7443 SAVE_MAP_CHAR(ptile,
7445 saving->file, "player%d.map_t%04d", plrno);
7446
7448 /* Save the map (borders). */
7449 int x, y;
7450
7451 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7453
7454 line[0] = '\0';
7455 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7456 char token[TOKEN_SIZE];
7457 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7458 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7459
7460 if (plrtile == NULL || plrtile->owner == NULL) {
7461 strcpy(token, "-");
7462 } else {
7463 fc_snprintf(token, sizeof(token), "%d",
7464 player_number(plrtile->owner));
7465 }
7466 strcat(line, token);
7467 if (x < MAP_NATIVE_WIDTH) {
7468 strcat(line, ",");
7469 }
7470 }
7471 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7472 plrno, y);
7473 }
7474
7475 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7477
7478 line[0] = '\0';
7479 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7480 char token[TOKEN_SIZE];
7481 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7482 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7483
7484 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7485 strcpy(token, "-");
7486 } else {
7487 fc_snprintf(token, sizeof(token), "%d",
7488 player_number(plrtile->extras_owner));
7489 }
7490 strcat(line, token);
7491 if (x < MAP_NATIVE_WIDTH) {
7492 strcat(line, ",");
7493 }
7494 }
7495 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7496 plrno, y);
7497 }
7498 }
7499
7500 /* Save the map (extras). */
7502 int mod[4];
7503 int l;
7504
7505 for (l = 0; l < 4; l++) {
7506 if (4 * j + 1 > game.control.num_extra_types) {
7507 mod[l] = -1;
7508 } else {
7509 mod[l] = 4 * j + l;
7510 }
7511 }
7512
7513 SAVE_MAP_CHAR(ptile,
7515 map_get_player_tile(ptile, plr)->resource,
7516 mod),
7517 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7519
7520 /* Save the map (update time). */
7521 for (i = 0; i < 4; i++) {
7522 /* put 4-bit segments of 16-bit "updated" field */
7523 SAVE_MAP_CHAR(ptile,
7525 map_get_player_tile(ptile, plr)->last_updated, i),
7526 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7527 }
7528
7529 /* Save known cities. */
7530 i = 0;
7531 whole_map_iterate(&(wld.map), ptile) {
7532 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7533 char impr_buf[B_LAST + 1];
7534 char buf[32];
7535
7536 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7537
7538 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7539 int nat_x, nat_y;
7540
7542 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7543 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7544
7545 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7547 "%s.owner", buf);
7548 if (pdcity->original != nullptr) {
7550 "%s.original", buf);
7551 } else {
7552 secfile_insert_int(saving->file, -1, "%s.original", buf);
7553 }
7554
7556 "%s.size", buf);
7557 secfile_insert_bool(saving->file, pdcity->occupied,
7558 "%s.occupied", buf);
7559 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7560 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7561 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7563 "%s.style", buf);
7564 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7566 "%s.capital", buf);
7567
7568 /* Save improvement list as bitvector. Note that improvement order
7569 * is saved in savefile.improvement.order. */
7570 improvement_iterate(pimprove) {
7571 impr_buf[improvement_index(pimprove)]
7572 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7573 ? '1' : '0';
7575 impr_buf[improvement_count()] = '\0';
7577 "Invalid size of the improvement vector (%s.improvements: "
7578 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7579 buf, strlen(impr_buf), sizeof(impr_buf));
7580 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7581 if (pdcity->name != NULL) {
7582 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7583 }
7584
7585 i++;
7586 }
7588
7589 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7590}
7591
7592/* =======================================================================
7593 * Load / save the researches.
7594 * ======================================================================= */
7595
7596/************************************************************************/
7600{
7601 struct research *presearch;
7602 int count;
7603 int number;
7604 const char *str;
7605 int i, j;
7606 int *vlist_research;
7607
7609 /* Check status and return if not OK (sg_success FALSE). */
7610 sg_check_ret();
7611
7612 /* Initialize all researches. */
7616
7617 /* May be unsaved (e.g. scenario case). */
7618 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7619 for (i = 0; i < count; i++) {
7621 "research.r%d.number", i),
7622 "%s", secfile_error());
7623 presearch = research_by_number(number);
7625 "Invalid research number %d in 'research.r%d.number'",
7626 number, i);
7627
7628 presearch->tech_goal = technology_load(loading->file,
7629 "research.r%d.goal", i);
7631 &presearch->future_tech,
7632 "research.r%d.futuretech", i),
7633 "%s", secfile_error());
7635 &presearch->bulbs_researched,
7636 "research.r%d.bulbs", i),
7637 "%s", secfile_error());
7639 &presearch->bulbs_researching_saved,
7640 "research.r%d.bulbs_before", i),
7641 "%s", secfile_error());
7642 presearch->researching_saved = technology_load(loading->file,
7643 "research.r%d.saved", i);
7644 presearch->researching = technology_load(loading->file,
7645 "research.r%d.now", i);
7647 &presearch->free_bulbs,
7648 "research.r%d.free_bulbs", i),
7649 "%s", secfile_error());
7650
7651 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7652 sg_failure_ret(str != NULL, "%s", secfile_error());
7653 sg_failure_ret(strlen(str) == loading->technology.size,
7654 "Invalid length of 'research.r%d.done' ("
7655 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7656 i, strlen(str), loading->technology.size);
7657 for (j = 0; j < loading->technology.size; j++) {
7658 sg_failure_ret(str[j] == '1' || str[j] == '0',
7659 "Undefined value '%c' within 'research.r%d.done'.",
7660 str[j], i);
7661
7662 if (str[j] == '1') {
7663 struct advance *padvance =
7664 advance_by_rule_name(loading->technology.order[j]);
7665
7666 if (padvance) {
7668 TECH_KNOWN);
7669 }
7670 }
7671 }
7672
7674 size_t count_res;
7675 int tn;
7676
7678 "research.r%d.vbs", i);
7679
7680 for (tn = 0; tn < count_res; tn++) {
7681 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7682
7683 if (padvance != NULL) {
7684 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7685 = vlist_research[tn];
7686 }
7687 }
7688 }
7689 }
7690
7691 /* In case of tech_leakage, we can update research only after all the
7692 * researches have been loaded */
7696}
7697
7698/************************************************************************/
7702{
7703 char invs[A_LAST];
7704 int i = 0;
7705 int *vlist_research;
7706
7708 /* Check status and return if not OK (sg_success FALSE). */
7709 sg_check_ret();
7710
7711 if (saving->save_players) {
7714 "research.r%d.number", i);
7715 technology_save(saving->file, "research.r%d.goal",
7716 i, presearch->tech_goal);
7717 secfile_insert_int(saving->file, presearch->future_tech,
7718 "research.r%d.futuretech", i);
7719 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7720 "research.r%d.bulbs_before", i);
7724 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7728 "research.r%d.vbs", i);
7729 if (vlist_research) {
7731 }
7732 }
7733 technology_save(saving->file, "research.r%d.saved",
7734 i, presearch->researching_saved);
7735 secfile_insert_int(saving->file, presearch->bulbs_researched,
7736 "research.r%d.bulbs", i);
7737 technology_save(saving->file, "research.r%d.now",
7738 i, presearch->researching);
7739 secfile_insert_int(saving->file, presearch->free_bulbs,
7740 "research.r%d.free_bulbs", i);
7741 /* Save technology lists as bytevector. Note that technology order is
7742 * saved in savefile.technology.order */
7743 advance_index_iterate(A_NONE, tech_id) {
7744 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7746 == TECH_KNOWN ? '1' : '0');
7749 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7750 i++;
7752 secfile_insert_int(saving->file, i, "research.count");
7753 }
7754}
7755
7756/* =======================================================================
7757 * Load / save the event cache. Should be the last thing to do.
7758 * ======================================================================= */
7759
7760/************************************************************************/
7764{
7765 /* Check status and return if not OK (sg_success FALSE). */
7766 sg_check_ret();
7767
7768 event_cache_load(loading->file, "event_cache");
7769}
7770
7771/************************************************************************/
7775{
7776 /* Check status and return if not OK (sg_success FALSE). */
7777 sg_check_ret();
7778
7779 if (saving->scenario) {
7780 /* Do _not_ save events in a scenario. */
7781 return;
7782 }
7783
7784 event_cache_save(saving->file, "event_cache");
7785}
7786
7787/* =======================================================================
7788 * Load / save the open treaties
7789 * ======================================================================= */
7790
7791/************************************************************************/
7795{
7796 int tidx;
7797 const char *plr0;
7798
7799 /* Check status and return if not OK (sg_success FALSE). */
7800 sg_check_ret();
7801
7802 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7803 "treaty%d.plr0", tidx)) != NULL ;
7804 tidx++) {
7805 const char *plr1;
7806 const char *ct;
7807 int cidx;
7808 struct player *p0, *p1;
7809
7810 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7811
7812 p0 = player_by_name(plr0);
7813 p1 = player_by_name(plr1);
7814
7815 if (p0 == NULL || p1 == NULL) {
7816 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7817 } else {
7818 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7819
7822
7823 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7824 "treaty%d.clause%d.type",
7825 tidx, cidx)) != NULL ;
7826 cidx++ ) {
7828 const char *plrx;
7829
7830 if (!clause_type_is_valid(type)) {
7831 log_error("Invalid clause type \"%s\"", ct);
7832 } else {
7833 struct player *pgiver = NULL;
7834
7835 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7836 tidx, cidx);
7837
7838 if (!fc_strcasecmp(plrx, plr0)) {
7839 pgiver = p0;
7840 } else if (!fc_strcasecmp(plrx, plr1)) {
7841 pgiver = p1;
7842 } else {
7843 log_error("Clause giver %s is not participant of the treaty"
7844 "between %s and %s", plrx, plr0, plr1);
7845 }
7846
7847 if (pgiver != NULL) {
7848 int value;
7849
7850 value = secfile_lookup_int_default(loading->file, 0,
7851 "treaty%d.clause%d.value",
7852 tidx, cidx);
7853
7854 add_clause(ptreaty, pgiver, type, value, NULL);
7855 }
7856 }
7857 }
7858
7859 /* These must be after clauses have been added so that acceptance
7860 * does not get cleared by what seems like changes to the treaty. */
7862 "treaty%d.accept0", tidx);
7864 "treaty%d.accept1", tidx);
7865 }
7866 }
7867}
7868
7869typedef struct {
7870 int tidx;
7873
7874/************************************************************************/
7877static void treaty_save(struct treaty *ptr, void *data_in)
7878{
7879 char tpath[512];
7880 int cidx = 0;
7882
7883 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7884
7885 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7886 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7887 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7888 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7889
7891 char cpath[512];
7892
7893 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7894
7895 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7896 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7897 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7899}
7900
7901/************************************************************************/
7905{
7906 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7907
7909}
7910
7911/* =======================================================================
7912 * Load / save the history report
7913 * ======================================================================= */
7914
7915/************************************************************************/
7919{
7921 int turn;
7922
7923 /* Check status and return if not OK (sg_success FALSE). */
7924 sg_check_ret();
7925
7926 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7927
7928 if (turn != -2) {
7929 hist->turn = turn;
7930 }
7931
7932 if (turn + 1 >= game.info.turn) {
7933 const char *str;
7934
7935 str = secfile_lookup_str(loading->file, "history.title");
7936 sg_failure_ret(str != NULL, "%s", secfile_error());
7937 sz_strlcpy(hist->title, str);
7938 str = secfile_lookup_str(loading->file, "history.body");
7939 sg_failure_ret(str != NULL, "%s", secfile_error());
7940 sz_strlcpy(hist->body, str);
7941 }
7942}
7943
7944/************************************************************************/
7947static void sg_save_history(struct savedata *saving)
7948{
7950
7951 secfile_insert_int(saving->file, hist->turn, "history.turn");
7952
7953 if (hist->turn + 1 >= game.info.turn) {
7954 secfile_insert_str(saving->file, hist->title, "history.title");
7955 secfile_insert_str(saving->file, hist->body, "history.body");
7956 }
7957}
7958
7959/* =======================================================================
7960 * Load / save the mapimg definitions.
7961 * ======================================================================= */
7962
7963/************************************************************************/
7966static void sg_load_mapimg(struct loaddata *loading)
7967{
7968 int mapdef_count, i;
7969
7970 /* Check status and return if not OK (sg_success FALSE). */
7971 sg_check_ret();
7972
7973 /* Clear all defined map images. */
7974 while (mapimg_count() > 0) {
7975 mapimg_delete(0);
7976 }
7977
7979 "mapimg.count");
7980 log_verbose("Saved map image definitions: %d.", mapdef_count);
7981
7982 if (0 >= mapdef_count) {
7983 return;
7984 }
7985
7986 for (i = 0; i < mapdef_count; i++) {
7987 const char *p;
7988
7989 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7990 if (NULL == p) {
7991 log_verbose("[Mapimg %4d] Missing definition.", i);
7992 continue;
7993 }
7994
7995 if (!mapimg_define(p, FALSE)) {
7996 log_error("Invalid map image definition %4d: %s.", i, p);
7997 }
7998
7999 log_verbose("Mapimg %4d loaded.", i);
8000 }
8001}
8002
8003/************************************************************************/
8006static void sg_save_mapimg(struct savedata *saving)
8007{
8008 /* Check status and return if not OK (sg_success FALSE). */
8009 sg_check_ret();
8010
8011 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8012 if (mapimg_count() > 0) {
8013 int i;
8014
8015 for (i = 0; i < mapimg_count(); i++) {
8016 char buf[MAX_LEN_MAPDEF];
8017
8018 mapimg_id2str(i, buf, sizeof(buf));
8019 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8020 }
8021 }
8022}
8023
8024/* =======================================================================
8025 * Sanity checks for loading / saving a game.
8026 * ======================================================================= */
8027
8028/************************************************************************/
8032{
8033 int players;
8034
8035 /* Check status and return if not OK (sg_success FALSE). */
8036 sg_check_ret();
8037
8038 if (game.info.is_new_game) {
8039 /* Nothing to do for new games (or not started scenarios). */
8040 return;
8041 }
8042
8043 /* Old savegames may have maxplayers lower than current player count,
8044 * fix. */
8045 players = normal_player_count();
8046 if (game.server.max_players < players) {
8047 log_verbose("Max players lower than current players, fixing");
8048 game.server.max_players = players;
8049 }
8050
8051 /* Fix ferrying sanity */
8052 players_iterate(pplayer) {
8053 unit_list_iterate_safe(pplayer->units, punit) {
8056 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8062 }
8065
8066 /* Fix stacking issues. We don't rely on the savegame preserving
8067 * alliance invariants (old savegames often did not) so if there are any
8068 * unallied units on the same tile we just bounce them. */
8069 players_iterate(pplayer) {
8071 resolve_unit_stacks(pplayer, aplayer, TRUE);
8074
8075 /* Recalculate the potential buildings for each city. Has caused some
8076 * problems with game random state.
8077 * This also changes the game state if you save the game directly after
8078 * loading it and compare the results. */
8079 players_iterate(pplayer) {
8080 /* Building advisor needs data phase open in order to work */
8081 adv_data_phase_init(pplayer, FALSE);
8082 building_advisor(pplayer);
8083 /* Close data phase again so it can be opened again when game starts. */
8084 adv_data_phase_done(pplayer);
8086
8087 /* Prevent a buggy or intentionally crafted save game from crashing
8088 * Freeciv. See hrm Bug #887748 */
8089 players_iterate(pplayer) {
8090 city_list_iterate(pplayer->cities, pcity) {
8091 worker_task_list_iterate(pcity->task_reqs, ptask) {
8092 if (!worker_task_is_sane(ptask)) {
8093 log_error("[city id: %d] Bad worker task %d.",
8094 pcity->id, ptask->act);
8095 worker_task_list_remove(pcity->task_reqs, ptask);
8096 free(ptask);
8097 ptask = NULL;
8098 }
8102
8103 /* Check worked tiles map */
8104#ifdef FREECIV_DEBUG
8105 if (loading->worked_tiles != NULL) {
8106 /* check the entire map for unused worked tiles */
8107 whole_map_iterate(&(wld.map), ptile) {
8108 if (loading->worked_tiles[ptile->index] != -1) {
8109 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8110 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8111 }
8113 }
8114#endif /* FREECIV_DEBUG */
8115
8116 /* Check researching technologies and goals. */
8118 if (presearch->researching != A_UNSET
8119 && !is_future_tech(presearch->researching)
8120 && (valid_advance_by_number(presearch->researching) == NULL
8122 != TECH_PREREQS_KNOWN))) {
8123 log_sg(_("%s had invalid researching technology."),
8125 presearch->researching = A_UNSET;
8126 }
8127 if (presearch->tech_goal != A_UNSET
8128 && !is_future_tech(presearch->tech_goal)
8129 && (valid_advance_by_number(presearch->tech_goal) == NULL
8132 == TECH_KNOWN))) {
8133 log_sg(_("%s had invalid technology goal."),
8135 presearch->tech_goal = A_UNSET;
8136 }
8137
8140
8141 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8142 players_iterate(pplayer) {
8143 int unique_count[U_LAST];
8144
8145 memset(unique_count, 0, sizeof(unique_count));
8146
8147 unit_list_iterate(pplayer->units, punit) {
8150
8153 log_sg(_("%s has multiple units of type %s though it should be possible "
8154 "to have only one."),
8156 }
8159
8160 players_iterate(pplayer) {
8161 unit_list_iterate_safe(pplayer->units, punit) {
8163 punit->orders.list)) {
8164 log_sg("Invalid unit orders for unit %d.", punit->id);
8166 }
8169
8170 /* Check max rates (rules may have changed since saving) */
8171 players_iterate(pplayer) {
8174
8175 if (0 == strlen(server.game_identifier)
8176 || !is_base64url(server.game_identifier)) {
8177 /* This uses fc_rand(), so random state has to be initialized before. */
8178 randomize_base64url_string(server.game_identifier,
8179 sizeof(server.game_identifier));
8180 }
8181
8182 /* Restore game random state, just in case various initialization code
8183 * inexplicably altered the previously existing state. */
8184 if (!game.info.is_new_game) {
8185 fc_rand_set_state(loading->rstate);
8186 }
8187
8188 /* At the end do the default sanity checks. */
8189 sanity_check();
8190}
8191
8192/************************************************************************/
8196{
8197 /* Check status and return if not OK (sg_success FALSE). */
8198 sg_check_ret();
8199}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
static struct action * actions[MAX_NUM_ACTIONS]
Definition actions.c:57
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:417
#define NUM_ACTIONS
Definition actions.h:59
#define action_id_get_activity(act_id)
Definition actions.h:462
#define ACTION_NONE
Definition actions.h:55
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:566
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
@ BODYGUARD_NONE
Definition aiguard.c:37
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:142
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:174
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
void citizens_init(struct city *pcity)
Definition citizens.c:32
void citizens_update(struct city *pcity, struct player *plr)
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:148
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c: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:3455
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:3382
void destroy_city_virtual(struct city *pcity)
Definition city.c:3541
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:514
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define cities_iterate(pcity)
Definition city.h:509
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:83
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define output_type_iterate(output)
Definition city.h:842
#define FREE_WORKED_TILES
Definition city.h:879
#define MAX_CITY_SIZE
Definition city.h:103
#define city_list_iterate_end
Definition city.h:507
#define I_NEVER
Definition city.h:244
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define output_type_iterate_end
Definition city.h:848
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2776
bool send_city_suppression(bool now)
Definition citytools.c:2170
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:136
void city_thaw_workers(struct city *pcity)
Definition citytools.c:146
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2847
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3451
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:366
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:851
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
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
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:108
struct treaty * ptreaty
Definition diplodlg_g.h:28
void treaty_add(struct treaty *ptreaty)
Definition diptreaty.c:377
void init_treaty(struct treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
bool add_clause(struct treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
#define clause_list_iterate_end
Definition diptreaty.h:73
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:71
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1128
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h:213
int Tech_type_id
Definition fc_types.h:236
unsigned char citizens
Definition fc_types.h:247
#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:245
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct unit * game_unit_by_number(int id)
Definition game.c:115
void initialize_globals(void)
Definition game.c:688
struct city * game_city_by_number(int id)
Definition game.c:106
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:599
#define GAME_DEFAULT_SCORETURN
Definition game.h:583
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:598
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:601
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:600
#define GAME_DEFAULT_RULESETDIR
Definition game.h:677
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:603
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:618
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c:502
void adv_city_alloc(struct city *pcity)
Definition infracache.c:489
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_fatal(message,...)
Definition log.h:101
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1804
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2021
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1820
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1843
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1916
void map_init_topology(struct civ_map *nmap)
Definition map.c:315
void main_map_allocate(void)
Definition map.c:534
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_startpos_count(void)
Definition map.c:2008
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1903
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1787
#define map_startpos_iterate(NAME_psp)
Definition map.h:136
#define map_startpos_iterate_end
Definition map.h:139
#define whole_map_iterate(_map, _tile)
Definition map.h:573
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define whole_map_iterate_end
Definition map.h:582
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:1226
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1472
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2171
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:899
bool send_tile_suppression(bool now)
Definition maphand.c:473
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:343
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1201
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1403
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1372
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1183
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1164
void map_calculate_borders(void)
Definition maphand.c:2329
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1637
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1314
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1207
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:318
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:1480
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:1996
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:1409
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1497
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1489
#define players_iterate_end
Definition player.h:542
dipl_reason
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:194
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:194
#define players_iterate(_pplayer)
Definition player.h:537
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:560
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define player_slots_iterate(_pslot)
Definition player.h:528
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:562
#define players_iterate_alive_end
Definition player.h:552
#define player_slots_iterate_end
Definition player.h:532
#define players_iterate_alive(_pplayer)
Definition player.h:547
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2270
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1896
int normal_player_count(void)
Definition plrhand.c:3209
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2059
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2458
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2408
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3255
void shuffle_players(void)
Definition plrhand.c:2383
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1945
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1620
void assign_player_colors(void)
Definition plrhand.c:1736
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3242
void fit_nationset_to_players(void)
Definition plrhand.c:2664
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
bool fc_rand_is_init(void)
Definition rand.c:200
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:51
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
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,...)
float secfile_lookup_float_default(const struct section_file *secfile, float def, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct 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,...)
#define secfile_insert_float(secfile, value, path,...)
struct history_report * history_report_get(void)
Definition report.c:1859
const char * universal_rule_name(const struct universal *psource)
const char * universal_type_rule_name(const struct universal *psource)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c: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:1353
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 ruleload.c:9112
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:230
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:240
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:151
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:252
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:202
#define sg_check_ret(...)
Definition savecompat.h:150
#define sg_warn(condition, message,...)
Definition savecompat.h:160
#define hex_chars
Definition savecompat.h:205
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
#define sg_regr(fixversion, message,...)
Definition savecompat.h:193
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:146
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:171
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:431
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:7947
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1198
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2755
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3021
static void unit_ordering_apply(void)
Definition savegame3.c:1079
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3713
static struct loaddata * loaddata_new(struct section_file *file)
Definition savegame3.c:584
static void worklist_save(struct section_file *file, const struct worklist *pwl, int max_length, const char *path,...)
Definition savegame3.c:1012
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3593
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3252
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:897
#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:2814
static enum unit_orders char2order(char order)
Definition savegame3.c:710
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:918
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:3084
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3554
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4168
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:219
static void treaty_save(struct treaty *ptr, void *data_in)
Definition savegame3.c:7877
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5661
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5613
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5045
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2920
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:6136
static char activity2char(int activity)
Definition savegame3.c:823
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:679
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1336
static enum unit_activity char2activity(char activity)
Definition savegame3.c:874
static void unit_ordering_calc(void)
Definition savegame3.c:1050
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2664
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6067
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1250
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2435
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3197
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7599
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3510
#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:2041
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2394
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1775
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6635
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7918
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7904
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3374
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7701
static void savegame3_save_real(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:527
#define TOKEN_SIZE
Definition savegame3.c:276
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2473
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2499
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2088
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:698
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4229
static char order2char(enum unit_orders order)
Definition savegame3.c:737
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7794
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2587
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1133
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6688
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2243
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1165
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1263
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7429
static enum direction8 char2dir(char dir)
Definition savegame3.c:761
#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:5164
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1227
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8195
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7966
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6954
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7034
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2064
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2875
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7117
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2960
static void worklist_load(struct section_file *file, int wlist_max_length, struct worklist *pwl, const char *path,...)
Definition savegame3.c:966
static void sg_save_mapimg(struct savedata *saving)
Definition savegame3.c:8006
static const char savefile_options_default[]
Definition savegame3.c:278
static char dir2char(enum direction8 dir)
Definition savegame3.c:790
static bool sg_load_player_vision_city(struct loaddata *loading, struct player *plr, struct vision_site *pdcity, const char *citystr)
Definition savegame3.c:7307
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2702
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3110
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:623
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3973
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:2988
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1299
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7774
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3052
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8031
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7763
void savegame3_load(struct section_file *file)
Definition savegame3.c:458
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1100
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2263
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4719
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2484
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2680
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3650
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:4913
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4825
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
sex_t sex_by_name(const char *name)
Definition sex.c:27
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
bool str_to_int(const char *str, int *pint)
Definition shared.c:515
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
bool is_base64url(const char *s)
Definition shared.c:321
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1923
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:343
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX_LEN_PATH
Definition shared.h:32
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
@ SSHIP_LAUNCHED
Definition spaceship.h:85
@ SSHIP_NONE
Definition spaceship.h:84
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c: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:3497
const char * aifill(int amount)
Definition srv_main.c:2506
bool game_was_started(void)
Definition srv_main.c:354
void identity_number_reserve(int id)
Definition srv_main.c:2035
struct server_arguments srvarg
Definition srv_main.c:181
void init_game_seed(void)
Definition srv_main.c:208
void update_nations_with_startpos(void)
Definition srv_main.c:2311
enum server_states server_state(void)
Definition srv_main.c:338
void server_game_free(void)
Definition srv_main.c:3521
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
Definition city.h:317
size_t length
Definition city.h:414
bool multiresearch
Definition game.h:166
bool last_updated_year
Definition game.h:239
struct civ_game::@32::@36::@38 save_options
int world_peace_start
Definition game.h:241
float turn_change_time
Definition game.h:221
bool vision_reveal_tiles
Definition game.h:203
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:237
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:210
char rulesetdir[MAX_LEN_NAME]
Definition game.h:242
int additional_phase_seconds
Definition game.h:215
struct section_file * luadata
Definition game.h:250
int scoreturn
Definition game.h:228
randseed seed
Definition game.h:230
int dbid
Definition game.h:251
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:206
struct timer * phase_timer
Definition game.h:214
unsigned revealmap
Definition game.h:180
char orig_game_version[MAX_LEN_NAME]
Definition game.h:224
bool save_known
Definition game.h:262
bool foggedborders
Definition game.h:150
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:208
struct civ_game::@32::@36 server
int timeoutinc
Definition game.h:207
int phase_mode_stored
Definition game.h:219
int max_players
Definition game.h:159
bool save_starts
Definition game.h:264
int timeoutintinc
Definition game.h:209
randseed seed
Definition map_types.h:105
bool have_resources
Definition map_types.h:121
bool altitude_info
Definition map_types.h:74
struct civ_map::@43::@45 server
bool have_huts
Definition map_types.h:120
enum map_generator generator
Definition map_types.h:111
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
int changed_to_times
Definition government.h: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:116
struct ai_trait * traits
Definition player.h:126
enum barbarian_type barbarian_type
Definition player.h:122
int science_cost
Definition player.h:119
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:124
int expand
Definition player.h:118
int fuzzy
Definition player.h:117
enum diplstate_type type
Definition player.h:199
int infra_points
Definition player.h:67
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int angry
Definition player.h:89
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:281
int bulbs_last_turn
Definition player.h:351
struct player_ai ai_common
Definition player.h:288
bv_plr_flags flags
Definition player.h:292
bool is_male
Definition player.h:257
int wonders[B_LAST]
Definition player.h:305
bool unassigned_ranked
Definition player.h:255
struct government * target_government
Definition player.h:259
int autoselect_weight
Definition player.h:299
char username[MAX_LEN_NAME]
Definition player.h:252
int revolution_finishes
Definition player.h:273
int nturns_idle
Definition player.h:265
struct government * government
Definition player.h:258
struct team * team
Definition player.h:261
int turns_alive
Definition player.h:266
const struct ai_type * ai
Definition player.h:289
struct unit_list * units
Definition player.h:282
char ranked_username[MAX_LEN_NAME]
Definition player.h:254
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
bv_player real_embassy
Definition player.h:277
struct player_economic economic
Definition player.h:284
struct player_spaceship spaceship
Definition player.h:286
struct attribute_block_s attribute_block
Definition player.h:307
struct player_score score
Definition player.h:283
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:314
struct nation_type * nation
Definition player.h:260
struct nation_style * style
Definition player.h:279
bool border_vision
Definition player.h:327
bool phase_done
Definition player.h:263
struct adv_data * adv
Definition player.h:334
int history
Definition player.h:316
struct player::@72::@74 server
char orig_username[MAX_LEN_NAME]
Definition player.h:347
int last_war_action
Definition player.h:270
struct rgbcolor * rgb
Definition player.h:312
bool unassigned_user
Definition player.h:253
const char * save_reason
Definition savegame3.c: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:40
Definition team.c:40
char identifier
Definition terrain.h:84
Definition tile.h:50
int altitude
Definition tile.h:65
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int infra_turns
Definition tile.h:62
struct extra_type * placing
Definition tile.h:61
struct tile * claimer
Definition tile.h:64
Definition timing.c:81
enum route_direction dir
Definition traderoutes.h:86
struct section_file * file
Definition savegame3.c:7871
struct player * plr1
Definition diptreaty.h:82
struct clause_list * clauses
Definition diptreaty.h:84
bool accept1
Definition diptreaty.h:83
struct player * plr0
Definition diptreaty.h:82
bool accept0
Definition diptreaty.h:83
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int length
Definition unit.h:198
int upkeep[O_LAST]
Definition unit.h:150
bool has_orders
Definition unit.h:196
enum action_decision action_decision_want
Definition unit.h:205
struct unit::@83::@86 server
int battlegroup
Definition unit.h:194
struct unit::@82 orders
enum unit_activity activity
Definition unit.h:159
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
enum gen_action action
Definition unit.h:160
int ord_city
Definition unit.h:245
bool moved
Definition unit.h:176
int ord_map
Definition unit.h:244
int index
Definition unit.h:198
struct vision * vision
Definition unit.h:247
bool vigilant
Definition unit.h:200
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
struct extra_type * changed_from_target
Definition unit.h:173
int current_form_turn
Definition unit.h:211
bool stay
Definition unit.h:208
enum direction8 facing
Definition unit.h:144
struct tile * tile
Definition unit.h:142
struct extra_type * activity_target
Definition unit.h:167
int activity_count
Definition unit.h:165
struct unit_order * list
Definition unit.h:201
enum unit_activity changed_from
Definition unit.h:171
struct unit_adv * adv
Definition unit.h:239
struct player * nationality
Definition unit.h:146
bool repeat
Definition unit.h:199
int homecity
Definition unit.h:148
bool paradropped
Definition unit.h:177
bool done_moving
Definition unit.h:184
int birth_turn
Definition unit.h:210
struct goods_type * carrying
Definition unit.h:189
struct tile * goto_tile
Definition unit.h:157
struct tile * action_decision_tile
Definition unit.h:206
int veteran
Definition unit.h:154
int changed_from_count
Definition unit.h:172
enum server_side_agent ssa_controller
Definition unit.h:175
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:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#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:309
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:246
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:273
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:274
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:242
void init_tech(struct research *research, bool update)
Definition techtools.c: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:266
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:272
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1097
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:89
#define tile_worked(_tile)
Definition tile.h:115
#define tile_terrain(_tile)
Definition tile.h:111
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
void timer_stop(struct timer *t)
Definition timing.c:305
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:379
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
void free_unit_orders(struct unit *punit)
Definition unit.c:1806
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2447
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1274
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2518
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:865
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1661
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2726
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target, enum gen_action trigger_action)
Definition unit.c:1132
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1766
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1284
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1114
#define unit_tile(_pu)
Definition unit.h:404
#define BATTLEGROUP_NONE
Definition unit.h:193
unit_orders
Definition unit.h:38
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#define unit_owner(_pu)
Definition unit.h:403
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:1401
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5004
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1225
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1062
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1771
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1591
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2629
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:1564
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
#define unit_type_iterate(_p)
Definition unittype.h:860
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:867
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:129
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT