Freeciv-3.4
Loading...
Searching...
No Matches
savegame3.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14/*
15 This file includes the definition of a new savegame format introduced with
16 3.0. It is defined by the mandatory option '+version3'. The main load
17 function checks if this option is present. If not, the old (pre-3.0)
18 loading routines are used.
19 The format version is also saved in the settings section of the savefile, as an
20 integer (savefile.version). The integer is used to determine the version
21 of the savefile.
22
23 Structure of this file:
24
25 - The main function for saving is savegame3_save().
26
27 - The real work is done by savegame3_load() and savegame3_save_real().
28 This function call all submodules (settings, players, etc.)
29
30 - The remaining part of this file is split into several sections:
31 * helper functions
32 * save / load functions for all submodules (and their subsubmodules)
33
34 - If possible, all functions for load / save submodules should exit in
35 pairs named sg_load_<submodule> and sg_save_<submodule>. If one is not
36 needed please add a comment why.
37
38 - The submodules can be further divided as:
39 sg_load_<submodule>_<subsubmodule>
40
41 - If needed (due to static variables in the *.c files) these functions
42 can be located in the corresponding source files (as done for the settings
43 and the event_cache).
44
45 Creating a savegame:
46
47 (nothing at the moment)
48
49 Loading a savegame:
50
51 - The status of the process is saved within the static variable
52 'sg_success'. This variable is set to TRUE within savegame3_load().
53 If you encounter an error use sg_failure_*() to set it to FALSE and
54 return an error message. Furthermore, sg_check_* should be used at the
55 start of each (submodule) function to return if previous functions failed.
56
57 - While the loading process dependencies between different modules exits.
58 They can be handled within the struct loaddata *loading which is used as
59 first argument for all sg_load_*() function. Please indicate the
60 dependencies within the definition of this struct.
61
62*/
63
64#ifdef HAVE_CONFIG_H
65#include <fc_config.h>
66#endif
67
68#include <ctype.h>
69#include <stdarg.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73
74/* utility */
75#include "bitvector.h"
76#include "fcintl.h"
77#include "idex.h"
78#include "log.h"
79#include "mem.h"
80#include "rand.h"
81#include "registry.h"
82#include "shared.h"
83#include "support.h" /* bool type */
84#include "timing.h"
85
86/* common */
87#include "achievements.h"
88#include "ai.h"
89#include "bitvector.h"
90#include "capability.h"
91#include "citizens.h"
92#include "city.h"
93#include "counters.h"
94#include "game.h"
95#include "government.h"
96#include "map.h"
97#include "mapimg.h"
98#include "movement.h"
99#include "multipliers.h"
100#include "packets.h"
101#include "research.h"
102#include "rgbcolor.h"
103#include "sex.h"
104#include "specialist.h"
105#include "unit.h"
106#include "unitlist.h"
107#include "version.h"
108
109/* server */
110#include "barbarian.h"
111#include "citizenshand.h"
112#include "citytools.h"
113#include "cityturn.h"
114#include "diplhand.h"
115#include "maphand.h"
116#include "meta.h"
117#include "notify.h"
118#include "plrhand.h"
119#include "report.h"
120#include "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/************************************************************************/
1263 const char *path, int plrno)
1264{
1265 char path_with_name[128];
1266 const char *name;
1267 struct advance *padvance;
1268
1270 "%s_name", path);
1271
1273
1274 if (!name || name[0] == '\0') {
1275 /* Used by researching_saved */
1276 return A_UNKNOWN;
1277 }
1278 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1279 return A_FUTURE;
1280 }
1281 if (fc_strcasecmp(name, "A_NONE") == 0) {
1282 return A_NONE;
1283 }
1284 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1285 return A_UNSET;
1286 }
1287
1290 "%s: unknown technology \"%s\".", path_with_name, name);
1291
1292 return advance_number(padvance);
1293}
1294
1295/************************************************************************/
1298static void technology_save(struct section_file *file,
1299 const char *path, int plrno, Tech_type_id tech)
1300{
1301 char path_with_name[128];
1302 const char *name;
1303
1305 "%s_name", path);
1306
1307 switch (tech) {
1308 case A_UNKNOWN: /* Used by researching_saved */
1309 name = "";
1310 break;
1311 case A_NONE:
1312 name = "A_NONE";
1313 break;
1314 case A_UNSET:
1315 name = "A_UNSET";
1316 break;
1317 case A_FUTURE:
1318 name = "A_FUTURE";
1319 break;
1320 default:
1322 break;
1323 }
1324
1326}
1327
1328/* =======================================================================
1329 * Load / save savefile data.
1330 * ======================================================================= */
1331
1332/************************************************************************/
1336{
1337 int i;
1338 const char *terr_name;
1339 bool ruleset_datafile;
1341 const char *str;
1342
1343 /* Check status and return if not OK (sg_success FALSE). */
1344 sg_check_ret();
1345
1346 /* Load savefile options. */
1347 loading->secfile_options
1348 = secfile_lookup_str(loading->file, "savefile.options");
1349
1350 /* We don't need these entries, but read them anyway to avoid
1351 * warnings about unread secfile entries. */
1352 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1353 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1354
1355 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1357
1358 if (game.scenario.datafile[0] != '\0') {
1360 } else {
1362 }
1363
1366 const char *req_caps;
1367
1370 /* Failed to load correct ruleset */
1371 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1373 }
1374
1375 req_caps = secfile_lookup_str_default(loading->file, "",
1376 "scenario.ruleset_caps");
1377 strncpy(game.scenario.req_caps, req_caps,
1378 sizeof(game.scenario.req_caps) - 1);
1379 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1380
1381 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1382 /* Current ruleset lacks required capabilities. */
1383 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1384 log_normal(_("Ruleset has capabilities: %s"),
1386 /* TRANS: ... ruleset dir ... scenario name ... */
1387 log_error(_("Current ruleset %s not compatible with the scenario %s."
1388 " Trying to switch to the ruleset specified by the"
1389 " scenario."),
1391
1393 }
1394 }
1395
1398 const char *ruleset, *alt_dir;
1399
1402 "savefile.rulesetdir");
1403
1404 /* Load ruleset. */
1406 if (!strcmp("default", game.server.rulesetdir)) {
1407 /* Here 'default' really means current default.
1408 * Saving happens with real ruleset name, so savegames containing this
1409 * are special scenarios. */
1411 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1413 }
1414
1415 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1416 "savefile.ruleset_alt_dir");
1417
1418 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1419 if (alt_dir) {
1421 _("Failed to load either of rulesets '%s' or '%s' "
1422 "needed for savegame."),
1423 ruleset, alt_dir);
1424 } else {
1426 _("Failed to load ruleset '%s' needed for savegame."),
1427 ruleset);
1428 }
1429 }
1430
1432 /* TRANS: ruleset dir */
1433 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1434 }
1435 }
1436
1437 /* Remove all aifill players. Correct number of them get created later
1438 * with correct skill level etc. */
1439 (void) aifill(0);
1440
1441 /* Time to load scenario specific luadata */
1442 if (game.scenario.datafile[0] != '\0') {
1443 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1445 } else {
1446 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1447 const struct strvec **path;
1448 const char *found = NULL;
1449 char testfile[MAX_LEN_PATH];
1450 struct section_file *secfile;
1451
1452 for (path = paths; found == NULL && *path != NULL; path++) {
1453 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1454
1455 found = fileinfoname(*path, testfile);
1456 }
1457
1458 if (found == NULL) {
1459 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1460 sg_success = FALSE;
1461 return;
1462 }
1463
1464 secfile = secfile_load(found, FALSE);
1465 if (secfile == NULL) {
1466 log_error(_("Failed to load scenario luadata file %s.luadata"),
1468 sg_success = FALSE;
1469 return;
1470 }
1471
1472 game.server.luadata = secfile;
1473 }
1474 }
1475
1477 "savefile.dbid");
1478
1479 /* This is in the savegame only if the game has been started before savegame3.c time,
1480 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1482 "savefile.last_updated_as_year");
1483
1484 /* Load improvements. */
1485 loading->improvement.size
1487 "savefile.improvement_size");
1488 if (loading->improvement.size) {
1489 loading->improvement.order
1490 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1491 "savefile.improvement_vector");
1492 sg_failure_ret(loading->improvement.size != 0,
1493 "Failed to load improvement order: %s",
1494 secfile_error());
1495 }
1496
1497 /* Load technologies. */
1498 loading->technology.size
1500 "savefile.technology_size");
1501 if (loading->technology.size) {
1502 loading->technology.order
1503 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1504 "savefile.technology_vector");
1505 sg_failure_ret(loading->technology.size != 0,
1506 "Failed to load technology order: %s",
1507 secfile_error());
1508 }
1509
1510 /* Load Activities. */
1511 loading->activities.size
1513 "savefile.activities_size");
1514 if (loading->activities.size) {
1515 loading->activities.order
1516 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1517 "savefile.activities_vector");
1518 sg_failure_ret(loading->activities.size != 0,
1519 "Failed to load activity order: %s",
1520 secfile_error());
1521 }
1522
1523 /* Load traits. */
1524 loading->trait.size
1526 "savefile.trait_size");
1527 if (loading->trait.size) {
1528 loading->trait.order
1529 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1530 "savefile.trait_vector");
1531 sg_failure_ret(loading->trait.size != 0,
1532 "Failed to load trait order: %s",
1533 secfile_error());
1534 }
1535
1536 /* Load extras. */
1537 loading->extra.size
1539 "savefile.extras_size");
1540 if (loading->extra.size) {
1541 const char **modname;
1542 size_t nmod;
1543 int j;
1544
1545 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1546 "savefile.extras_vector");
1547 sg_failure_ret(loading->extra.size != 0,
1548 "Failed to load extras order: %s",
1549 secfile_error());
1551 "Number of extras defined by the ruleset (= %d) are "
1552 "lower than the number in the savefile (= %d).",
1553 game.control.num_extra_types, (int)loading->extra.size);
1554 /* make sure that the size of the array is divisible by 4 */
1555 nmod = 4 * ((loading->extra.size + 3) / 4);
1556 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1557 for (j = 0; j < loading->extra.size; j++) {
1558 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1559 }
1560 free(modname);
1561 for (; j < nmod; j++) {
1562 loading->extra.order[j] = NULL;
1563 }
1564 }
1565
1566 /* Load multipliers. */
1567 loading->multiplier.size
1569 "savefile.multipliers_size");
1570 if (loading->multiplier.size) {
1571 const char **modname;
1572 int j;
1573
1574 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1575 "savefile.multipliers_vector");
1576 sg_failure_ret(loading->multiplier.size != 0,
1577 "Failed to load multipliers order: %s",
1578 secfile_error());
1579 /* It's OK for the set of multipliers in the savefile to differ
1580 * from those in the ruleset. */
1581 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1582 sizeof(*loading->multiplier.order));
1583 for (j = 0; j < loading->multiplier.size; j++) {
1584 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1585 if (!loading->multiplier.order[j]) {
1586 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1587 "discarding", modname[j]);
1588 }
1589 }
1590 free(modname);
1591 }
1592
1593 /* Load specialists. */
1594 loading->specialist.size
1596 "savefile.specialists_size");
1597 if (loading->specialist.size) {
1598 const char **modname;
1599 size_t nmod;
1600 int j;
1601
1602 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1603 "savefile.specialists_vector");
1604 sg_failure_ret(loading->specialist.size != 0,
1605 "Failed to load specialists order: %s",
1606 secfile_error());
1608 "Number of specialists defined by the ruleset (= %d) are "
1609 "lower than the number in the savefile (= %d).",
1610 game.control.num_specialist_types, (int)loading->specialist.size);
1611 /* make sure that the size of the array is divisible by 4 */
1612 /* That's not really needed with specialists at the moment, but done this way
1613 * for consistency with other types, and to be prepared for the time it needs
1614 * to be this way. */
1615 nmod = 4 * ((loading->specialist.size + 3) / 4);
1616 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1617 for (j = 0; j < loading->specialist.size; j++) {
1618 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1619 }
1620 free(modname);
1621 for (; j < nmod; j++) {
1622 loading->specialist.order[j] = NULL;
1623 }
1624 }
1625
1626 /* Load action order. */
1627 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1628 "savefile.action_size");
1629
1630 sg_failure_ret(loading->action.size > 0,
1631 "Failed to load action order: %s",
1632 secfile_error());
1633
1634 if (loading->action.size) {
1635 const char **modname;
1636 int j;
1637
1638 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1639 "savefile.action_vector");
1640
1641 loading->action.order = fc_calloc(loading->action.size,
1642 sizeof(*loading->action.order));
1643
1644 for (j = 0; j < loading->action.size; j++) {
1646
1647 if (real_action) {
1648 loading->action.order[j] = real_action->id;
1649 } else {
1650 log_sg("Unknown action \'%s\'", modname[j]);
1651 loading->action.order[j] = ACTION_NONE;
1652 }
1653 }
1654
1655 free(modname);
1656 }
1657
1658 /* Load action decision order. */
1659 loading->act_dec.size
1661 "savefile.action_decision_size");
1662
1663 sg_failure_ret(loading->act_dec.size > 0,
1664 "Failed to load action decision order: %s",
1665 secfile_error());
1666
1667 if (loading->act_dec.size) {
1668 const char **modname;
1669 int j;
1670
1671 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1672 "savefile.action_decision_vector");
1673
1674 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1675 sizeof(*loading->act_dec.order));
1676
1677 for (j = 0; j < loading->act_dec.size; j++) {
1678 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1680 }
1681
1682 free(modname);
1683 }
1684
1685 /* Load server side agent order. */
1686 loading->ssa.size
1688 "savefile.server_side_agent_size");
1689
1690 sg_failure_ret(loading->ssa.size > 0,
1691 "Failed to load server side agent order: %s",
1692 secfile_error());
1693
1694 if (loading->ssa.size) {
1695 const char **modname;
1696 int j;
1697
1698 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1699 "savefile.server_side_agent_list");
1700
1701 loading->ssa.order = fc_calloc(loading->ssa.size,
1702 sizeof(*loading->ssa.order));
1703
1704 for (j = 0; j < loading->ssa.size; j++) {
1705 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1707 }
1708
1709 free(modname);
1710 }
1711
1712 /* Load city options order. */
1713 loading->coptions.size
1715 "savefile.city_options_size");
1716
1717 sg_failure_ret(loading->coptions.size > 0,
1718 "Failed to load city options order: %s",
1719 secfile_error());
1720
1721 if (loading->coptions.size) {
1722 const char **modname;
1723 int j;
1724
1725 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1726 "savefile.city_options_vector");
1727
1728 loading->coptions.order = fc_calloc(loading->coptions.size,
1729 sizeof(*loading->coptions.order));
1730
1731 for (j = 0; j < loading->coptions.size; j++) {
1732 loading->coptions.order[j] = city_options_by_name(modname[j],
1734 }
1735
1736 free(modname);
1737 }
1738
1739 /* Terrain identifiers */
1741 pterr->identifier_load = '\0';
1743
1744 i = 0;
1746 "savefile.terrident%d.name", i)) != NULL) {
1748
1749 if (pterr != NULL) {
1750 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1751 "savefile.terrident%d.identifier", i);
1752
1753 pterr->identifier_load = *iptr;
1754 } else {
1755 log_error("Identifier for unknown terrain type %s.", terr_name);
1756 }
1757 i++;
1758 }
1759
1762 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1763 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1764 "%s and %s share a saved identifier",
1766 }
1769}
1770
1771/************************************************************************/
1775{
1776 int i;
1777
1778 /* Check status and return if not OK (sg_success FALSE). */
1779 sg_check_ret();
1780
1781 /* Save savefile options. */
1783
1784 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1785
1786 /* Save reason of the savefile generation. */
1787 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1788
1789 /* Save as accurate freeciv revision information as possible */
1790 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1791
1792 /* Freeciv version used in the very first launch of this game -
1793 * or even saving in pregame. */
1795 "savefile.orig_version");
1796
1797 /* Save rulesetdir at this point as this ruleset is required by this
1798 * savefile. */
1799 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1800
1801 if (game.control.version[0] != '\0') {
1802 /* Current ruleset has version information, save it.
1803 * This is never loaded, but exist in savegame file only for debugging purposes. */
1804 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1805 }
1806
1807 if (game.control.alt_dir[0] != '\0') {
1808 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1809 }
1810
1812 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1813 }
1814
1815 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1816
1817 /* Save improvement order in savegame, so we are not dependent on ruleset
1818 * order. If the game isn't started improvements aren't loaded so we can
1819 * not save the order. */
1821 "savefile.improvement_size");
1822 if (improvement_count() > 0) {
1823 const char *buf[improvement_count()];
1824
1825 improvement_iterate(pimprove) {
1826 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1828
1830 "savefile.improvement_vector");
1831 }
1832
1833 /* Save technology order in savegame, so we are not dependent on ruleset
1834 * order. If the game isn't started advances aren't loaded so we can not
1835 * save the order. */
1837 "savefile.technology_size");
1838 if (game.control.num_tech_types > 0) {
1839 const char *buf[game.control.num_tech_types];
1840
1841 buf[A_NONE] = "A_NONE";
1842 advance_iterate(a) {
1846 "savefile.technology_vector");
1847 }
1848
1849 /* Save activities order in the savegame. */
1851 "savefile.activities_size");
1852 if (ACTIVITY_LAST > 0) {
1853 const char **modname;
1854 int j;
1855
1856 i = 0;
1857
1859
1860 for (j = 0; j < ACTIVITY_LAST; j++) {
1862 }
1863
1866 "savefile.activities_vector");
1867 free(modname);
1868 }
1869
1870 /* Save specialists order in the savegame. */
1872 "savefile.specialists_size");
1873 {
1874 const char **modname;
1875
1876 i = 0;
1878
1882
1884 "savefile.specialists_vector");
1885
1886 free(modname);
1887 }
1888
1889 /* Save trait order in savegame. */
1891 "savefile.trait_size");
1892 {
1893 const char **modname;
1894 enum trait tr;
1895 int j;
1896
1897 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1898
1899 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1900 modname[j] = trait_name(tr);
1901 }
1902
1904 "savefile.trait_vector");
1905 free(modname);
1906 }
1907
1908 /* Save extras order in the savegame. */
1910 "savefile.extras_size");
1911 if (game.control.num_extra_types > 0) {
1912 const char **modname;
1913
1914 i = 0;
1916
1917 extra_type_iterate(pextra) {
1918 modname[i++] = extra_rule_name(pextra);
1920
1923 "savefile.extras_vector");
1924 free(modname);
1925 }
1926
1927 /* Save multipliers order in the savegame. */
1929 "savefile.multipliers_size");
1930 if (multiplier_count() > 0) {
1931 const char **modname;
1932
1934
1935 multipliers_iterate(pmul) {
1938
1941 "savefile.multipliers_vector");
1942 free(modname);
1943 }
1944
1945 /* Save city_option order in the savegame. */
1947 "savefile.city_options_size");
1948 if (CITYO_LAST > 0) {
1949 const char **modname;
1950 int j;
1951
1952 i = 0;
1953 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1954
1955 for (j = 0; j < CITYO_LAST; j++) {
1956 modname[i++] = city_options_name(j);
1957 }
1958
1960 CITYO_LAST,
1961 "savefile.city_options_vector");
1962 free(modname);
1963 }
1964
1965 /* Save action order in the savegame. */
1967 "savefile.action_size");
1968 if (NUM_ACTIONS > 0) {
1969 const char **modname;
1970 int j;
1971
1972 i = 0;
1973 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1974
1975 for (j = 0; j < NUM_ACTIONS; j++) {
1977 }
1978
1981 "savefile.action_vector");
1982 free(modname);
1983 }
1984
1985 /* Save action decision order in the savegame. */
1987 "savefile.action_decision_size");
1988 if (ACT_DEC_COUNT > 0) {
1989 const char **modname;
1990 int j;
1991
1992 i = 0;
1994
1995 for (j = 0; j < ACT_DEC_COUNT; j++) {
1997 }
1998
2001 "savefile.action_decision_vector");
2002 free(modname);
2003 }
2004
2005 /* Save server side agent order in the savegame. */
2007 "savefile.server_side_agent_size");
2008 if (SSA_COUNT > 0) {
2009 const char **modname;
2010 int j;
2011
2012 i = 0;
2013 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2014
2015 for (j = 0; j < SSA_COUNT; j++) {
2017 }
2018
2020 SSA_COUNT,
2021 "savefile.server_side_agent_list");
2022 free(modname);
2023 }
2024
2025 /* Save terrain character mapping in the savegame. */
2026 i = 0;
2028 char buf[2];
2029
2030 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2032 buf[1] = '\0';
2033 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2035}
2036
2037/************************************************************************/
2041 const char *option)
2042{
2043 /* Check status and return if not OK (sg_success FALSE). */
2044 sg_check_ret();
2045
2046 if (option == NULL) {
2047 /* no additional option */
2048 return;
2049 }
2050
2051 sz_strlcat(saving->secfile_options, option);
2052 secfile_replace_str(saving->file, saving->secfile_options,
2053 "savefile.options");
2054}
2055
2056/* =======================================================================
2057 * Load / save game status.
2058 * ======================================================================= */
2059
2060/************************************************************************/
2064{
2065 int i;
2066 const char *name;
2067
2068 /* Check status and return if not OK (sg_success FALSE). */
2069 sg_check_ret();
2070
2071 for (i = 0;
2073 "ruledata.government%d.name", i));
2074 i++) {
2076
2077 if (gov != NULL) {
2079 "ruledata.government%d.changes", i);
2080 }
2081 }
2082}
2083
2084/************************************************************************/
2087static void sg_load_game(struct loaddata *loading)
2088{
2089 const char *str;
2090 int i;
2091
2092 /* Check status and return if not OK (sg_success FALSE). */
2093 sg_check_ret();
2094
2095 /* Load server state. */
2096 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2097 "game.server_state");
2098 loading->server_state = server_states_by_name(str, strcmp);
2099 if (!server_states_is_valid(loading->server_state)) {
2100 /* Don't take any risk! */
2101 loading->server_state = S_S_INITIAL;
2102 }
2103
2105 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2106
2109 "game.meta_patches");
2111
2113 /* Do not overwrite this if the user requested a specific metaserver
2114 * from the command line (option --Metaserver). */
2118 "game.meta_server"));
2119 }
2120
2121 if ('\0' == srvarg.serverid[0]) {
2122 /* Do not overwrite this if the user requested a specific metaserver
2123 * from the command line (option --serverid). */
2126 "game.serverid"));
2127 }
2128 sz_strlcpy(server.game_identifier,
2129 secfile_lookup_str_default(loading->file, "", "game.id"));
2130 /* We are not checking game_identifier legality just yet.
2131 * That's done when we are sure that rand seed has been initialized,
2132 * so that we can generate new game_identifier, if needed.
2133 * See sq_load_sanitycheck(). */
2134
2136 "game.phase_mode");
2137 if (str != NULL) {
2140 log_error("Illegal phase mode \"%s\"", str);
2142 }
2143 } else {
2144 log_error("Phase mode missing");
2145 }
2146
2148 "game.phase_mode_stored");
2149 if (str != NULL) {
2152 log_error("Illegal stored phase mode \"%s\"", str);
2154 }
2155 } else {
2156 log_error("Stored phase mode missing");
2157 }
2160 "game.phase");
2164 "game.scoreturn");
2165
2168 "game.timeoutint");
2171 "game.timeoutintinc");
2174 "game.timeoutinc");
2177 "game.timeoutincmult");
2180 "game.timeoutcounter");
2181
2182 game.info.turn
2183 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2185 "game.year"), "%s", secfile_error());
2187 "game.world_peace_start"), "%s", secfile_error());
2189 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2190
2192 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2194 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2196 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2197
2199 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2201 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2203 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2204
2205 /* Savegame may have stored random_seed for documentation purposes only,
2206 * but we want to keep it for resaving. */
2207 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2208
2209 /* Global advances. */
2211 "game.global_advances");
2212 if (str != NULL) {
2213 sg_failure_ret(strlen(str) == loading->technology.size,
2214 "Invalid length of 'game.global_advances' ("
2215 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2216 strlen(str), loading->technology.size);
2217 for (i = 0; i < loading->technology.size; i++) {
2218 sg_failure_ret(str[i] == '1' || str[i] == '0',
2219 "Undefined value '%c' within 'game.global_advances'.",
2220 str[i]);
2221 if (str[i] == '1') {
2222 struct advance *padvance
2223 = advance_by_rule_name(loading->technology.order[i]);
2224
2225 if (padvance != NULL) {
2227 }
2228 }
2229 }
2230 }
2231
2233 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2234
2236 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2237}
2238
2239/************************************************************************/
2243{
2244 int set_count = 0;
2245
2247 char path[256];
2248
2249 fc_snprintf(path, sizeof(path),
2250 "ruledata.government%d", set_count++);
2251
2253 "%s.name", path);
2254 secfile_insert_int(saving->file, pgov->changed_to_times,
2255 "%s.changes", path);
2257}
2258
2259/************************************************************************/
2262static void sg_save_game(struct savedata *saving)
2263{
2265 char global_advances[game.control.num_tech_types + 1];
2266 int i;
2267
2268 /* Check status and return if not OK (sg_success FALSE). */
2269 sg_check_ret();
2270
2271 /* Game state: once the game is no longer a new game (ie, has been
2272 * started the first time), it should always be considered a running
2273 * game for savegame purposes. */
2274 if (saving->scenario && !game.scenario.players) {
2276 } else {
2278 }
2280 "game.server_state");
2281
2282 if (game.server.phase_timer != NULL) {
2286 "game.phase_seconds");
2287 }
2288
2290 "game.meta_patches");
2291 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2292
2293 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2294 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2295
2298 "game.phase_mode");
2301 "game.phase_mode_stored");
2303 "game.phase");
2305 "game.scoreturn");
2306
2308 "game.timeoutint");
2310 "game.timeoutintinc");
2312 "game.timeoutinc");
2314 "game.timeoutincmult");
2316 "game.timeoutcounter");
2317
2318 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2319 secfile_insert_int(saving->file, game.info.year, "game.year");
2320 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2322 "game.year_0_hack");
2323
2325 "game.globalwarming");
2327 "game.heating");
2329 "game.warminglevel");
2330
2332 "game.nuclearwinter");
2334 "game.cooling");
2336 "game.coolinglevel");
2337 /* For debugging purposes only.
2338 * Do not save it if it's 0 (not known);
2339 * this confuses people reading this 'document' less than
2340 * saving 0. */
2341 if (game.server.seed != 0) {
2343 "game.random_seed");
2344 }
2345
2346 /* Global advances. */
2347 for (i = 0; i < game.control.num_tech_types; i++) {
2348 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2349 }
2350 global_advances[i] = '\0';
2351 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2352
2353 if (!game_was_started()) {
2354 saving->save_players = FALSE;
2355 } else {
2356 if (saving->scenario) {
2357 saving->save_players = game.scenario.players;
2358 } else {
2359 saving->save_players = TRUE;
2360 }
2361#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2363 "game.last_turn_change_time");
2364#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2366 "game.last_turn_change_time");
2367#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2368 }
2369 secfile_insert_bool(saving->file, saving->save_players,
2370 "game.save_players");
2371
2372 if (srv_state != S_S_INITIAL) {
2373 const char *ainames[ai_type_get_count()];
2374
2375 i = 0;
2376 ai_type_iterate(ait) {
2377 ainames[i] = ait->name;
2378 i++;
2380
2382 "game.ai_types");
2383 }
2384}
2385
2386/* =======================================================================
2387 * Load / save random status.
2388 * ======================================================================= */
2389
2390/************************************************************************/
2393static void sg_load_random(struct loaddata *loading)
2394{
2395 /* Check status and return if not OK (sg_success FALSE). */
2396 sg_check_ret();
2397
2398 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2399 const char *str;
2400 int i;
2401
2403 "random.index_J"), "%s", secfile_error());
2405 "random.index_K"), "%s", secfile_error());
2407 "random.index_X"), "%s", secfile_error());
2408
2409 for (i = 0; i < 8; i++) {
2410 str = secfile_lookup_str(loading->file, "random.table%d",i);
2411 sg_failure_ret(NULL != str, "%s", secfile_error());
2412 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2413 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2414 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2415 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2416 }
2417 loading->rstate.is_init = TRUE;
2418 fc_rand_set_state(loading->rstate);
2419 } else {
2420 /* No random values - mark the setting. */
2421 (void) secfile_entry_by_path(loading->file, "random.saved");
2422
2423 /* We're loading a game without a seed (which is okay, if it's a scenario).
2424 * We need to generate the game seed now because it will be needed later
2425 * during the load. */
2427 loading->rstate = fc_rand_state();
2428 }
2429}
2430
2431/************************************************************************/
2434static void sg_save_random(struct savedata *saving)
2435{
2436 /* Check status and return if not OK (sg_success FALSE). */
2437 sg_check_ret();
2438
2439 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2440 int i;
2441 RANDOM_STATE rstate = fc_rand_state();
2442
2443 secfile_insert_bool(saving->file, TRUE, "random.saved");
2444 fc_assert(rstate.is_init);
2445
2446 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2447 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2448 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2449
2450 for (i = 0; i < 8; i++) {
2451 char vec[100];
2452
2453 fc_snprintf(vec, sizeof(vec),
2454 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2455 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2456 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2457 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2458 secfile_insert_str(saving->file, vec, "random.table%d", i);
2459 }
2460 } else {
2461 secfile_insert_bool(saving->file, FALSE, "random.saved");
2462 }
2463}
2464
2465/* =======================================================================
2466 * Load / save lua script data.
2467 * ======================================================================= */
2468
2469/************************************************************************/
2472static void sg_load_script(struct loaddata *loading)
2473{
2474 /* Check status and return if not OK (sg_success FALSE). */
2475 sg_check_ret();
2476
2478}
2479
2480/************************************************************************/
2483static void sg_save_script(struct savedata *saving)
2484{
2485 /* Check status and return if not OK (sg_success FALSE). */
2486 sg_check_ret();
2487
2489}
2490
2491/* =======================================================================
2492 * Load / save scenario data.
2493 * ======================================================================= */
2494
2495/************************************************************************/
2499{
2500 const char *buf;
2501 int game_version;
2502
2503 /* Check status and return if not OK (sg_success FALSE). */
2504 sg_check_ret();
2505
2506 /* Load version. */
2508 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2509 /* We require at least version 2.90.99 - and at that time we saved version
2510 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2511 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2512 "version 2.90.99 required.");
2513
2514 loading->full_version = game_version;
2515
2516 game.scenario.datafile[0] = '\0';
2517
2519 "scenario.is_scenario"), "%s", secfile_error());
2520 if (!game.scenario.is_scenario) {
2521 return;
2522 }
2523
2524 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2525 if (buf[0] != '\0') {
2527 }
2528
2530 "scenario.authors");
2531 if (buf[0] != '\0') {
2533 } else {
2534 game.scenario.authors[0] = '\0';
2535 }
2536
2538 "scenario.description");
2539 if (buf[0] != '\0') {
2541 } else {
2542 game.scenario_desc.description[0] = '\0';
2543 }
2545 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2547 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2550 "scenario.startpos_nations");
2553 "scenario.prevent_new_cities");
2556 "scenario.lake_flooding");
2559 "scenario.handmade");
2562 "scenario.allow_ai_type_fallback");
2563
2566 "scenario.ruleset_locked");
2567
2569 "scenario.datafile");
2570 if (buf[0] != '\0') {
2572 }
2573
2574 sg_failure_ret(loading->server_state == S_S_INITIAL
2575 || (loading->server_state == S_S_RUNNING
2576 && game.scenario.players),
2577 "Invalid scenario definition (server state '%s' and "
2578 "players are %s).",
2579 server_states_name(loading->server_state),
2580 game.scenario.players ? "saved" : "not saved");
2581}
2582
2583/************************************************************************/
2587{
2588 struct entry *mod_entry;
2589 int game_version;
2590
2591 /* Check status and return if not OK (sg_success FALSE). */
2592 sg_check_ret();
2593
2594 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2595#ifdef EMERGENCY_VERSION
2597#endif /* EMERGENCY_VERSION */
2598 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2599
2600 if (!saving->scenario || !game.scenario.is_scenario) {
2601 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2602 return;
2603 }
2604
2605 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2606
2607 /* Name is mandatory to the level that is saved even if empty. */
2608 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2610
2611 /* Authors list is saved only if it exist */
2612 if (game.scenario.authors[0] != '\0') {
2614 "scenario.authors");
2616 }
2617
2618 /* Description is saved only if it exist */
2619 if (game.scenario_desc.description[0] != '\0') {
2621 "scenario.description");
2623 }
2624
2625 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2626 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2628 "scenario.startpos_nations");
2631 "scenario.prevent_new_cities");
2632 }
2634 "scenario.lake_flooding");
2635 if (game.scenario.handmade) {
2637 "scenario.handmade");
2638 }
2641 "scenario.allow_ai_type_fallback");
2642 }
2643
2644 if (game.scenario.datafile[0] != '\0') {
2646 "scenario.datafile");
2647 }
2649 "scenario.ruleset_locked");
2650 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2652 "scenario.ruleset_caps");
2653 }
2654}
2655
2656/* =======================================================================
2657 * Load / save game settings.
2658 * ======================================================================= */
2659
2660/************************************************************************/
2664{
2665 /* Check status and return if not OK (sg_success FALSE). */
2666 sg_check_ret();
2667
2668 settings_game_load(loading->file, "settings");
2669
2670 /* Save current status of fogofwar. */
2672
2673 /* Add all compatibility settings here. */
2674}
2675
2676/************************************************************************/
2680{
2682
2683 /* Check status and return if not OK (sg_success FALSE). */
2684 sg_check_ret();
2685
2686 if (saving->scenario) {
2687 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2688 }
2689
2690 settings_game_save(saving->file, "settings");
2691 /* Restore real map generator. */
2693
2694 /* Add all compatibility settings here. */
2695}
2696
2697
2698/************************************************************************/
2702{
2703 struct city *pcity;
2704 int i, j;
2705 size_t length, length2;
2706 int *city_count;
2708 "savefile.city_counters_order_size");
2709
2710 if (0==length) {
2711
2712 return;
2713 }
2714
2715 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2716
2717 sg_failure_ret(loading->counter.order != 0,
2718 "Failed to load counter's ruleset order: %s",
2719 secfile_error());
2720 sg_failure_ret(loading->counter.size = length,
2721 "Counter vector in savegame have bad size: %s",
2722 secfile_error());
2723
2724 int corder[length];
2725
2726 for (i = 0; i < length; i++) {
2727
2728 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2730 }
2731
2732 i = 0;
2733 while (NULL != (city_count =
2735 "counters.c%d", i))) {
2736
2737 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);
2738
2740
2741 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2742
2743 for (j = 0; j < length; j++) {
2744
2745 pcity->counter_values[corder[j]] = city_count[j+1];
2746 }
2747 i++;
2748 }
2749}
2750
2751/************************************************************************/
2755{
2756 /* Check status and return if not OK (sg_success FALSE). */
2757 sg_check_ret();
2758
2759 const char **countnames;
2760 int *countvalues;
2761 int i, j, count;
2762
2764
2765 secfile_insert_int(saving->file, count,
2766 "savefile.city_counters_order_size");
2767
2768 if (0 == count) {
2769
2770 return;
2771 }
2772
2773 countnames = fc_calloc(count, sizeof(*countnames));
2774 for (j = 0; j < count; j++) {
2776 }
2777
2779 "savefile.city_counters_order_vector");
2780
2782
2783 // Saving city's counters
2784
2785 j = 0;
2786 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2787
2789
2790 city_list_iterate(_pplayer->cities, pcity) {
2791
2792 countvalues[0] = pcity->id;
2793 for (i = 0; i < count; ++i) {
2794
2795 countvalues[i+1] = pcity->counter_values[i];
2796 }
2797
2798 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2799 ++j;
2802
2804}
2805
2806/* =======================================================================
2807 * Load / save the main map.
2808 * ======================================================================= */
2809
2810/************************************************************************/
2813static void sg_load_map(struct loaddata *loading)
2814{
2815 /* Check status and return if not OK (sg_success FALSE). */
2816 sg_check_ret();
2817
2818 /* This defaults to TRUE even if map has not been generated.
2819 * We rely on that
2820 * 1) scenario maps have it explicitly right.
2821 * 2) when map is actually generated, it re-initialize this to FALSE. */
2823 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2824
2826 "map.altitude"),
2827 "%s", secfile_error());
2828
2830 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2831
2833
2834 /* Savegame may have stored random_seed for documentation purposes only,
2835 * but we want to keep it for resaving. */
2837 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2838
2839 if (S_S_INITIAL == loading->server_state
2841 /* Generator MAPGEN_SCENARIO is used;
2842 * this map was done with the map editor. */
2843
2844 /* Load tiles. */
2848
2849 /* Nothing more needed for a scenario. */
2850 secfile_entry_ignore(loading->file, "game.save_known");
2851
2852 return;
2853 }
2854
2855 if (S_S_INITIAL == loading->server_state) {
2856 /* Nothing more to do if it is not a scenario but in initial state. */
2857 return;
2858 }
2859
2861 if (wld.map.altitude_info) {
2863 }
2869}
2870
2871/************************************************************************/
2874static void sg_save_map(struct savedata *saving)
2875{
2876 /* Check status and return if not OK (sg_success FALSE). */
2877 sg_check_ret();
2878
2879 if (map_is_empty()) {
2880 /* No map. */
2881 return;
2882 }
2883
2884 if (saving->scenario) {
2886 "map.have_huts");
2888 "map.have_resources");
2889 } else {
2890 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2891 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2892 }
2893
2894 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2895
2896 /* For debugging purposes only.
2897 * Do not save it if it's 0 (not known);
2898 * this confuses people reading this 'document' less than
2899 * saving 0. */
2900 if (wld.map.server.seed != 0) {
2902 "map.random_seed");
2903 }
2904
2906 if (wld.map.altitude_info) {
2908 }
2914}
2915
2916/************************************************************************/
2920{
2921 /* Check status and return if not OK (sg_success FALSE). */
2922 sg_check_ret();
2923
2924 /* Initialize the map for the current topology. 'map.xsize' and
2925 * 'map.ysize' must be set. */
2927
2928 /* Allocate map. */
2930
2931 /* get the terrain type */
2932 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2933 "map.t%04d");
2935
2936 /* Check for special tile sprites. */
2937 whole_map_iterate(&(wld.map), ptile) {
2938 const char *spec_sprite;
2939 const char *label;
2940 int nat_x, nat_y;
2941
2943 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2944 nat_x, nat_y);
2945 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2946 nat_x, nat_y);
2947 if (NULL != ptile->spec_sprite) {
2948 ptile->spec_sprite = fc_strdup(spec_sprite);
2949 }
2950 if (label != NULL) {
2951 tile_set_label(ptile, label);
2952 }
2954}
2955
2956/************************************************************************/
2960{
2961 /* Check status and return if not OK (sg_success FALSE). */
2962 sg_check_ret();
2963
2964 /* Save the terrain type. */
2965 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2966 "map.t%04d");
2967
2968 /* Save special tile sprites. */
2969 whole_map_iterate(&(wld.map), ptile) {
2970 int nat_x, nat_y;
2971
2973 if (ptile->spec_sprite) {
2974 secfile_insert_str(saving->file, ptile->spec_sprite,
2975 "map.spec_sprite_%d_%d", nat_x, nat_y);
2976 }
2977 if (ptile->label != NULL) {
2978 secfile_insert_str(saving->file, ptile->label,
2979 "map.label_%d_%d", nat_x, nat_y);
2980 }
2982}
2983
2984/************************************************************************/
2988{
2989 int y;
2990
2991 /* Check status and return if not OK (sg_success FALSE). */
2992 sg_check_ret();
2993
2994 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
2995 const char *buffer = secfile_lookup_str(loading->file,
2996 "map.alt%04d", y);
2997 const char *ptr = buffer;
2998 int x;
2999
3000 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3001
3002 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3003 char token[TOKEN_SIZE];
3004 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3005 int number;
3006
3007 scanin(&ptr, ",", token, sizeof(token));
3008 sg_failure_ret(token[0] != '\0',
3009 "Map size not correct (map.alt%d).", y);
3010 sg_failure_ret(str_to_int(token, &number),
3011 "Got map alt %s in (%d, %d).", token, x, y);
3012 ptile->altitude = number;
3013 }
3014 }
3015}
3016
3017/************************************************************************/
3021{
3022 int y;
3023
3024 /* Check status and return if not OK (sg_success FALSE). */
3025 sg_check_ret();
3026
3027 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3029 int x;
3030
3031 line[0] = '\0';
3032 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3033 char token[TOKEN_SIZE];
3034 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3035
3036 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3037
3038 strcat(line, token);
3039 if (x + 1 < MAP_NATIVE_WIDTH) {
3040 strcat(line, ",");
3041 }
3042 }
3043
3044 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3045 }
3046}
3047
3048/************************************************************************/
3052{
3053 /* Check status and return if not OK (sg_success FALSE). */
3054 sg_check_ret();
3055
3056 /* Load extras. */
3057 halfbyte_iterate_extras(j, loading->extra.size) {
3058 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3059 loading->extra.order + 4 * j),
3060 loading->file, "map.e%02d_%04d", j);
3062
3063 if (S_S_INITIAL != loading->server_state
3066 whole_map_iterate(&(wld.map), ptile) {
3068 if (tile_has_extra(ptile, pres)) {
3069 tile_set_resource(ptile, pres);
3070
3071 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3072 BV_CLR(ptile->extras, extra_index(pres));
3073 }
3074 }
3077 }
3078}
3079
3080/************************************************************************/
3084{
3085 /* Check status and return if not OK (sg_success FALSE). */
3086 sg_check_ret();
3087
3088 /* Save extras. */
3090 int mod[4];
3091 int l;
3092
3093 for (l = 0; l < 4; l++) {
3094 if (4 * j + 1 > game.control.num_extra_types) {
3095 mod[l] = -1;
3096 } else {
3097 mod[l] = 4 * j + l;
3098 }
3099 }
3100 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3101 saving->file, "map.e%02d_%04d", j);
3103}
3104
3105/************************************************************************/
3110{
3111 struct nation_type *pnation;
3112 struct startpos *psp;
3113 struct tile *ptile;
3114 const char SEPARATOR = '#';
3115 const char *nation_names;
3116 int nat_x, nat_y;
3117 bool exclude;
3118 int i, startpos_count;
3119
3120 /* Check status and return if not OK (sg_success FALSE). */
3121 sg_check_ret();
3122
3124 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3125
3126 if (0 == startpos_count) {
3127 /* Nothing to do. */
3128 return;
3129 }
3130
3131 for (i = 0; i < startpos_count; i++) {
3132 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3133 || !secfile_lookup_int(loading->file, &nat_y,
3134 "map.startpos%d.y", i)) {
3135 log_sg("Warning: Undefined coordinates for startpos %d", i);
3136 continue;
3137 }
3138
3139 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3140 if (NULL == ptile) {
3141 log_error("Start position native coordinates (%d, %d) do not exist "
3142 "in this map. Skipping...", nat_x, nat_y);
3143 continue;
3144 }
3145
3146 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3147 "map.startpos%d.exclude", i);
3148
3149 psp = map_startpos_new(ptile);
3150
3152 "map.startpos%d.nations", i);
3153 if (NULL != nation_names && '\0' != nation_names[0]) {
3154 const size_t size = strlen(nation_names) + 1;
3155 char buf[size], *start, *end;
3156
3158 for (start = buf - 1; NULL != start; start = end) {
3159 start++;
3160 if ((end = strchr(start, SEPARATOR))) {
3161 *end = '\0';
3162 }
3163
3164 pnation = nation_by_rule_name(start);
3165 if (NO_NATION_SELECTED != pnation) {
3166 if (exclude) {
3167 startpos_disallow(psp, pnation);
3168 } else {
3169 startpos_allow(psp, pnation);
3170 }
3171 } else {
3172 log_verbose("Missing nation \"%s\".", start);
3173 }
3174 }
3175 }
3176 }
3177
3178 if (0 < map_startpos_count()
3179 && loading->server_state == S_S_INITIAL
3181 log_verbose("Number of starts (%d) are lower than rules.max_players "
3182 "(%d), lowering rules.max_players.",
3185 }
3186
3187 /* Re-initialize nation availability in light of start positions.
3188 * This has to be after loading [scenario] and [map].startpos and
3189 * before we seek nations for players. */
3191}
3192
3193/************************************************************************/
3197{
3198 struct tile *ptile;
3199 const char SEPARATOR = '#';
3200 int i = 0;
3201
3202 /* Check status and return if not OK (sg_success FALSE). */
3203 sg_check_ret();
3204
3206 return;
3207 }
3208
3210 "map.startpos_count");
3211
3213 int nat_x, nat_y;
3214
3215 ptile = startpos_tile(psp);
3216
3218 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3219 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3220
3222 "map.startpos%d.exclude", i);
3223 if (startpos_allows_all(psp)) {
3224 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3225 } else {
3226 const struct nation_hash *nations = startpos_raw_nations(psp);
3228
3229 nation_names[0] = '\0';
3230 nation_hash_iterate(nations, pnation) {
3231 if ('\0' == nation_names[0]) {
3233 sizeof(nation_names));
3234 } else {
3236 "%c%s", SEPARATOR, nation_rule_name(pnation));
3237 }
3240 "map.startpos%d.nations", i);
3241 }
3242 i++;
3244
3246}
3247
3248/************************************************************************/
3252{
3253 int y;
3254 struct tile *claimer = NULL;
3255 struct extra_type *placing = NULL;
3256
3257 /* Check status and return if not OK (sg_success FALSE). */
3258 sg_check_ret();
3259
3260 if (game.info.is_new_game) {
3261 /* No owner/source information for a new game / scenario. */
3262 return;
3263 }
3264
3265 /* Owner, ownership source, and infra turns are stored as plain numbers */
3266 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3267 const char *buffer1 = secfile_lookup_str(loading->file,
3268 "map.owner%04d", y);
3269 const char *buffer2 = secfile_lookup_str(loading->file,
3270 "map.source%04d", y);
3271 const char *buffer3 = secfile_lookup_str(loading->file,
3272 "map.eowner%04d", y);
3274 NULL,
3275 "map.placing%04d", y);
3277 NULL,
3278 "map.infra_turns%04d", y);
3279 const char *ptr1 = buffer1;
3280 const char *ptr2 = buffer2;
3281 const char *ptr3 = buffer3;
3282 const char *ptr_placing = buffer_placing;
3283 const char *ptr_turns = buffer_turns;
3284 int x;
3285
3289
3290 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3291 char token1[TOKEN_SIZE];
3292 char token2[TOKEN_SIZE];
3293 char token3[TOKEN_SIZE];
3295 char token_turns[TOKEN_SIZE];
3296 struct player *owner = NULL;
3297 struct player *eowner = NULL;
3298 int turns;
3299 int number;
3300 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3301
3302 scanin(&ptr1, ",", token1, sizeof(token1));
3303 sg_failure_ret(token1[0] != '\0',
3304 "Map size not correct (map.owner%d).", y);
3305 if (strcmp(token1, "-") == 0) {
3306 owner = NULL;
3307 } else {
3309 "Got map owner %s in (%d, %d).", token1, x, y);
3310 owner = player_by_number(number);
3311 }
3312
3313 scanin(&ptr2, ",", token2, sizeof(token2));
3314 sg_failure_ret(token2[0] != '\0',
3315 "Map size not correct (map.source%d).", y);
3316 if (strcmp(token2, "-") == 0) {
3317 claimer = NULL;
3318 } else {
3320 "Got map source %s in (%d, %d).", token2, x, y);
3321 claimer = index_to_tile(&(wld.map), number);
3322 }
3323
3324 scanin(&ptr3, ",", token3, sizeof(token3));
3325 sg_failure_ret(token3[0] != '\0',
3326 "Map size not correct (map.eowner%d).", y);
3327 if (strcmp(token3, "-") == 0) {
3328 eowner = NULL;
3329 } else {
3331 "Got base owner %s in (%d, %d).", token3, x, y);
3332 eowner = player_by_number(number);
3333 }
3334
3335 if (ptr_placing != NULL) {
3337 sg_failure_ret(token_placing[0] != '\0',
3338 "Map size not correct (map.placing%d).", y);
3339 if (strcmp(token_placing, "-") == 0) {
3340 placing = NULL;
3341 } else {
3343 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3344 placing = extra_by_number(number);
3345 }
3346 } else {
3347 placing = NULL;
3348 }
3349
3350 if (ptr_turns != NULL) {
3351 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3352 sg_failure_ret(token_turns[0] != '\0',
3353 "Map size not correct (map.infra_turns%d).", y);
3355 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3356 turns = number;
3357 } else {
3358 turns = 1;
3359 }
3360
3362 tile_claim_bases(ptile, eowner);
3363 ptile->placing = placing;
3364 ptile->infra_turns = turns;
3365 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3366 }
3367 }
3368}
3369
3370/************************************************************************/
3374{
3375 int y;
3376
3377 /* Check status and return if not OK (sg_success FALSE). */
3378 sg_check_ret();
3379
3380 if (saving->scenario && !saving->save_players) {
3381 /* Nothing to do for a scenario without saved players. */
3382 return;
3383 }
3384
3385 /* Store owner and ownership source as plain numbers. */
3386 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3388 int x;
3389
3390 line[0] = '\0';
3391 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3392 char token[TOKEN_SIZE];
3393 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3394
3395 if (!saving->save_players || tile_owner(ptile) == NULL) {
3396 strcpy(token, "-");
3397 } else {
3398 fc_snprintf(token, sizeof(token), "%d",
3399 player_number(tile_owner(ptile)));
3400 }
3401 strcat(line, token);
3402 if (x + 1 < MAP_NATIVE_WIDTH) {
3403 strcat(line, ",");
3404 }
3405 }
3406
3407 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3408 }
3409
3410 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3412 int x;
3413
3414 line[0] = '\0';
3415 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3416 char token[TOKEN_SIZE];
3417 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3418
3419 if (ptile->claimer == NULL) {
3420 strcpy(token, "-");
3421 } else {
3422 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3423 }
3424 strcat(line, token);
3425 if (x + 1 < MAP_NATIVE_WIDTH) {
3426 strcat(line, ",");
3427 }
3428 }
3429
3430 secfile_insert_str(saving->file, line, "map.source%04d", y);
3431 }
3432
3433 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3435 int x;
3436
3437 line[0] = '\0';
3438 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3439 char token[TOKEN_SIZE];
3440 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3441
3442 if (!saving->save_players || extra_owner(ptile) == NULL) {
3443 strcpy(token, "-");
3444 } else {
3445 fc_snprintf(token, sizeof(token), "%d",
3446 player_number(extra_owner(ptile)));
3447 }
3448 strcat(line, token);
3449 if (x + 1 < MAP_NATIVE_WIDTH) {
3450 strcat(line, ",");
3451 }
3452 }
3453
3454 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3455 }
3456
3457 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3459 int x;
3460
3461 line[0] = '\0';
3462 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3463 char token[TOKEN_SIZE];
3464 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3465
3466 if (ptile->placing == NULL) {
3467 strcpy(token, "-");
3468 } else {
3469 fc_snprintf(token, sizeof(token), "%d",
3470 extra_number(ptile->placing));
3471 }
3472 strcat(line, token);
3473 if (x + 1 < MAP_NATIVE_WIDTH) {
3474 strcat(line, ",");
3475 }
3476 }
3477
3478 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3479 }
3480
3481 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3483 int x;
3484
3485 line[0] = '\0';
3486 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3487 char token[TOKEN_SIZE];
3488 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3489
3490 if (ptile->placing != NULL) {
3491 fc_snprintf(token, sizeof(token), "%d",
3492 ptile->infra_turns);
3493 } else {
3494 fc_snprintf(token, sizeof(token), "0");
3495 }
3496 strcat(line, token);
3497 if (x + 1 < MAP_NATIVE_WIDTH) {
3498 strcat(line, ",");
3499 }
3500 }
3501
3502 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3503 }
3504}
3505
3506/************************************************************************/
3510{
3511 int x, y;
3512
3513 /* Check status and return if not OK (sg_success FALSE). */
3514 sg_check_ret();
3515
3516 sg_failure_ret(loading->worked_tiles == NULL,
3517 "City worked map not loaded!");
3518
3519 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3520 sizeof(*loading->worked_tiles));
3521
3522 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3523 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3524 y);
3525 const char *ptr = buffer;
3526
3527 sg_failure_ret(NULL != buffer,
3528 "Savegame corrupt - map line %d not found.", y);
3529 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3530 char token[TOKEN_SIZE];
3531 int number;
3532 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3533
3534 scanin(&ptr, ",", token, sizeof(token));
3535 sg_failure_ret('\0' != token[0],
3536 "Savegame corrupt - map size not correct.");
3537 if (strcmp(token, "-") == 0) {
3538 number = -1;
3539 } else {
3540 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3541 "Savegame corrupt - got tile worked by city "
3542 "id=%s in (%d, %d).", token, x, y);
3543 }
3544
3545 loading->worked_tiles[ptile->index] = number;
3546 }
3547 }
3548}
3549
3550/************************************************************************/
3554{
3555 int x, y;
3556
3557 /* Check status and return if not OK (sg_success FALSE). */
3558 sg_check_ret();
3559
3560 if (saving->scenario && !saving->save_players) {
3561 /* Nothing to do for a scenario without saved players. */
3562 return;
3563 }
3564
3565 /* Additionally save the tiles worked by the cities */
3566 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3568
3569 line[0] = '\0';
3570 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3571 char token[TOKEN_SIZE];
3572 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3573 struct city *pcity = tile_worked(ptile);
3574
3575 if (pcity == NULL) {
3576 strcpy(token, "-");
3577 } else {
3578 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3579 }
3580 strcat(line, token);
3581 if (x < MAP_NATIVE_WIDTH) {
3582 strcat(line, ",");
3583 }
3584 }
3585 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3586 }
3587}
3588
3589/************************************************************************/
3593{
3594 /* Check status and return if not OK (sg_success FALSE). */
3595 sg_check_ret();
3596
3597 players_iterate(pplayer) {
3598 /* Allocate player private map here; it is needed in different modules
3599 * besides this one ((i.e. sg_load_player_*()). */
3600 player_map_init(pplayer);
3602
3604 "game.save_known")) {
3605 int lines = player_slot_max_used_number() / 32 + 1;
3606 int j, p, l, i;
3607 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3608
3609 for (l = 0; l < lines; l++) {
3610 for (j = 0; j < 8; j++) {
3611 for (i = 0; i < 4; i++) {
3612 /* Only bother trying to load the map for this halfbyte if at least
3613 * one of the corresponding player slots is in use. */
3614 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3615 LOAD_MAP_CHAR(ch, ptile,
3616 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3617 |= ascii_hex2bin(ch, j),
3618 loading->file, "map.k%02d_%04d", l * 8 + j);
3619 break;
3620 }
3621 }
3622 }
3623 }
3624
3625 players_iterate(pplayer) {
3626 dbv_clr_all(&pplayer->tile_known);
3628
3629 /* HACK: we read the known data from hex into 32-bit integers, and
3630 * now we convert it to the known tile data of each player. */
3631 whole_map_iterate(&(wld.map), ptile) {
3632 players_iterate(pplayer) {
3633 p = player_index(pplayer);
3634 l = player_index(pplayer) / 32;
3635
3636 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3637 map_set_known(ptile, pplayer);
3638 }
3641
3642 FC_FREE(known);
3643 }
3644}
3645
3646/************************************************************************/
3650{
3651 /* Check status and return if not OK (sg_success FALSE). */
3652 sg_check_ret();
3653
3654 if (!saving->save_players) {
3655 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3656 return;
3657 } else {
3658 int lines = player_slot_max_used_number() / 32 + 1;
3659
3661 "game.save_known");
3663 int j, p, l, i;
3664 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3665
3666 /* HACK: we convert the data into a 32-bit integer, and then save it as
3667 * hex. */
3668
3669 whole_map_iterate(&(wld.map), ptile) {
3670 players_iterate(pplayer) {
3671 if (map_is_known(ptile, pplayer)) {
3672 p = player_index(pplayer);
3673 l = p / 32;
3674 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3675 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3676 }
3679
3680 for (l = 0; l < lines; l++) {
3681 for (j = 0; j < 8; j++) {
3682 for (i = 0; i < 4; i++) {
3683 /* Only bother saving the map for this halfbyte if at least one
3684 * of the corresponding player slots is in use */
3685 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3686 /* put 4-bit segments of the 32-bit "known" field */
3688 + tile_index(ptile)], j),
3689 saving->file, "map.k%02d_%04d", l * 8 + j);
3690 break;
3691 }
3692 }
3693 }
3694 }
3695
3696 FC_FREE(known);
3697 }
3698 }
3699}
3700
3701/* =======================================================================
3702 * Load / save player data.
3703 *
3704 * This is split into two parts as some data can only be loaded if the
3705 * number of players is known and the corresponding player slots are
3706 * defined.
3707 * ======================================================================= */
3708
3709/************************************************************************/
3713{
3714 int i, k, nplayers;
3715 const char *str;
3716 bool shuffle_loaded = TRUE;
3717
3718 /* Check status and return if not OK (sg_success FALSE). */
3719 sg_check_ret();
3720
3721 if (S_S_INITIAL == loading->server_state
3722 || game.info.is_new_game) {
3723 /* Nothing more to do. */
3724 return;
3725 }
3726
3727 /* Load destroyed wonders: */
3729 "players.destroyed_wonders");
3730 sg_failure_ret(str != NULL, "%s", secfile_error());
3731 sg_failure_ret(strlen(str) == loading->improvement.size,
3732 "Invalid length for 'players.destroyed_wonders' ("
3733 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3734 strlen(str), loading->improvement.size);
3735 for (k = 0; k < loading->improvement.size; k++) {
3736 sg_failure_ret(str[k] == '1' || str[k] == '0',
3737 "Undefined value '%c' within "
3738 "'players.destroyed_wonders'.", str[k]);
3739
3740 if (str[k] == '1') {
3741 struct impr_type *pimprove
3742 = improvement_by_rule_name(loading->improvement.order[k]);
3743
3744 if (pimprove != NULL) {
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 enum capital_type cap;
5179
5181 FALSE, "%s", secfile_error());
5183 FALSE, "%s", secfile_error());
5186 "%s has invalid center tile (%d, %d)",
5187 citystr, nat_x, nat_y);
5189 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5190
5191 /* Instead of dying, use 'citystr' string for damaged name. */
5193 "%s.name", citystr));
5194
5196 citystr), FALSE, "%s", secfile_error());
5197
5199 "%s.original", citystr);
5200 past = player_by_number(id);
5201 if (NULL != past) {
5202 pcity->original = past;
5203 }
5204
5205 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5206 citystr), FALSE, "%s", secfile_error());
5207 size = (citizens)value; /* Set the correct type */
5208 sg_warn_ret_val(value == (int)size, FALSE,
5209 "Invalid city size: %d, set to %d", value, size);
5211
5213 "%s.capital", citystr),
5215
5217 pcity->capital = cap;
5218 if (cap == CAPITAL_PRIMARY) {
5219 plr->primary_capital_id = pcity->id;
5220 }
5221 } else {
5222 pcity->capital = CAPITAL_NOT;
5223 }
5224
5225 for (i = 0; i < loading->specialist.size; i++) {
5226 Specialist_type_id si = specialist_index(loading->specialist.order[i]);
5227
5228 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5229 citystr, i),
5230 FALSE, "%s", secfile_error());
5231 pcity->specialists[si] = (citizens)value;
5233 sp_count += value;
5234 }
5235 }
5236
5237 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5238 for (i = 0; partner != 0; i++) {
5239 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5240 const char *dir;
5241 const char *good_str;
5242
5243 /* Append to routes list immediately, so the pointer can be found for freeing
5244 * even if we abort */
5246
5247 proute->partner = partner;
5248 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5250 "No traderoute direction found for %s", citystr);
5253 "Illegal route direction %s", dir);
5254 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5256 "No good found for %s", citystr);
5258 sg_warn_ret_val(proute->goods != NULL, FALSE,
5259 "Illegal good %s", good_str);
5260
5261 /* Next one */
5263 "%s.traderoute%d", citystr, i + 1);
5264 }
5265
5266 for (; i < routes_max; i++) {
5267 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5268 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5269 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5270 }
5271
5272 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5273 "%s.food_stock", citystr),
5274 FALSE, "%s", secfile_error());
5275 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5276 "%s.shield_stock", citystr),
5277 FALSE, "%s", secfile_error());
5278 pcity->history =
5279 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5280
5281 pcity->airlift =
5282 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5283 pcity->was_happy =
5284 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5285 citystr);
5286 pcity->had_famine =
5287 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5288 citystr);
5289
5290 pcity->turn_plague =
5291 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5292
5294 "%s.anarchy", citystr),
5295 FALSE, "%s", secfile_error());
5296 pcity->rapture =
5297 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5298 pcity->steal =
5299 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5300
5301 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5302 "%s.turn_founded", citystr),
5303 FALSE, "%s", secfile_error());
5305 "%s.acquire_t", citystr),
5306 FALSE, "%s", secfile_error());
5307 pcity->acquire_t = tmp_int;
5308 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5309 citystr), FALSE, "%s", secfile_error());
5310 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5311 citystr), FALSE, "%s", secfile_error());
5312
5313 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5314 "%s.turn_last_built", citystr),
5315 FALSE, "%s", secfile_error());
5316
5317 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5318 citystr);
5319 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5320 citystr);
5321 pcity->production = universal_by_rule_name(kind, name);
5322 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5323 "%s.currently_building: unknown \"%s\" \"%s\".",
5324 citystr, kind, name);
5325
5326 want = secfile_lookup_int_default(loading->file, 0,
5327 "%s.current_want", citystr);
5328 if (pcity->production.kind == VUT_IMPROVEMENT) {
5329 pcity->server.adv->
5330 building_want[improvement_index(pcity->production.value.building)]
5331 = want;
5332 }
5333
5334 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5335 citystr);
5336 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5337 citystr);
5340 "%s.changed_from: unknown \"%s\" \"%s\".",
5341 citystr, kind, name);
5342
5343 pcity->before_change_shields =
5344 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5345 "%s.before_change_shields", citystr);
5346 pcity->caravan_shields =
5348 "%s.caravan_shields", citystr);
5349 pcity->disbanded_shields =
5351 "%s.disbanded_shields", citystr);
5352 pcity->last_turns_shield_surplus =
5354 "%s.last_turns_shield_surplus",
5355 citystr);
5356
5358 "%s.style", citystr);
5359 if (stylename != NULL) {
5361 } else {
5362 pcity->style = 0;
5363 }
5364 if (pcity->style < 0) {
5365 pcity->style = city_style(pcity);
5366 }
5367
5368 pcity->server.synced = FALSE; /* Must re-sync with clients */
5369
5370 /* Initialise list of city improvements. */
5371 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5372 pcity->built[i].turn = I_NEVER;
5373 }
5374
5375 /* Load city improvements. */
5376 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5378 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5379 "Invalid length of '%s.improvements' ("
5380 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5381 citystr, strlen(str), loading->improvement.size);
5382 for (i = 0; i < loading->improvement.size; i++) {
5383 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5384 "Undefined value '%c' within '%s.improvements'.",
5385 str[i], citystr)
5386
5387 if (str[i] == '1') {
5388 struct impr_type *pimprove
5389 = improvement_by_rule_name(loading->improvement.order[i]);
5390
5391 if (pimprove) {
5392 city_add_improvement(pcity, pimprove);
5393 }
5394 }
5395 }
5396
5397 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5398 "No worked tiles map defined.");
5399
5401
5402 /* Load new savegame with variable (squared) city radius and worked
5403 * tiles map */
5404
5405 int radius_sq
5406 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5407 citystr);
5408 city_map_radius_sq_set(pcity, radius_sq);
5409
5411 if (loading->worked_tiles[ptile->index] == pcity->id) {
5412 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5413 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5414 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5415 TILE_XY(pcity->tile), TILE_XY(ptile));
5416 pcity->specialists[DEFAULT_SPECIALIST]++;
5417 sp_count++;
5418 } else {
5419 tile_set_worked(ptile, pcity);
5420 workers++;
5421 }
5422
5423#ifdef FREECIV_DEBUG
5424 /* Set this tile to unused; a check for not reset tiles is
5425 * included in game_load_internal() */
5426 loading->worked_tiles[ptile->index] = -1;
5427#endif /* FREECIV_DEBUG */
5428 }
5430
5431 if (tile_worked(city_tile(pcity)) != pcity) {
5432 struct city *pwork = tile_worked(city_tile(pcity));
5433
5434 if (NULL != pwork) {
5435 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5436 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5439
5440 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5441 pwork->specialists[DEFAULT_SPECIALIST]++;
5443 } else {
5444 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5447 }
5448
5449 /* Repair pcity */
5452 }
5453
5455 if (0 != repair) {
5456 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5457 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5459 workers, FREE_WORKED_TILES, sp_count);
5460
5461 /* Repair pcity */
5463 }
5464
5465 /* worklist_init() done in create_city_virtual() */
5466 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5467
5468 /* Load city options. */
5469 BV_CLR_ALL(pcity->city_options);
5470 for (i = 0; i < loading->coptions.size; i++) {
5471 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5472 citystr, i)) {
5473 BV_SET(pcity->city_options, loading->coptions.order[i]);
5474 }
5475 }
5477 "%s.wlcb", citystr),
5478 FALSE, "%s", secfile_error());
5479 pcity->wlcb = tmp_int;
5480
5481 /* Load the city rally point. */
5482 {
5483 int len = secfile_lookup_int_default(loading->file, 0,
5484 "%s.rally_point_length", citystr);
5485 int unconverted;
5486
5487 pcity->rally_point.length = len;
5488 if (len > 0) {
5490
5491 pcity->rally_point.orders
5492 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5493 pcity->rally_point.persistent
5495 "%s.rally_point_persistent", citystr);
5496 pcity->rally_point.vigilant
5498 "%s.rally_point_vigilant", citystr);
5499
5502 "%s.rally_point_orders", citystr);
5505 "%s.rally_point_dirs", citystr);
5508 "%s.rally_point_activities", citystr);
5509
5510 for (i = 0; i < len; i++) {
5511 struct unit_order *order = &pcity->rally_point.orders[i];
5512
5513 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5514 || rally_activities[i] == '\0') {
5515 log_sg("Invalid rally point.");
5516 free(pcity->rally_point.orders);
5517 pcity->rally_point.orders = NULL;
5518 pcity->rally_point.length = 0;
5519 break;
5520 }
5521 order->order = char2order(rally_orders[i]);
5522 order->dir = char2dir(rally_dirs[i]);
5523 order->activity = char2activity(rally_activities[i]);
5524
5526 "%s.rally_point_action_vec,%d",
5527 citystr, i);
5528
5529 if (unconverted == -1) {
5530 order->action = ACTION_NONE;
5531 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5532 /* Look up what action id the unconverted number represents. */
5533 order->action = loading->action.order[unconverted];
5534 } else {
5535 if (order->order == ORDER_PERFORM_ACTION) {
5536 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5537 pcity->id);
5538 }
5539
5540 order->action = ACTION_NONE;
5541 }
5542
5543 order->target
5545 "%s.rally_point_tgt_vec,%d",
5546 citystr, i);
5547 order->sub_target
5549 "%s.rally_point_sub_tgt_vec,%d",
5550 citystr, i);
5551 }
5552 } else {
5553 pcity->rally_point.orders = NULL;
5554
5555 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5556 citystr);
5557 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5558 citystr);
5559 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5560 citystr);
5561 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5562 citystr);
5563 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5564 citystr);
5565 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5566 citystr);
5568 "%s.rally_point_tgt_vec", citystr);
5570 "%s.rally_point_sub_tgt_vec", citystr);
5571 }
5572 }
5573
5574 /* Load the city manager parameters. */
5575 {
5576 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5577 "%s.cma_enabled", citystr);
5578 if (enabled) {
5579 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5580
5581 for (i = 0; i < O_LAST; i++) {
5583 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5585 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5586 }
5587
5589 loading->file, FALSE, "%s.max_growth", citystr);
5591 loading->file, FALSE, "%s.require_happy", citystr);
5593 loading->file, FALSE, "%s.allow_disorder", citystr);
5595 loading->file, FALSE, "%s.allow_specialists", citystr);
5597 loading->file, 0, "%s.happy_factor", citystr);
5598 pcity->cm_parameter = param;
5599 } else {
5600 pcity->cm_parameter = NULL;
5601
5602 for (i = 0; i < O_LAST; i++) {
5604 "%s.cma_minimal_surplus,%d", citystr, i);
5606 "%s.cma_factor,%d", citystr, i);
5607 }
5608
5609 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5610 citystr);
5611 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5612 citystr);
5613 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5614 citystr);
5615 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5616 citystr);
5617 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5618 citystr);
5619 }
5620 }
5621
5622 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5623
5624 return TRUE;
5625}
5626
5627/************************************************************************/
5631 struct player *plr,
5632 struct city *pcity,
5633 const char *citystr)
5634{
5636 citizens size;
5637
5639 player_slots_iterate(pslot) {
5640 int nationality;
5641
5642 nationality = secfile_lookup_int_default(loading->file, -1,
5643 "%s.citizen%d", citystr,
5644 player_slot_index(pslot));
5645 if (nationality > 0 && !player_slot_is_used(pslot)) {
5646 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5648 continue;
5649 }
5650
5651 if (nationality != -1 && player_slot_is_used(pslot)) {
5652 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5653 "Invalid value for citizens of player %d in %s: %d.",
5654 player_slot_index(pslot), city_name_get(pcity), nationality);
5655 citizens_nation_set(pcity, pslot, nationality);
5656 }
5658 /* Sanity check. */
5660 if (size != city_size_get(pcity)) {
5661 if (size != 0) {
5662 /* size == 0 can be result from the fact that ruleset had no
5663 * nationality enabled at saving time, so no citizens at all
5664 * were saved. But something more serious must be going on if
5665 * citizens have been saved partially - if some of them are there. */
5666 log_sg("City size and number of citizens does not match in %s "
5667 "(%d != %d)! Repairing ...", city_name_get(pcity),
5669 }
5671 }
5672 }
5673}
5674
5675/************************************************************************/
5679 struct player *plr)
5680{
5682 int i = 0;
5683 int plrno = player_number(plr);
5685
5686 /* Check status and return if not OK (sg_success FALSE). */
5687 sg_check_ret();
5688
5690 "player%d.ncities", plrno);
5691
5693 /* Initialise the nation list for the citizens information. */
5694 player_slots_iterate(pslot) {
5697 }
5698
5699 /* First determine length of longest worklist, rally point order, and the
5700 * nationalities we have. */
5702 int routes;
5703
5704 /* Check the sanity of the city. */
5707
5708 if (pcity->worklist.length > wlist_max_length) {
5709 wlist_max_length = pcity->worklist.length;
5710 }
5711
5712 if (pcity->rally_point.length > rally_point_max_length) {
5713 rally_point_max_length = pcity->rally_point.length;
5714 }
5715
5716 routes = city_num_trade_routes(pcity);
5717 if (routes > routes_max) {
5718 routes_max = routes;
5719 }
5720
5722 /* Find all nations of the citizens,*/
5723 players_iterate(pplayer) {
5724 if (!nations[player_index(pplayer)]
5725 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5726 nations[player_index(pplayer)] = TRUE;
5727 }
5729 }
5731
5733 "player%d.wl_max_length", plrno);
5735 "player%d.routes_max_length", plrno);
5736
5738 struct tile *pcenter = city_tile(pcity);
5739 char impr_buf[B_LAST + 1];
5740 char buf[32];
5741 int j, nat_x, nat_y;
5742
5743 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5744
5745
5747 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5748 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5749
5750 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5751
5752 if (pcity->original != NULL) {
5753 secfile_insert_int(saving->file, player_number(pcity->original),
5754 "%s.original", buf);
5755 } else {
5756 secfile_insert_int(saving->file, -1, "%s.original", buf);
5757 }
5758 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5759
5761 "%s.capital", buf);
5762
5763 j = 0;
5765 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5766 buf, j++);
5768
5769 j = 0;
5771 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5772 buf, j);
5774 "%s.route_direction%d", buf, j);
5776 "%s.route_good%d", buf, j);
5777 j++;
5779
5780 /* Save dummy values to keep tabular format happy */
5781 for (; j < routes_max; j++) {
5782 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5784 "%s.route_direction%d", buf, j);
5786 "%s.route_good%d", buf, j);
5787 }
5788
5789 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5790 buf);
5791 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5792 buf);
5793 secfile_insert_int(saving->file, pcity->history, "%s.history",
5794 buf);
5795
5796 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5797 buf);
5798 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5799 buf);
5800 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5801 buf);
5802 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5803 buf);
5804
5805 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5806 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5807 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5808 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5809 buf);
5810 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5811 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5812 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5813 secfile_insert_int(saving->file, pcity->turn_last_built,
5814 "%s.turn_last_built", buf);
5815
5816 /* For visual debugging, variable length strings together here */
5817 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5818
5820 "%s.currently_building_kind", buf);
5822 "%s.currently_building_name", buf);
5823
5824 if (pcity->production.kind == VUT_IMPROVEMENT) {
5826 pcity->server.adv->
5827 building_want[improvement_index(pcity->production.value.building)],
5828 "%s.current_want", buf);
5829 } else {
5830 secfile_insert_int(saving->file, 0,
5831 "%s.current_want", buf);
5832 }
5833
5835 "%s.changed_from_kind", buf);
5837 "%s.changed_from_name", buf);
5838
5839 secfile_insert_int(saving->file, pcity->before_change_shields,
5840 "%s.before_change_shields", buf);
5841 secfile_insert_int(saving->file, pcity->caravan_shields,
5842 "%s.caravan_shields", buf);
5843 secfile_insert_int(saving->file, pcity->disbanded_shields,
5844 "%s.disbanded_shields", buf);
5845 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5846 "%s.last_turns_shield_surplus", buf);
5847
5849 "%s.style", buf);
5850
5851 /* Save the squared city radius and all tiles within the corresponding
5852 * city map. */
5853 secfile_insert_int(saving->file, pcity->city_radius_sq,
5854 "player%d.c%d.city_radius_sq", plrno, i);
5855 /* The tiles worked by the city are saved using the main map.
5856 * See also sg_save_map_worked(). */
5857
5858 /* Save improvement list as bytevector. Note that improvement order
5859 * is saved in savefile.improvement_order. */
5860 improvement_iterate(pimprove) {
5861 impr_buf[improvement_index(pimprove)]
5862 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5863 : '1';
5865 impr_buf[improvement_count()] = '\0';
5866
5868 "Invalid size of the improvement vector (%s.improvements: "
5869 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5870 strlen(impr_buf), sizeof(impr_buf));
5871 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5872
5873 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5874 buf);
5875
5876 for (j = 0; j < CITYO_LAST; j++) {
5877 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5878 "%s.option%d", buf, j);
5879 }
5880 secfile_insert_int(saving->file, pcity->wlcb,
5881 "%s.wlcb", buf);
5882
5883 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5884
5886 /* Save nationality of the citizens,*/
5887 players_iterate(pplayer) {
5888 if (nations[player_index(pplayer)]) {
5890 citizens_nation_get(pcity, pplayer->slot),
5891 "%s.citizen%d", buf, player_index(pplayer));
5892 }
5894 }
5895
5896 secfile_insert_int(saving->file, pcity->rally_point.length,
5897 "%s.rally_point_length", buf);
5898 if (pcity->rally_point.length) {
5899 int len = pcity->rally_point.length;
5900 char orders[len + 1], dirs[len + 1], activities[len + 1];
5901 int actions[len];
5902 int targets[len];
5903 int sub_targets[len];
5904
5905 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5906 "%s.rally_point_persistent", buf);
5907 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5908 "%s.rally_point_vigilant", buf);
5909
5910 for (j = 0; j < len; j++) {
5911 orders[j] = order2char(pcity->rally_point.orders[j].order);
5912 dirs[j] = '?';
5913 activities[j] = '?';
5914 targets[j] = NO_TARGET;
5915 sub_targets[j] = NO_TARGET;
5916 actions[j] = -1;
5917 switch (pcity->rally_point.orders[j].order) {
5918 case ORDER_MOVE:
5919 case ORDER_ACTION_MOVE:
5920 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5921 break;
5922 case ORDER_ACTIVITY:
5923 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5924 activities[j]
5925 = activity2char(pcity->rally_point.orders[j].activity);
5926 actions[j]
5927 = pcity->rally_point.orders[j].action;
5928 break;
5930 actions[j] = pcity->rally_point.orders[j].action;
5931 targets[j] = pcity->rally_point.orders[j].target;
5932 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5933 break;
5934 case ORDER_FULL_MP:
5935 case ORDER_LAST:
5936 break;
5937 }
5938
5939 if (actions[j] == ACTION_NONE) {
5940 actions[j] = -1;
5941 }
5942 }
5943 orders[len] = dirs[len] = activities[len] = '\0';
5944
5945 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5946 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5947 secfile_insert_str(saving->file, activities,
5948 "%s.rally_point_activities", buf);
5949
5951 "%s.rally_point_action_vec", buf);
5952 /* Fill in dummy values for order targets so the registry will save
5953 * the unit table in a tabular format. */
5954 for (j = len; j < rally_point_max_length; j++) {
5955 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5956 buf, j);
5957 }
5958
5959 secfile_insert_int_vec(saving->file, targets, len,
5960 "%s.rally_point_tgt_vec", buf);
5961 /* Fill in dummy values for order targets so the registry will save
5962 * the unit table in a tabular format. */
5963 for (j = len; j < rally_point_max_length; j++) {
5965 "%s.rally_point_tgt_vec,%d", buf, j);
5966 }
5967
5968 secfile_insert_int_vec(saving->file, sub_targets, len,
5969 "%s.rally_point_sub_tgt_vec", buf);
5970 /* Fill in dummy values for order targets so the registry will save
5971 * the unit table in a tabular format. */
5972 for (j = len; j < rally_point_max_length; j++) {
5973 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5974 buf, j);
5975 }
5976 } else {
5977 /* Put all the same fields into the savegame - otherwise the
5978 * registry code can't correctly use a tabular format and the
5979 * savegame will be bigger. */
5980 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5981 buf);
5982 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5983 buf);
5984 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5985 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5986 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5987 buf);
5988
5989 /* Fill in dummy values for order targets so the registry will save
5990 * the unit table in a tabular format. */
5991
5992 /* The start of a vector has no number. */
5993 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5994 buf);
5995 for (j = 1; j < rally_point_max_length; j++) {
5996 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5997 buf, j);
5998 }
5999
6000 /* The start of a vector has no number. */
6001 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
6002 buf);
6003 for (j = 1; j < rally_point_max_length; j++) {
6005 "%s.rally_point_tgt_vec,%d", buf, j);
6006 }
6007
6008 /* The start of a vector has no number. */
6009 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
6010 buf);
6011 for (j = 1; j < rally_point_max_length; j++) {
6012 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
6013 buf, j);
6014 }
6015 }
6016
6017 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
6018 "%s.cma_enabled", buf);
6019 if (pcity->cm_parameter) {
6021 pcity->cm_parameter->minimal_surplus, O_LAST,
6022 "%s.cma_minimal_surplus", buf);
6024 pcity->cm_parameter->factor, O_LAST,
6025 "%s.cma_factor", buf);
6026 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6027 "%s.max_growth", buf);
6028 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6029 "%s.require_happy", buf);
6030 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6031 "%s.allow_disorder", buf);
6033 pcity->cm_parameter->allow_specialists,
6034 "%s.allow_specialists", buf);
6035 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6036 "%s.happy_factor", buf);
6037 } else {
6038 int zeros[O_LAST];
6039
6040 memset(zeros, 0, sizeof(zeros));
6042 "%s.cma_minimal_surplus", buf);
6044 "%s.cma_factor", buf);
6045 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6046 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6047 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6048 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6049 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6050 }
6051
6052 i++;
6054
6055 i = 0;
6057 worker_task_list_iterate(pcity->task_reqs, ptask) {
6058 int nat_x, nat_y;
6059
6061 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6062 plrno, i);
6063 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6064 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6066 "player%d.task%d.activity",
6067 plrno, i);
6068 if (ptask->tgt != NULL) {
6070 "player%d.task%d.target",
6071 plrno, i);
6072 } else {
6073 secfile_insert_str(saving->file, "-",
6074 "player%d.task%d.target",
6075 plrno, i);
6076 }
6077 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6078
6079 i++;
6082}
6083
6084/************************************************************************/
6088 struct player *plr)
6089{
6090 int nunits, i, plrno = player_number(plr);
6091 size_t orders_max_length;
6092
6093 /* Check status and return if not OK (sg_success FALSE). */
6094 sg_check_ret();
6095
6097 "player%d.nunits", plrno),
6098 "%s", secfile_error());
6099 if (!plr->is_alive && nunits > 0) {
6100 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6101 nunits = 0; /* Some old savegames may be buggy. */
6102 }
6103
6105 "player%d.orders_max_length",
6106 plrno);
6107
6108 for (i = 0; i < nunits; i++) {
6109 struct unit *punit;
6110 struct city *pcity;
6111 const char *name;
6112 char buf[32];
6113 struct unit_type *type;
6114 struct tile *ptile;
6115
6116 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6117
6118 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6120 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6121
6122 /* Create a dummy unit. */
6123 punit = unit_virtual_create(plr, NULL, type, 0);
6126 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6127 }
6128
6131
6133 unit_list_prepend(pcity->units_supported, punit);
6134 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6135 log_sg("%s: bad home city %d.", buf, punit->homecity);
6137 }
6138
6139 ptile = unit_tile(punit);
6140
6141 /* allocate the unit's contribution to fog of war */
6144 /* NOTE: There used to be some map_set_known calls here. These were
6145 * unneeded since unfogging the tile when the unit sees it will
6146 * automatically reveal that tile. */
6147
6150 }
6151}
6152
6153/************************************************************************/
6157 struct player *plr, struct unit *punit,
6159 const char *unitstr)
6160{
6161 enum unit_activity activity;
6162 int nat_x, nat_y;
6163 struct extra_type *pextra = NULL;
6164 struct tile *ptile;
6165 int extra_id;
6166 int ei;
6167 const char *facing_str;
6168 int natnbr;
6169 int unconverted;
6170 const char *str;
6171 enum gen_action action;
6172
6174 unitstr), FALSE, "%s", secfile_error());
6176 FALSE, "%s", secfile_error());
6178 FALSE, "%s", secfile_error());
6179
6180 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6181 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6182 unitstr, nat_x, nat_y);
6183 unit_tile_set(punit, ptile);
6184
6187 "%s.facing", unitstr);
6188 if (facing_str[0] != 'x') {
6189 /* We don't touch punit->facing if savegame does not contain that
6190 * information. Initial orientation set by unit_virtual_create()
6191 * is as good as any. */
6192 enum direction8 facing = char2dir(facing_str[0]);
6193
6194 if (direction8_is_valid(facing)) {
6195 punit->facing = facing;
6196 } else {
6197 log_error("Illegal unit orientation '%s'", facing_str);
6198 }
6199 }
6200
6201 /* If savegame has unit nationality, it doesn't hurt to
6202 * internally set it even if nationality rules are disabled. */
6204 player_number(plr),
6205 "%s.nationality", unitstr);
6206
6208 if (punit->nationality == NULL) {
6209 punit->nationality = plr;
6210 }
6211
6213 "%s.homecity", unitstr), FALSE,
6214 "%s", secfile_error());
6216 "%s.moves", unitstr), FALSE,
6217 "%s", secfile_error());
6219 "%s.fuel", unitstr), FALSE,
6220 "%s", secfile_error());
6222 "%s.activity", unitstr), FALSE,
6223 "%s", secfile_error());
6224 activity = unit_activity_by_name(loading->activities.order[ei],
6227 "%s.action", unitstr), FALSE,
6228 "%s", secfile_error());
6229 if (ei == -1) {
6231 } else if (ei >= 0 && ei < loading->action.size) {
6232 action = loading->action.order[ei];
6233 } else {
6234 log_sg("Invalid action id for unit %d", punit->id);
6236 }
6237
6240 "%s.born", unitstr);
6243 "%s.current_form_turn", unitstr);
6244
6246 "%s.activity_tgt", unitstr);
6247
6248 if (extra_id != -2) {
6249 if (extra_id >= 0 && extra_id < loading->extra.size) {
6250 pextra = loading->extra.order[extra_id];
6251 set_unit_activity_targeted(punit, activity, pextra, action);
6252 } else if (activity == ACTIVITY_IRRIGATE) {
6256 punit);
6257 if (tgt != NULL) {
6259 } else {
6261 }
6262 } else if (activity == ACTIVITY_MINE) {
6264 EC_MINE,
6266 punit);
6267 if (tgt != NULL) {
6269 } else {
6271 }
6272 } else {
6273 set_unit_activity(punit, activity, action);
6274 }
6275 } else {
6277 } /* activity_tgt == NULL */
6278
6280 "%s.activity_count", unitstr), FALSE,
6281 "%s", secfile_error());
6282
6285 "%s.changed_from", unitstr);
6286
6288 "%s.changed_from_tgt", unitstr), FALSE,
6289 "%s", secfile_error());
6290
6291 if (extra_id >= 0 && extra_id < loading->extra.size) {
6292 punit->changed_from_target = loading->extra.order[extra_id];
6293 } else {
6295 }
6296
6299 "%s.changed_from_count", unitstr);
6300
6301 /* Special case: for a long time, we accidentally incremented
6302 * activity_count while a unit was sentried, so it could increase
6303 * without bound (bug #20641) and be saved in old savefiles.
6304 * We zero it to prevent potential trouble overflowing the range
6305 * in network packets, etc. */
6306 if (activity == ACTIVITY_SENTRY) {
6307 punit->activity_count = 0;
6308 }
6311 }
6312
6313 punit->veteran
6314 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6315 {
6316 /* Protect against change in veteran system in ruleset */
6317 const int levels = utype_veteran_levels(unit_type_get(punit));
6318
6319 if (punit->veteran >= levels) {
6320 fc_assert(levels >= 1);
6321 punit->veteran = levels - 1;
6322 }
6323 }
6326 "%s.done_moving", unitstr);
6329 "%s.battlegroup", unitstr);
6330
6332 "%s.go", unitstr)) {
6333 int gnat_x, gnat_y;
6334
6336 "%s.goto_x", unitstr), FALSE,
6337 "%s", secfile_error());
6339 "%s.goto_y", unitstr), FALSE,
6340 "%s", secfile_error());
6341
6343 } else {
6344 punit->goto_tile = NULL;
6345
6346 if (punit->activity == ACTIVITY_GOTO) {
6347 /* goto_tile should never be NULL with ACTIVITY_GOTO */
6348 sg_regr(3020200, "Unit %d on goto without goto_tile. Aborting goto.",
6349 punit->id);
6351 }
6352
6353 /* These variables are not used but needed for saving the unit table.
6354 * Load them to prevent unused variables errors. */
6355 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6356 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6357 }
6358
6359 /* Load AI data of the unit. */
6360 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6361
6364 "%s.server_side_agent",
6365 unitstr);
6366 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6367 /* Look up what server side agent the unconverted number represents. */
6368 punit->ssa_controller = loading->ssa.order[unconverted];
6369 } else {
6370 log_sg("Invalid server side agent %d for unit %d",
6371 unconverted, punit->id);
6372
6374 }
6375
6377 "%s.hp", unitstr), FALSE,
6378 "%s", secfile_error());
6379
6381 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6383 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6384 punit->moved
6385 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6388 "%s.paradropped", unitstr);
6389 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6390 if (str[0] != '\0') {
6392 }
6393
6394 /* The transport status (punit->transported_by) is loaded in
6395 * sg_player_units_transport(). */
6396
6397 /* Initialize upkeep values: these are hopefully initialized
6398 * elsewhere before use (specifically, in city_support(); but
6399 * fixme: check whether always correctly initialized?).
6400 * Below is mainly for units which don't have homecity --
6401 * otherwise these don't get initialized (and AI calculations
6402 * etc may use junk values). */
6406
6408 "%s.action_decision", unitstr),
6409 FALSE, "%s", secfile_error());
6410
6411 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6412 /* Look up what action decision want the unconverted number
6413 * represents. */
6414 punit->action_decision_want = loading->act_dec.order[unconverted];
6415 } else {
6416 log_sg("Invalid action decision want for unit %d", punit->id);
6417
6419 }
6420
6422 /* Load the tile to act against. */
6423 int adwt_x, adwt_y;
6424
6425 if (secfile_lookup_int(loading->file, &adwt_x,
6426 "%s.action_decision_tile_x", unitstr)
6428 "%s.action_decision_tile_y", unitstr)) {
6430 adwt_x, adwt_y);
6431 } else {
6434 log_sg("Bad action_decision_tile for unit %d", punit->id);
6435 }
6436 } else {
6437 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6438 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6440 }
6441
6443
6444 /* Load the unit orders */
6445 {
6446 int len = secfile_lookup_int_default(loading->file, 0,
6447 "%s.orders_length", unitstr);
6448
6449 if (len > 0) {
6450 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6451 int j;
6452
6453 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6457 "%s.orders_index", unitstr);
6460 "%s.orders_repeat", unitstr);
6463 "%s.orders_vigilant", unitstr);
6464
6467 "%s.orders_list", unitstr);
6470 "%s.dir_list", unitstr);
6473 "%s.activity_list", unitstr);
6474
6476
6477 for (j = 0; j < len; j++) {
6478 struct unit_order *order = &punit->orders.list[j];
6480 int order_sub_tgt;
6481
6482 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6483 || act_unitstr[j] == '\0') {
6484 log_sg("Invalid unit orders.");
6486 break;
6487 }
6488 order->order = char2order(orders_unitstr[j]);
6489 order->dir = char2dir(dir_unitstr[j]);
6490 order->activity = char2activity(act_unitstr[j]);
6491
6493 "%s.action_vec,%d",
6494 unitstr, j);
6495
6496 if (unconverted == -1) {
6497 order->action = ACTION_NONE;
6498 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6499 /* Look up what action id the unconverted number represents. */
6500 order->action = loading->action.order[unconverted];
6501 } else {
6502 if (order->order == ORDER_PERFORM_ACTION) {
6503 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6504 }
6505
6506 order->action = ACTION_NONE;
6507 }
6508
6509 if (order->order == ORDER_LAST
6510 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6511 || (order->order == ORDER_ACTION_MOVE
6512 && !direction8_is_valid(order->dir))
6513 || (order->order == ORDER_PERFORM_ACTION
6514 && !action_id_exists(order->action))
6515 || (order->order == ORDER_ACTIVITY
6516 && (order->activity == ACTIVITY_LAST
6517 || !action_id_exists(order->action)))) {
6518 /* An invalid order. Just drop the orders for this unit. */
6520 punit->orders.list = NULL;
6521 punit->orders.length = 0;
6523 punit->goto_tile = NULL;
6524 break;
6525 }
6526
6528 "%s.tgt_vec,%d",
6529 unitstr, j);
6531 "%s.sub_tgt_vec,%d",
6532 unitstr, j);
6533
6534 if (order->order == ORDER_PERFORM_ACTION) {
6535 /* Validate sub target */
6536 switch (action_id_get_sub_target_kind(order->action)) {
6537 case ASTK_BUILDING:
6538 /* Sub target is a building. */
6539 if (order_sub_tgt < 0
6540 || order_sub_tgt >= loading->improvement.size
6541 || !loading->improvement.order[order_sub_tgt]) {
6542 /* Sub target is invalid. */
6543 log_sg("Cannot find building %d for %s to %s",
6546 order->sub_target = B_LAST;
6547 } else {
6548 struct impr_type *pimprove
6549 = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
6550
6551 if (pimprove != NULL) {
6552 order->sub_target = improvement_index(pimprove);
6553 }
6554 }
6555 break;
6556 case ASTK_TECH:
6557 /* Sub target is a technology. */
6558 {
6559 bool failure = order_sub_tgt < 0
6560 || order_sub_tgt >= loading->technology.size
6561 || !loading->technology.order[order_sub_tgt];
6562 struct advance *padvance = NULL;
6563
6564 if (!failure) {
6565 padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
6566 }
6567 if (padvance == NULL) {
6568 /* Target tech is invalid. */
6569 log_sg("Cannot find tech %d for %s to steal",
6571 order->sub_target = A_NONE;
6572 } else {
6574 }
6575 }
6576 break;
6577 case ASTK_EXTRA:
6579 /* These take an extra. */
6581 break;
6582 case ASTK_SPECIALIST:
6583 /* A valid specialist must be supplied. */
6584 if (order_sub_tgt < 0
6585 || order_sub_tgt >= loading->specialist.size
6586 || !loading->specialist.order[order_sub_tgt]) {
6587 log_sg("Cannot find specialist %d for %s to become",
6589 order->sub_target = NO_TARGET;
6590 } else {
6591 order->sub_target = specialist_index(loading->specialist.order[order_sub_tgt]);
6592 }
6593 break;
6594 case ASTK_NONE:
6595 /* None of these can take a sub target. */
6597 "Specified sub target for action %d unsupported.",
6598 order->action);
6599 order->sub_target = NO_TARGET;
6600 break;
6601 case ASTK_COUNT:
6603 "Bad action action %d.",
6604 order->action);
6605 order->sub_target = NO_TARGET;
6606 break;
6607 }
6608 }
6609
6610 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6611 enum unit_activity act;
6612
6614 || !loading->extra.order[order_sub_tgt]) {
6615 if (order_sub_tgt != EXTRA_NONE) {
6616 log_sg("Cannot find extra %d for %s to build",
6618 }
6619
6620 order->sub_target = EXTRA_NONE;
6621 } else {
6622 order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
6623 }
6624
6625 /* An action or an activity may require an extra target. */
6626 if (action_wants_extra) {
6627 act = action_id_get_activity(order->action);
6628 } else {
6629 act = order->activity;
6630 }
6631
6632 if (unit_activity_is_valid(act)
6634 && order->sub_target == EXTRA_NONE) {
6635 /* Missing required action extra target. */
6637 punit->orders.list = NULL;
6638 punit->orders.length = 0;
6640 punit->goto_tile = NULL;
6641 break;
6642 }
6643 } else if (order->order != ORDER_PERFORM_ACTION) {
6644 if (order_sub_tgt != -1) {
6645 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6646 order_sub_tgt, -1, order->order);
6647 }
6648 order->sub_target = NO_TARGET;
6649 }
6650 }
6651
6652 for (; j < orders_max_length; j++) {
6654 "%s.action_vec,%d", unitstr, j);
6656 "%s.tgt_vec,%d", unitstr, j);
6658 "%s.sub_tgt_vec,%d", unitstr, j);
6659 }
6660 } else {
6661 int j;
6662
6664
6665 /* Never nullify goto_tile for a unit that is in active goto. */
6666 if (punit->activity != ACTIVITY_GOTO) {
6667 punit->goto_tile = NULL;
6668 }
6669
6670 punit->orders.list = NULL;
6671 punit->orders.length = 0;
6672
6673 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6674 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6675 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6676 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6677 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6678 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6679 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6680 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6681 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6682
6683 for (j = 1; j < orders_max_length; j++) {
6685 "%s.action_vec,%d", unitstr, j);
6687 "%s.tgt_vec,%d", unitstr, j);
6689 "%s.sub_tgt_vec,%d", unitstr, j);
6690 }
6691 }
6692 }
6693
6694 return TRUE;
6695}
6696
6697/************************************************************************/
6702 struct player *plr)
6703{
6704 int nunits, i, plrno = player_number(plr);
6705
6706 /* Check status and return if not OK (sg_success FALSE). */
6707 sg_check_ret();
6708
6709 /* Recheck the number of units for the player. This is a copied from
6710 * sg_load_player_units(). */
6712 "player%d.nunits", plrno),
6713 "%s", secfile_error());
6714 if (!plr->is_alive && nunits > 0) {
6715 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6716 nunits = 0; /* Some old savegames may be buggy. */
6717 }
6718
6719 for (i = 0; i < nunits; i++) {
6720 int id_unit, id_trans;
6721 struct unit *punit, *ptrans;
6722
6724 "player%d.u%d.id",
6725 plrno, i);
6727 fc_assert_action(punit != NULL, continue);
6728
6730 "player%d.u%d.transported_by",
6731 plrno, i);
6732 if (id_trans == -1) {
6733 /* Not transported. */
6734 continue;
6735 }
6736
6738 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6739
6740 if (ptrans) {
6741#ifndef FREECIV_NDEBUG
6742 bool load_success =
6743#endif
6745
6746 fc_assert_action(load_success, continue);
6747 }
6748 }
6749}
6750
6751/************************************************************************/
6755 struct player *plr)
6756{
6757 int i = 0;
6758 int longest_order = 0;
6759 int plrno = player_number(plr);
6760
6761 /* Check status and return if not OK (sg_success FALSE). */
6762 sg_check_ret();
6763
6765 "player%d.nunits", plrno);
6766
6767 /* Find the longest unit order so different order length won't break
6768 * storing units in the tabular format. */
6770 if (punit->has_orders) {
6771 if (longest_order < punit->orders.length) {
6773 }
6774 }
6776
6778 "player%d.orders_max_length", plrno);
6779
6781 char buf[32];
6782 char dirbuf[2] = " ";
6783 int nat_x, nat_y;
6784 int last_order, j;
6785
6786 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6787 dirbuf[0] = dir2char(punit->facing);
6788 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6789
6791 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6792 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6793
6794 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6797 "%s.nationality", buf);
6798 }
6799 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6800 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6801 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6803 "%s.type_by_name", buf);
6804
6805 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6807 "%s.activity_count", buf);
6808 if (punit->action == ACTION_NONE) {
6809 secfile_insert_int(saving->file, -1, "%s.action", buf);
6810 } else {
6811 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6812 }
6813 if (punit->activity_target == NULL) {
6814 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6815 } else {
6817 "%s.activity_tgt", buf);
6818 }
6819
6821 "%s.changed_from", buf);
6823 "%s.changed_from_count", buf);
6824 if (punit->changed_from_target == NULL) {
6825 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6826 } else {
6828 "%s.changed_from_tgt", buf);
6829 }
6830
6832 "%s.done_moving", buf);
6833 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6834 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6836 "%s.born", buf);
6838 "%s.current_form_turn", buf);
6840 "%s.battlegroup", buf);
6841
6842 if (punit->goto_tile) {
6844 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6845 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6846 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6847 } else {
6848 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6849 /* Set this values to allow saving it as table. */
6850 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6851 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6852 }
6853
6855 "%s.server_side_agent", buf);
6856
6857 /* Save AI data of the unit. */
6858 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6859
6861 "%s.ord_map", buf);
6863 "%s.ord_city", buf);
6864 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6866 "%s.paradropped", buf);
6868 ? unit_transport_get(punit)->id : -1,
6869 "%s.transported_by", buf);
6870 if (punit->carrying != NULL) {
6872 "%s.carrying", buf);
6873 } else {
6874 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6875 }
6876
6878 "%s.action_decision", buf);
6879
6880 /* Stored as tile rather than direction to make sure the target tile is
6881 * sane. */
6886 "%s.action_decision_tile_x", buf);
6888 "%s.action_decision_tile_y", buf);
6889 } else {
6890 /* Dummy values to get tabular format. */
6891 secfile_insert_int(saving->file, -1,
6892 "%s.action_decision_tile_x", buf);
6893 secfile_insert_int(saving->file, -1,
6894 "%s.action_decision_tile_y", buf);
6895 }
6896
6898 "%s.stay", buf);
6899
6900 if (punit->has_orders) {
6901 int len = punit->orders.length;
6902 char orders_buf[len + 1], dir_buf[len + 1];
6903 char act_buf[len + 1];
6904 int action_buf[len];
6905 int tgt_vec[len];
6906 int sub_tgt_vec[len];
6907
6908 last_order = len;
6909
6910 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6912 "%s.orders_index", buf);
6914 "%s.orders_repeat", buf);
6916 "%s.orders_vigilant", buf);
6917
6918 for (j = 0; j < len; j++) {
6920 dir_buf[j] = '?';
6921 act_buf[j] = '?';
6922 tgt_vec[j] = NO_TARGET;
6923 sub_tgt_vec[j] = -1;
6924 action_buf[j] = -1;
6925 switch (punit->orders.list[j].order) {
6926 case ORDER_MOVE:
6927 case ORDER_ACTION_MOVE:
6928 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6929 break;
6930 case ORDER_ACTIVITY:
6934 break;
6937 tgt_vec[j] = punit->orders.list[j].target;
6939 break;
6940 case ORDER_FULL_MP:
6941 case ORDER_LAST:
6942 break;
6943 }
6944
6945 if (action_buf[j] == ACTION_NONE) {
6946 action_buf[j] = -1;
6947 }
6948 }
6949 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6950
6951 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6952 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6953 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6954
6956 "%s.action_vec", buf);
6957 /* Fill in dummy values for order targets so the registry will save
6958 * the unit table in a tabular format. */
6959 for (j = last_order; j < longest_order; j++) {
6960 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6961 }
6962
6964 "%s.tgt_vec", buf);
6965 /* Fill in dummy values for order targets so the registry will save
6966 * the unit table in a tabular format. */
6967 for (j = last_order; j < longest_order; j++) {
6968 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6969 }
6970
6972 "%s.sub_tgt_vec", buf);
6973 /* Fill in dummy values for order targets so the registry will save
6974 * the unit table in a tabular format. */
6975 for (j = last_order; j < longest_order; j++) {
6976 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6977 }
6978 } else {
6979
6980 /* Put all the same fields into the savegame - otherwise the
6981 * registry code can't correctly use a tabular format and the
6982 * savegame will be bigger. */
6983 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6984 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6985 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6986 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6987 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6988 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6989 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6990
6991 /* Fill in dummy values for order targets so the registry will save
6992 * the unit table in a tabular format. */
6993
6994 /* The start of a vector has no number. */
6995 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6996 for (j = 1; j < longest_order; j++) {
6997 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6998 }
6999
7000 /* The start of a vector has no number. */
7001 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
7002 for (j = 1; j < longest_order; j++) {
7003 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
7004 }
7005
7006 /* The start of a vector has no number. */
7007 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
7008 for (j = 1; j < longest_order; j++) {
7009 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
7010 }
7011 }
7012
7013 i++;
7015}
7016
7017/************************************************************************/
7021 struct player *plr)
7022{
7023 int plrno = player_number(plr);
7024
7025 /* Check status and return if not OK (sg_success FALSE). */
7026 sg_check_ret();
7027
7028 /* Toss any existing attribute_block (should not exist) */
7029 if (plr->attribute_block.data) {
7031 plr->attribute_block.data = NULL;
7032 }
7033
7034 /* This is a big heap of opaque data for the client, check everything! */
7036 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
7037
7038 if (0 > plr->attribute_block.length) {
7039 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
7040 plr->attribute_block.length);
7041 plr->attribute_block.length = 0;
7042 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
7043 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
7045 plr->attribute_block.length = 0;
7046 } else if (0 < plr->attribute_block.length) {
7047 int part_nr, parts;
7048 int quoted_length;
7049 char *quoted;
7050#ifndef FREECIV_NDEBUG
7051 size_t actual_length;
7052#endif
7053
7056 "player%d.attribute_v2_block_length_quoted",
7057 plrno), "%s", secfile_error());
7060 "player%d.attribute_v2_block_parts", plrno),
7061 "%s", secfile_error());
7062
7064 quoted[0] = '\0';
7066 for (part_nr = 0; part_nr < parts; part_nr++) {
7067 const char *current =
7069 "player%d.attribute_v2_block_data.part%d",
7070 plrno, part_nr);
7071 if (!current) {
7072 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7073 break;
7074 }
7075 log_debug("attribute_v2_block_length_quoted=%d"
7076 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7077 quoted_length, strlen(quoted), strlen(current));
7078 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7079 strcat(quoted, current);
7080 }
7082 "attribute_v2_block_length_quoted=%d"
7083 " actual=" SIZE_T_PRINTF,
7085
7086#ifndef FREECIV_NDEBUG
7088#endif
7090 plr->attribute_block.data,
7091 plr->attribute_block.length);
7093 free(quoted);
7094 }
7095}
7096
7097/************************************************************************/
7101 struct player *plr)
7102{
7103 int plrno = player_number(plr);
7104
7105 /* Check status and return if not OK (sg_success FALSE). */
7106 sg_check_ret();
7107
7108 /* This is a big heap of opaque data from the client. Although the binary
7109 * format is not user editable, keep the lines short enough for debugging,
7110 * and hope that data compression will keep the file a reasonable size.
7111 * Note that the "quoted" format is a multiple of 3.
7112 */
7113#define PART_SIZE (3*256)
7114#define PART_ADJUST (3)
7115 if (plr->attribute_block.data) {
7116 char part[PART_SIZE + PART_ADJUST];
7117 int parts;
7118 int current_part_nr;
7120 plr->attribute_block.length);
7121 char *quoted_at = strchr(quoted, ':');
7122 size_t bytes_left = strlen(quoted);
7123 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7125
7127 "player%d.attribute_v2_block_length", plrno);
7129 "player%d.attribute_v2_block_length_quoted", plrno);
7130
7131 /* Try to wring some compression efficiencies out of the "quoted" format.
7132 * The first line has a variable length decimal, mis-aligning triples.
7133 */
7134 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7135 /* first line can be longer */
7136 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7137 } else {
7138 parts = 1;
7139 }
7140
7142 "player%d.attribute_v2_block_parts", plrno);
7143
7144 if (parts > 1) {
7146
7147 /* first line can be longer */
7149 part[size_of_current_part] = '\0';
7151 "player%d.attribute_v2_block_data.part%d",
7152 plrno, 0);
7155 current_part_nr = 1;
7156 } else {
7157 quoted_at = quoted;
7158 current_part_nr = 0;
7159 }
7160
7163
7165 part[size_of_current_part] = '\0';
7167 "player%d.attribute_v2_block_data.part%d",
7168 plrno,
7172 }
7173 fc_assert(bytes_left == 0);
7174 free(quoted);
7175 }
7176#undef PART_ADJUST
7177#undef PART_SIZE
7178}
7179
7180/************************************************************************/
7184 struct player *plr)
7185{
7186 int plrno = player_number(plr);
7187 int total_ncities
7189 "player%d.dc_total", plrno);
7190 int i;
7191 bool someone_alive = FALSE;
7192
7193 /* Check status and return if not OK (sg_success FALSE). */
7194 sg_check_ret();
7195
7198 if (pteam_member->is_alive) {
7200 break;
7201 }
7203
7204 if (!someone_alive) {
7205 /* Reveal all for completely dead teams. */
7207 }
7208 }
7209
7210 if (-1 == total_ncities
7211 || !game.info.fogofwar
7213 "game.save_private_map")) {
7214 /* We have:
7215 * - a dead player;
7216 * - fogged cities are not saved for any reason;
7217 * - a savegame with fog of war turned off;
7218 * - or game.save_private_map is not set to FALSE in the scenario /
7219 * savegame. The players private knowledge is set to be what they could
7220 * see without fog of war. */
7221 whole_map_iterate(&(wld.map), ptile) {
7222 if (map_is_known(ptile, plr)) {
7223 struct city *pcity = tile_city(ptile);
7224
7225 update_player_tile_last_seen(plr, ptile);
7226 update_player_tile_knowledge(plr, ptile);
7227
7228 if (NULL != pcity) {
7229 update_dumb_city(plr, pcity);
7230 }
7231 }
7233
7234 /* Nothing more to do; */
7235 return;
7236 }
7237
7238 /* Load player map (terrain). */
7239 LOAD_MAP_CHAR(ch, ptile,
7240 map_get_player_tile(ptile, plr)->terrain
7241 = char2terrain(ch), loading->file,
7242 "player%d.map_t%04d", plrno);
7243
7244 /* Load player map (extras). */
7245 halfbyte_iterate_extras(j, loading->extra.size) {
7246 LOAD_MAP_CHAR(ch, ptile,
7248 ch, loading->extra.order + 4 * j),
7249 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7251
7252 whole_map_iterate(&(wld.map), ptile) {
7253 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7254 bool regr_warn = FALSE;
7255
7257 int pres_id = extra_number(pres);
7258
7259 if (BV_ISSET(plrtile->extras, pres_id)) {
7260 if (plrtile->terrain == nullptr) {
7261 if (!regr_warn) {
7262 sg_regr(3030000, "FoW tile (%d, %d) has extras, though it's on unknown.",
7263 TILE_XY(ptile));
7264 regr_warn = TRUE;
7265 }
7266 BV_CLR(plrtile->extras, pres_id);
7267 } else {
7268 plrtile->resource = pres;
7269 if (!terrain_has_resource(plrtile->terrain, pres)) {
7270 BV_CLR(plrtile->extras, pres_id);
7271 }
7272 }
7273 }
7276
7278 /* Load player map (border). */
7279 int x, y;
7280
7281 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7282 const char *buffer
7283 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7284 plrno, y);
7285 const char *buffer2
7286 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7287 plrno, y);
7288 const char *ptr = buffer;
7289 const char *ptr2 = buffer2;
7290
7291 sg_failure_ret(NULL != buffer,
7292 "Savegame corrupt - map line %d not found.", y);
7293 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7294 char token[TOKEN_SIZE];
7295 char token2[TOKEN_SIZE];
7296 int number;
7297 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7298
7299 scanin(&ptr, ",", token, sizeof(token));
7300 sg_failure_ret('\0' != token[0],
7301 "Savegame corrupt - map size not correct.");
7302 if (strcmp(token, "-") == 0) {
7303 map_get_player_tile(ptile, plr)->owner = NULL;
7304 } else {
7305 sg_failure_ret(str_to_int(token, &number),
7306 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7307 token, x, y);
7308 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7309 }
7310
7311 scanin(&ptr2, ",", token2, sizeof(token2));
7312 sg_failure_ret('\0' != token2[0],
7313 "Savegame corrupt - map size not correct.");
7314 if (strcmp(token2, "-") == 0) {
7315 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7316 } else {
7318 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7319 token, x, y);
7320 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7321 }
7322 }
7323 }
7324 }
7325
7326 /* Load player map (update time). */
7327 for (i = 0; i < 4; i++) {
7328 /* put 4-bit segments of 16-bit "updated" field */
7329 if (i == 0) {
7330 LOAD_MAP_CHAR(ch, ptile,
7331 map_get_player_tile(ptile, plr)->last_updated
7332 = ascii_hex2bin(ch, i),
7333 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7334 } else {
7335 LOAD_MAP_CHAR(ch, ptile,
7336 map_get_player_tile(ptile, plr)->last_updated
7337 |= ascii_hex2bin(ch, i),
7338 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7339 }
7340 }
7341
7342 /* Load player map known cities. */
7343 for (i = 0; i < total_ncities; i++) {
7344 struct vision_site *pdcity;
7345 char buf[32];
7346 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7347
7351 pdcity);
7353 } else {
7354 /* Error loading the data. */
7355 log_sg("Skipping seen city %d for player %d.", i, plrno);
7356 if (pdcity != NULL) {
7358 }
7359 }
7360 }
7361
7362 /* Repair inconsistent player maps. */
7363 whole_map_iterate(&(wld.map), ptile) {
7364 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7365 struct city *pcity = tile_city(ptile);
7366
7367 update_player_tile_knowledge(plr, ptile);
7368 reality_check_city(plr, ptile);
7369
7370 if (NULL != pcity) {
7371 update_dumb_city(plr, pcity);
7372 }
7373 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7374 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7375 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7376
7377 plrtile->owner = tile_owner(ptile);
7378 }
7380}
7381
7382/************************************************************************/
7386 struct player *plr,
7387 struct vision_site *pdcity,
7388 const char *citystr)
7389{
7390 const char *str;
7391 int i, id, size;
7392 citizens city_size;
7393 int nat_x, nat_y;
7394 const char *stylename;
7395 enum capital_type cap;
7396 const char *vname;
7397
7399 citystr),
7400 FALSE, "%s", secfile_error());
7402 citystr),
7403 FALSE, "%s", secfile_error());
7404 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7405 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7406 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7407
7408 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7409 citystr),
7410 FALSE, "%s", secfile_error());
7411 pdcity->owner = player_by_number(id);
7412 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7413 "%s has invalid owner (%d); skipping.", citystr, id);
7414
7415 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7416 citystr),
7417 FALSE, "%s", secfile_error());
7418 if (id >= 0) {
7419 pdcity->original = player_by_number(id);
7420 sg_warn_ret_val(NULL != pdcity->original, FALSE,
7421 "%s has invalid original owner (%d); skipping.", citystr, id);
7422 } else {
7423 pdcity->original = nullptr;
7424 }
7425
7427 "%s.id", citystr),
7428 FALSE, "%s", secfile_error());
7430 "%s has invalid id (%d); skipping.", citystr, id);
7431
7433 "%s.size", citystr),
7434 FALSE, "%s", secfile_error());
7435 city_size = (citizens)size; /* set the correct type */
7436 sg_warn_ret_val(size == (int)city_size, FALSE,
7437 "Invalid city size: %d; set to %d.", size, city_size);
7438 vision_site_size_set(pdcity, city_size);
7439
7440 /* Initialise list of improvements */
7441 BV_CLR_ALL(pdcity->improvements);
7442 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7444 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7445 "Invalid length of '%s.improvements' ("
7446 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7447 citystr, strlen(str), loading->improvement.size);
7448 for (i = 0; i < loading->improvement.size; i++) {
7449 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7450 "Undefined value '%c' within '%s.improvements'.",
7451 str[i], citystr)
7452
7453 if (str[i] == '1') {
7454 struct impr_type *pimprove =
7455 improvement_by_rule_name(loading->improvement.order[i]);
7456 if (pimprove) {
7457 BV_SET(pdcity->improvements, improvement_index(pimprove));
7458 }
7459 }
7460 }
7461
7463 "%s.name", citystr);
7464
7465 if (vname != NULL) {
7466 pdcity->name = fc_strdup(vname);
7467 }
7468
7470 "%s.occupied", citystr);
7472 "%s.walls", citystr);
7474 "%s.happy", citystr);
7476 "%s.unhappy", citystr);
7478 "%s.style", citystr);
7479 if (stylename != NULL) {
7481 } else {
7482 pdcity->style = 0;
7483 }
7484 if (pdcity->style < 0) {
7485 pdcity->style = 0;
7486 }
7487
7488 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7489 "%s.city_image", citystr);
7490
7492 "%s.capital", citystr),
7494
7496 pdcity->capital = cap;
7497 } else {
7498 pdcity->capital = CAPITAL_NOT;
7499 }
7500
7501 return TRUE;
7502}
7503
7504/************************************************************************/
7508 struct player *plr)
7509{
7510 int i, plrno = player_number(plr);
7511
7512 /* Check status and return if not OK (sg_success FALSE). */
7513 sg_check_ret();
7514
7516 /* The player can see all, there's no reason to save the private map. */
7517 return;
7518 }
7519
7520 /* Save the map (terrain). */
7521 SAVE_MAP_CHAR(ptile,
7523 saving->file, "player%d.map_t%04d", plrno);
7524
7526 /* Save the map (borders). */
7527 int x, y;
7528
7529 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7531
7532 line[0] = '\0';
7533 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7534 char token[TOKEN_SIZE];
7535 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7536 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7537
7538 if (plrtile == NULL || plrtile->owner == NULL) {
7539 strcpy(token, "-");
7540 } else {
7541 fc_snprintf(token, sizeof(token), "%d",
7542 player_number(plrtile->owner));
7543 }
7544 strcat(line, token);
7545 if (x < MAP_NATIVE_WIDTH) {
7546 strcat(line, ",");
7547 }
7548 }
7549 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7550 plrno, y);
7551 }
7552
7553 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7555
7556 line[0] = '\0';
7557 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7558 char token[TOKEN_SIZE];
7559 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7560 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7561
7562 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7563 strcpy(token, "-");
7564 } else {
7565 fc_snprintf(token, sizeof(token), "%d",
7566 player_number(plrtile->extras_owner));
7567 }
7568 strcat(line, token);
7569 if (x < MAP_NATIVE_WIDTH) {
7570 strcat(line, ",");
7571 }
7572 }
7573 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7574 plrno, y);
7575 }
7576 }
7577
7578 /* Save the map (extras). */
7580 int mod[4];
7581 int l;
7582
7583 for (l = 0; l < 4; l++) {
7584 if (4 * j + 1 > game.control.num_extra_types) {
7585 mod[l] = -1;
7586 } else {
7587 mod[l] = 4 * j + l;
7588 }
7589 }
7590
7591 SAVE_MAP_CHAR(ptile,
7593 map_get_player_tile(ptile, plr)->resource,
7594 mod),
7595 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7597
7598 /* Save the map (update time). */
7599 for (i = 0; i < 4; i++) {
7600 /* put 4-bit segments of 16-bit "updated" field */
7601 SAVE_MAP_CHAR(ptile,
7603 map_get_player_tile(ptile, plr)->last_updated, i),
7604 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7605 }
7606
7607 /* Save known cities. */
7608 i = 0;
7609 whole_map_iterate(&(wld.map), ptile) {
7610 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7611 char impr_buf[B_LAST + 1];
7612 char buf[32];
7613
7614 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7615
7616 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7617 int nat_x, nat_y;
7618
7620 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7621 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7622
7623 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7625 "%s.owner", buf);
7626 if (pdcity->original != nullptr) {
7628 "%s.original", buf);
7629 } else {
7630 secfile_insert_int(saving->file, -1, "%s.original", buf);
7631 }
7632
7634 "%s.size", buf);
7635 secfile_insert_bool(saving->file, pdcity->occupied,
7636 "%s.occupied", buf);
7637 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7638 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7639 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7641 "%s.style", buf);
7642 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7644 "%s.capital", buf);
7645
7646 /* Save improvement list as bitvector. Note that improvement order
7647 * is saved in savefile.improvement.order. */
7648 improvement_iterate(pimprove) {
7649 impr_buf[improvement_index(pimprove)]
7650 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7651 ? '1' : '0';
7653 impr_buf[improvement_count()] = '\0';
7655 "Invalid size of the improvement vector (%s.improvements: "
7656 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7657 buf, strlen(impr_buf), sizeof(impr_buf));
7658 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7659 if (pdcity->name != NULL) {
7660 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7661 }
7662
7663 i++;
7664 }
7666
7667 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7668}
7669
7670/* =======================================================================
7671 * Load / save the researches.
7672 * ======================================================================= */
7673
7674/************************************************************************/
7678{
7679 struct research *presearch;
7680 int count;
7681 int number;
7682 const char *str;
7683 int i, j;
7684 int *vlist_research;
7685
7687 /* Check status and return if not OK (sg_success FALSE). */
7688 sg_check_ret();
7689
7690 /* Initialize all researches. */
7694
7695 /* May be unsaved (e.g. scenario case). */
7696 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7697 for (i = 0; i < count; i++) {
7699 "research.r%d.number", i),
7700 "%s", secfile_error());
7701 presearch = research_by_number(number);
7703 "Invalid research number %d in 'research.r%d.number'",
7704 number, i);
7705
7706 presearch->tech_goal = technology_load(loading->file,
7707 "research.r%d.goal", i);
7709 &presearch->future_tech,
7710 "research.r%d.futuretech", i),
7711 "%s", secfile_error());
7713 &presearch->bulbs_researched,
7714 "research.r%d.bulbs", i),
7715 "%s", secfile_error());
7717 &presearch->bulbs_researching_saved,
7718 "research.r%d.bulbs_before", i),
7719 "%s", secfile_error());
7720 presearch->researching_saved = technology_load(loading->file,
7721 "research.r%d.saved", i);
7722 presearch->researching = technology_load(loading->file,
7723 "research.r%d.now", i);
7725 &presearch->free_bulbs,
7726 "research.r%d.free_bulbs", i),
7727 "%s", secfile_error());
7728
7729 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7730 sg_failure_ret(str != NULL, "%s", secfile_error());
7731 sg_failure_ret(strlen(str) == loading->technology.size,
7732 "Invalid length of 'research.r%d.done' ("
7733 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7734 i, strlen(str), loading->technology.size);
7735 for (j = 0; j < loading->technology.size; j++) {
7736 sg_failure_ret(str[j] == '1' || str[j] == '0',
7737 "Undefined value '%c' within 'research.r%d.done'.",
7738 str[j], i);
7739
7740 if (str[j] == '1') {
7741 struct advance *padvance
7742 = advance_by_rule_name(loading->technology.order[j]);
7743
7744 if (padvance) {
7746 TECH_KNOWN);
7747 }
7748 }
7749 }
7750
7752 size_t count_res;
7753 int tn;
7754
7756 "research.r%d.vbs", i);
7757
7758 for (tn = 0; tn < count_res; tn++) {
7759 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7760
7761 if (padvance != NULL) {
7762 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7763 = vlist_research[tn];
7764 }
7765 }
7766 }
7767 }
7768
7769 /* In case of tech_leakage, we can update research only after all the
7770 * researches have been loaded */
7774}
7775
7776/************************************************************************/
7780{
7781 char invs[A_LAST];
7782 int i = 0;
7783 int *vlist_research;
7784
7786 /* Check status and return if not OK (sg_success FALSE). */
7787 sg_check_ret();
7788
7789 if (saving->save_players) {
7792 "research.r%d.number", i);
7793 technology_save(saving->file, "research.r%d.goal",
7794 i, presearch->tech_goal);
7795 secfile_insert_int(saving->file, presearch->future_tech,
7796 "research.r%d.futuretech", i);
7797 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7798 "research.r%d.bulbs_before", i);
7802 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7806 "research.r%d.vbs", i);
7807 if (vlist_research) {
7809 }
7810 }
7811 technology_save(saving->file, "research.r%d.saved",
7812 i, presearch->researching_saved);
7813 secfile_insert_int(saving->file, presearch->bulbs_researched,
7814 "research.r%d.bulbs", i);
7815 technology_save(saving->file, "research.r%d.now",
7816 i, presearch->researching);
7817 secfile_insert_int(saving->file, presearch->free_bulbs,
7818 "research.r%d.free_bulbs", i);
7819 /* Save technology lists as bytevector. Note that technology order is
7820 * saved in savefile.technology.order */
7821 advance_index_iterate(A_NONE, tech_id) {
7822 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7824 == TECH_KNOWN ? '1' : '0');
7827 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7828 i++;
7830 secfile_insert_int(saving->file, i, "research.count");
7831 }
7832}
7833
7834/* =======================================================================
7835 * Load / save the event cache. Should be the last thing to do.
7836 * ======================================================================= */
7837
7838/************************************************************************/
7842{
7843 /* Check status and return if not OK (sg_success FALSE). */
7844 sg_check_ret();
7845
7846 event_cache_load(loading->file, "event_cache");
7847}
7848
7849/************************************************************************/
7853{
7854 /* Check status and return if not OK (sg_success FALSE). */
7855 sg_check_ret();
7856
7857 if (saving->scenario) {
7858 /* Do _not_ save events in a scenario. */
7859 return;
7860 }
7861
7862 event_cache_save(saving->file, "event_cache");
7863}
7864
7865/* =======================================================================
7866 * Load / save the open treaties
7867 * ======================================================================= */
7868
7869/************************************************************************/
7873{
7874 int tidx;
7875 const char *plr0;
7876
7877 /* Check status and return if not OK (sg_success FALSE). */
7878 sg_check_ret();
7879
7880 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7881 "treaty%d.plr0", tidx)) != NULL ;
7882 tidx++) {
7883 const char *plr1;
7884 const char *ct;
7885 int cidx;
7886 struct player *p0, *p1;
7887
7888 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7889
7890 p0 = player_by_name(plr0);
7891 p1 = player_by_name(plr1);
7892
7893 if (p0 == NULL || p1 == NULL) {
7894 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7895 } else {
7896 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7897
7900
7901 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7902 "treaty%d.clause%d.type",
7903 tidx, cidx)) != NULL ;
7904 cidx++ ) {
7906 const char *plrx;
7907
7908 if (!clause_type_is_valid(type)) {
7909 log_error("Invalid clause type \"%s\"", ct);
7910 } else {
7911 struct player *pgiver = NULL;
7912
7913 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7914 tidx, cidx);
7915
7916 if (!fc_strcasecmp(plrx, plr0)) {
7917 pgiver = p0;
7918 } else if (!fc_strcasecmp(plrx, plr1)) {
7919 pgiver = p1;
7920 } else {
7921 log_error("Clause giver %s is not participant of the treaty"
7922 "between %s and %s", plrx, plr0, plr1);
7923 }
7924
7925 if (pgiver != NULL) {
7926 int value;
7927
7928 value = secfile_lookup_int_default(loading->file, 0,
7929 "treaty%d.clause%d.value",
7930 tidx, cidx);
7931
7932 add_clause(ptreaty, pgiver, type, value, NULL);
7933 }
7934 }
7935 }
7936
7937 /* These must be after clauses have been added so that acceptance
7938 * does not get cleared by what seems like changes to the treaty. */
7940 "treaty%d.accept0", tidx);
7942 "treaty%d.accept1", tidx);
7943 }
7944 }
7945}
7946
7947typedef struct {
7948 int tidx;
7951
7952/************************************************************************/
7955static void treaty_save(struct treaty *ptr, void *data_in)
7956{
7957 char tpath[512];
7958 int cidx = 0;
7960
7961 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7962
7963 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7964 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7965 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7966 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7967
7969 char cpath[512];
7970
7971 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7972
7973 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7974 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7975 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7977}
7978
7979/************************************************************************/
7983{
7984 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7985
7987}
7988
7989/* =======================================================================
7990 * Load / save the history report
7991 * ======================================================================= */
7992
7993/************************************************************************/
7997{
7999 int turn;
8000
8001 /* Check status and return if not OK (sg_success FALSE). */
8002 sg_check_ret();
8003
8004 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
8005
8006 if (turn != -2) {
8007 hist->turn = turn;
8008 }
8009
8010 if (turn + 1 >= game.info.turn) {
8011 const char *str;
8012
8013 str = secfile_lookup_str(loading->file, "history.title");
8014 sg_failure_ret(str != NULL, "%s", secfile_error());
8015 sz_strlcpy(hist->title, str);
8016 str = secfile_lookup_str(loading->file, "history.body");
8017 sg_failure_ret(str != NULL, "%s", secfile_error());
8018 sz_strlcpy(hist->body, str);
8019 }
8020}
8021
8022/************************************************************************/
8025static void sg_save_history(struct savedata *saving)
8026{
8028
8029 secfile_insert_int(saving->file, hist->turn, "history.turn");
8030
8031 if (hist->turn + 1 >= game.info.turn) {
8032 secfile_insert_str(saving->file, hist->title, "history.title");
8033 secfile_insert_str(saving->file, hist->body, "history.body");
8034 }
8035}
8036
8037/* =======================================================================
8038 * Load / save the mapimg definitions.
8039 * ======================================================================= */
8040
8041/************************************************************************/
8044static void sg_load_mapimg(struct loaddata *loading)
8045{
8046 int mapdef_count, i;
8047
8048 /* Check status and return if not OK (sg_success FALSE). */
8049 sg_check_ret();
8050
8051 /* Clear all defined map images. */
8052 while (mapimg_count() > 0) {
8053 mapimg_delete(0);
8054 }
8055
8057 "mapimg.count");
8058 log_verbose("Saved map image definitions: %d.", mapdef_count);
8059
8060 if (0 >= mapdef_count) {
8061 return;
8062 }
8063
8064 for (i = 0; i < mapdef_count; i++) {
8065 const char *p;
8066
8067 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
8068 if (NULL == p) {
8069 log_verbose("[Mapimg %4d] Missing definition.", i);
8070 continue;
8071 }
8072
8073 if (!mapimg_define(p, FALSE)) {
8074 log_error("Invalid map image definition %4d: %s.", i, p);
8075 }
8076
8077 log_verbose("Mapimg %4d loaded.", i);
8078 }
8079}
8080
8081/************************************************************************/
8084static void sg_save_mapimg(struct savedata *saving)
8085{
8086 /* Check status and return if not OK (sg_success FALSE). */
8087 sg_check_ret();
8088
8089 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8090 if (mapimg_count() > 0) {
8091 int i;
8092
8093 for (i = 0; i < mapimg_count(); i++) {
8094 char buf[MAX_LEN_MAPDEF];
8095
8096 mapimg_id2str(i, buf, sizeof(buf));
8097 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8098 }
8099 }
8100}
8101
8102/* =======================================================================
8103 * Sanity checks for loading / saving a game.
8104 * ======================================================================= */
8105
8106/************************************************************************/
8110{
8111 int players;
8112
8113 /* Check status and return if not OK (sg_success FALSE). */
8114 sg_check_ret();
8115
8116 if (game.info.is_new_game) {
8117 /* Nothing to do for new games (or not started scenarios). */
8118 return;
8119 }
8120
8121 /* Old savegames may have maxplayers lower than current player count,
8122 * fix. */
8123 players = normal_player_count();
8124 if (game.server.max_players < players) {
8125 log_verbose("Max players lower than current players, fixing");
8126 game.server.max_players = players;
8127 }
8128
8129 /* Fix ferrying sanity */
8130 players_iterate(pplayer) {
8131 unit_list_iterate_safe(pplayer->units, punit) {
8134 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8140 }
8143
8144 /* Fix stacking issues. We don't rely on the savegame preserving
8145 * alliance invariants (old savegames often did not) so if there are any
8146 * unallied units on the same tile we just bounce them. */
8147 players_iterate(pplayer) {
8149 resolve_unit_stacks(pplayer, aplayer, TRUE);
8152
8153 /* Recalculate the potential buildings for each city. Has caused some
8154 * problems with game random state.
8155 * This also changes the game state if you save the game directly after
8156 * loading it and compare the results. */
8157 players_iterate(pplayer) {
8158 /* Building advisor needs data phase open in order to work */
8159 adv_data_phase_init(pplayer, FALSE);
8160 building_advisor(pplayer);
8161 /* Close data phase again so it can be opened again when game starts. */
8162 adv_data_phase_done(pplayer);
8164
8165 /* Prevent a buggy or intentionally crafted save game from crashing
8166 * Freeciv. See hrm Bug #887748 */
8167 players_iterate(pplayer) {
8168 city_list_iterate(pplayer->cities, pcity) {
8169 worker_task_list_iterate(pcity->task_reqs, ptask) {
8170 if (!worker_task_is_sane(ptask)) {
8171 log_error("[city id: %d] Bad worker task %d.",
8172 pcity->id, ptask->act);
8173 worker_task_list_remove(pcity->task_reqs, ptask);
8174 free(ptask);
8175 ptask = NULL;
8176 }
8180
8181 /* Check worked tiles map */
8182#ifdef FREECIV_DEBUG
8183 if (loading->worked_tiles != NULL) {
8184 /* check the entire map for unused worked tiles */
8185 whole_map_iterate(&(wld.map), ptile) {
8186 if (loading->worked_tiles[ptile->index] != -1) {
8187 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8188 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8189 }
8191 }
8192#endif /* FREECIV_DEBUG */
8193
8194 /* Check researching technologies and goals. */
8196 if (presearch->researching != A_UNSET
8197 && !is_future_tech(presearch->researching)
8198 && (valid_advance_by_number(presearch->researching) == NULL
8200 != TECH_PREREQS_KNOWN))) {
8201 log_sg(_("%s had invalid researching technology."),
8203 presearch->researching = A_UNSET;
8204 }
8205 if (presearch->tech_goal != A_UNSET
8206 && !is_future_tech(presearch->tech_goal)
8207 && (valid_advance_by_number(presearch->tech_goal) == NULL
8210 == TECH_KNOWN))) {
8211 log_sg(_("%s had invalid technology goal."),
8213 presearch->tech_goal = A_UNSET;
8214 }
8215
8218
8219 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8220 players_iterate(pplayer) {
8221 int unique_count[U_LAST];
8222
8223 memset(unique_count, 0, sizeof(unique_count));
8224
8225 unit_list_iterate(pplayer->units, punit) {
8228
8231 log_sg(_("%s has multiple units of type %s though it should be possible "
8232 "to have only one."),
8234 }
8237
8238 players_iterate(pplayer) {
8239 unit_list_iterate_safe(pplayer->units, punit) {
8240 if (punit->has_orders
8242 punit->orders.list)) {
8243 log_sg("Invalid unit orders for unit %d.", punit->id);
8245 }
8248
8249 /* Check max rates (rules may have changed since saving) */
8250 players_iterate(pplayer) {
8253
8254 if (0 == strlen(server.game_identifier)
8255 || !is_base64url(server.game_identifier)) {
8256 /* This uses fc_rand(), so random state has to be initialized before. */
8257 randomize_base64url_string(server.game_identifier,
8258 sizeof(server.game_identifier));
8259 }
8260
8261 /* Restore game random state, just in case various initialization code
8262 * inexplicably altered the previously existing state. */
8263 if (!game.info.is_new_game) {
8264 fc_rand_set_state(loading->rstate);
8265 }
8266
8267 /* At the end do the default sanity checks. */
8268 sanity_check();
8269}
8270
8271/************************************************************************/
8275{
8276 /* Check status and return if not OK (sg_success FALSE). */
8277 sg_check_ret();
8278}
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:1271
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1260
bool action_id_exists(const action_id act_id)
Definition actions.c:1089
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:421
#define NUM_ACTIONS
Definition actions.h:63
#define action_id_get_activity(act_id)
Definition actions.h:466
#define ACTION_NONE
Definition actions.h:59
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
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:3470
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:3397
void destroy_city_virtual(struct city *pcity)
Definition city.c:3556
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:517
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define cities_iterate(pcity)
Definition city.h:512
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:84
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define output_type_iterate(output)
Definition city.h:846
#define FREE_WORKED_TILES
Definition city.h:883
#define MAX_CITY_SIZE
Definition city.h:104
#define city_list_iterate_end
Definition city.h:510
#define I_NEVER
Definition city.h:245
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:228
#define city_tile_iterate_end
Definition city.h:236
#define output_type_iterate_end
Definition city.h:852
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2781
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:2852
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3454
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:367
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:852
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
char * incite_cost
Definition comments.c:77
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:160
#define NO_TARGET
Definition fc_types.h:215
int Tech_type_id
Definition fc_types.h:238
unsigned char citizens
Definition fc_types.h:249
int Specialist_type_id
Definition fc_types.h:236
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:128
#define MAX_LEN_NAME
Definition fc_types.h:68
@ O_LAST
Definition fc_types.h:103
int Multiplier_type_id
Definition fc_types.h:247
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:94
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
void initialize_globals(void)
Definition game.c:691
struct city * game_city_by_number(int id)
Definition game.c:107
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:603
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:602
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:605
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:604
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:607
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:622
struct government * government_of_player(const struct player *pplayer)
Definition government.c:116
const char * government_rule_name(const struct government *pgovern)
Definition government.c:135
struct government * government_by_rule_name(const char *name)
Definition government.c:57
#define governments_iterate(NAME_pgov)
Definition government.h:127
#define governments_iterate_end
Definition government.h:130
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c: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:1312
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1205
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:350
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:443
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:133
char * lines
Definition packhand.c:132
int len
Definition packhand.c:128
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:441
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1217
struct player * player_by_number(const int player_id)
Definition player.c:837
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1468
int player_count(void)
Definition player.c:806
int player_slot_count(void)
Definition player.c:415
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:454
int player_number(const struct player *pplayer)
Definition player.c:826
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:164
const char * player_name(const struct player *pplayer)
Definition player.c:885
int player_slot_max_used_number(void)
Definition player.c:467
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
struct player * player_by_name(const char *name)
Definition player.c:871
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:245
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1191
int player_index(const struct player *pplayer)
Definition player.c:818
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:849
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:325
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1485
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1477
#define players_iterate_end
Definition player.h:552
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:547
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:570
static bool is_barbarian(const struct player *pplayer)
Definition player.h:499
#define player_slots_iterate(_pslot)
Definition player.h:538
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:572
#define players_iterate_alive_end
Definition player.h:562
#define player_slots_iterate_end
Definition player.h:542
#define players_iterate_alive(_pplayer)
Definition player.h:557
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:671
const char * research_name_translation(const struct research *presearch)
Definition research.c:158
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:640
struct research * research_by_number(int number)
Definition research.c:119
int research_number(const struct research *presearch)
Definition research.c:109
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1357
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
void research_update(struct research *presearch)
Definition research.c:504
#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:9437
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:233
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:243
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:154
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:255
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:205
#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:8025
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:2754
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3020
static void unit_ordering_apply(void)
Definition savegame3.c:1079
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3712
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:3592
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3251
bool sg_success
Definition savecompat.c:35
#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:2813
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:3083
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3553
#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:7955
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5678
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5630
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:2919
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:6156
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:1335
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:2663
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6087
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1250
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2434
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3196
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7677
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3509
#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:2040
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2393
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1774
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6701
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7996
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7982
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3373
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7779
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:2472
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2498
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2087
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:7872
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2586
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:6754
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2242
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:1262
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7507
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:8274
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:8044
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7020
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7100
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2063
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2874
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7183
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2959
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:8084
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:7385
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2701
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3109
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:2987
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1298
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7852
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3051
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8109
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7841
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:2262
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:2483
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2679
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3649
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:4958
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4870
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:123
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:90
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
Specialist_type_id specialist_count(void)
Definition specialist.c:71
bool is_normal_specialist_id(Specialist_type_id sp)
Definition specialist.c:196
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
#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:3501
const char * aifill(int amount)
Definition srv_main.c:2509
bool game_was_started(void)
Definition srv_main.c:355
void identity_number_reserve(int id)
Definition srv_main.c:2036
struct server_arguments srvarg
Definition srv_main.c:182
void init_game_seed(void)
Definition srv_main.c:209
void update_nations_with_startpos(void)
Definition srv_main.c:2314
enum server_states server_state(void)
Definition srv_main.c:339
void server_game_free(void)
Definition srv_main.c:3525
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:318
size_t length
Definition city.h:415
bool multiresearch
Definition game.h:170
bool last_updated_year
Definition game.h:243
int world_peace_start
Definition game.h:245
float turn_change_time
Definition game.h:225
bool vision_reveal_tiles
Definition game.h:207
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:269
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:241
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:214
char rulesetdir[MAX_LEN_NAME]
Definition game.h:246
int additional_phase_seconds
Definition game.h:219
struct section_file * luadata
Definition game.h:254
int scoreturn
Definition game.h:232
randseed seed
Definition game.h:234
int dbid
Definition game.h:255
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:210
struct timer * phase_timer
Definition game.h:218
unsigned revealmap
Definition game.h:184
char orig_game_version[MAX_LEN_NAME]
Definition game.h:228
bool save_known
Definition game.h:266
bool foggedborders
Definition game.h:154
struct civ_game::@32::@36::@39 save_options
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:212
struct civ_game::@32::@36 server
int timeoutinc
Definition game.h:211
int phase_mode_stored
Definition game.h:223
int max_players
Definition game.h:163
bool save_starts
Definition game.h:268
int timeoutintinc
Definition game.h:213
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::@44::@46 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:66
struct section_file * file
Definition savecompat.h:48
bool global_advances[A_LAST]
int great_wonder_owners[B_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char alt_dir[MAX_LEN_NAME]
char version[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char authors[MAX_LEN_PACKET/3]
char datafile[MAX_LEN_NAME]
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
int primary_capital_id
Definition player.h:275
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::@73::@75 server
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
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:7949
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
int battlegroup
Definition unit.h:194
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
struct unit::@83 orders
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 unit::@84::@87 server
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:468
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:457
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c: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:188
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:127
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:257
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:273
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1098
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:350
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:107
#define tile_index(_pt_)
Definition tile.h:89
#define tile_worked(_tile)
Definition tile.h:119
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#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:1833
int unit_upkeep_cost(const struct unit *punit, Output_type_id otype)
Definition unit.c:2994
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2474
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1301
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2545
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:884
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1688
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2753
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:1159
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1793
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1311
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1141
#define unit_tile(_pu)
Definition unit.h:407
#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:406
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:1406
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5016
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1230
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1063
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1793
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2657
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:93
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define unit_type_iterate(_p)
Definition unittype.h:863
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:870
const char * freeciv_datafile_version(void)
Definition version.c:186
#define MINOR_VERSION
Definition version_gen.h:7
#define EMERGENCY_VERSION
Definition version_gen.h:9
#define MAJOR_VERSION
Definition version_gen.h:6
#define PATCH_VERSION
Definition version_gen.h:8
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:128
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT