Freeciv-3.3
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/************************************************************************/
1264 const char *path, int plrno)
1265{
1266 char path_with_name[128];
1267 const char *name;
1268 struct advance *padvance;
1269
1271 "%s_name", path);
1272
1274
1275 if (!name || name[0] == '\0') {
1276 /* Used by researching_saved */
1277 return A_UNKNOWN;
1278 }
1279 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1280 return A_FUTURE;
1281 }
1282 if (fc_strcasecmp(name, "A_NONE") == 0) {
1283 return A_NONE;
1284 }
1285 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1286 return A_UNSET;
1287 }
1288
1291 "%s: unknown technology \"%s\".", path_with_name, name);
1292
1293 return advance_number(padvance);
1294}
1295
1296/************************************************************************/
1299static void technology_save(struct section_file *file,
1300 const char *path, int plrno, Tech_type_id tech)
1301{
1302 char path_with_name[128];
1303 const char *name;
1304
1306 "%s_name", path);
1307
1308 switch (tech) {
1309 case A_UNKNOWN: /* Used by researching_saved */
1310 name = "";
1311 break;
1312 case A_NONE:
1313 name = "A_NONE";
1314 break;
1315 case A_UNSET:
1316 name = "A_UNSET";
1317 break;
1318 case A_FUTURE:
1319 name = "A_FUTURE";
1320 break;
1321 default:
1323 break;
1324 }
1325
1327}
1328
1329/* =======================================================================
1330 * Load / save savefile data.
1331 * ======================================================================= */
1332
1333/************************************************************************/
1337{
1338 int i;
1339 const char *terr_name;
1340 bool ruleset_datafile;
1342 const char *str;
1343
1344 /* Check status and return if not OK (sg_success FALSE). */
1345 sg_check_ret();
1346
1347 /* Load savefile options. */
1348 loading->secfile_options
1349 = secfile_lookup_str(loading->file, "savefile.options");
1350
1351 /* We don't need these entries, but read them anyway to avoid
1352 * warnings about unread secfile entries. */
1353 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1354 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1355
1356 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1358
1359 if (game.scenario.datafile[0] != '\0') {
1361 } else {
1363 }
1364
1367 const char *req_caps;
1368
1371 /* Failed to load correct ruleset */
1372 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1374 }
1375
1376 req_caps = secfile_lookup_str_default(loading->file, "",
1377 "scenario.ruleset_caps");
1378 strncpy(game.scenario.req_caps, req_caps,
1379 sizeof(game.scenario.req_caps) - 1);
1380 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1381
1382 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1383 /* Current ruleset lacks required capabilities. */
1384 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1385 log_normal(_("Ruleset has capabilities: %s"),
1387 /* TRANS: ... ruleset dir ... scenario name ... */
1388 log_error(_("Current ruleset %s not compatible with the scenario %s."
1389 " Trying to switch to the ruleset specified by the"
1390 " scenario."),
1392
1394 }
1395 }
1396
1399 const char *ruleset, *alt_dir;
1400
1403 "savefile.rulesetdir");
1404
1405 /* Load ruleset. */
1407 if (!strcmp("default", game.server.rulesetdir)) {
1408 /* Here 'default' really means current default.
1409 * Saving happens with real ruleset name, so savegames containing this
1410 * are special scenarios. */
1412 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1414 }
1415
1416 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1417 "savefile.ruleset_alt_dir");
1418
1419 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1420 if (alt_dir) {
1422 _("Failed to load either of rulesets '%s' or '%s' "
1423 "needed for savegame."),
1424 ruleset, alt_dir);
1425 } else {
1427 _("Failed to load ruleset '%s' needed for savegame."),
1428 ruleset);
1429 }
1430 }
1431
1433 /* TRANS: ruleset dir */
1434 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1435 }
1436 }
1437
1438 /* Remove all aifill players. Correct number of them get created later
1439 * with correct skill level etc. */
1440 (void) aifill(0);
1441
1442 /* Time to load scenario specific luadata */
1443 if (game.scenario.datafile[0] != '\0') {
1444 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1446 } else {
1447 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1448 const struct strvec **path;
1449 const char *found = NULL;
1450 char testfile[MAX_LEN_PATH];
1451 struct section_file *secfile;
1452
1453 for (path = paths; found == NULL && *path != NULL; path++) {
1454 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1455
1456 found = fileinfoname(*path, testfile);
1457 }
1458
1459 if (found == NULL) {
1460 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1461 sg_success = FALSE;
1462 return;
1463 }
1464
1465 secfile = secfile_load(found, FALSE);
1466 if (secfile == NULL) {
1467 log_error(_("Failed to load scenario luadata file %s.luadata"),
1469 sg_success = FALSE;
1470 return;
1471 }
1472
1473 game.server.luadata = secfile;
1474 }
1475 }
1476
1478 "savefile.dbid");
1479
1480 /* This is in the savegame only if the game has been started before savegame3.c time,
1481 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1483 "savefile.last_updated_as_year");
1484
1485 /* Load improvements. */
1486 loading->improvement.size
1488 "savefile.improvement_size");
1489 if (loading->improvement.size) {
1490 loading->improvement.order
1491 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1492 "savefile.improvement_vector");
1493 sg_failure_ret(loading->improvement.size != 0,
1494 "Failed to load improvement order: %s",
1495 secfile_error());
1496 }
1497
1498 /* Load technologies. */
1499 loading->technology.size
1501 "savefile.technology_size");
1502 if (loading->technology.size) {
1503 loading->technology.order
1504 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1505 "savefile.technology_vector");
1506 sg_failure_ret(loading->technology.size != 0,
1507 "Failed to load technology order: %s",
1508 secfile_error());
1509 }
1510
1511 /* Load Activities. */
1512 loading->activities.size
1514 "savefile.activities_size");
1515 if (loading->activities.size) {
1516 loading->activities.order
1517 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1518 "savefile.activities_vector");
1519 sg_failure_ret(loading->activities.size != 0,
1520 "Failed to load activity order: %s",
1521 secfile_error());
1522 }
1523
1524 /* Load traits. */
1525 loading->trait.size
1527 "savefile.trait_size");
1528 if (loading->trait.size) {
1529 loading->trait.order
1530 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1531 "savefile.trait_vector");
1532 sg_failure_ret(loading->trait.size != 0,
1533 "Failed to load trait order: %s",
1534 secfile_error());
1535 }
1536
1537 /* Load extras. */
1538 loading->extra.size
1540 "savefile.extras_size");
1541 if (loading->extra.size) {
1542 const char **modname;
1543 size_t nmod;
1544 int j;
1545
1546 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1547 "savefile.extras_vector");
1548 sg_failure_ret(loading->extra.size != 0,
1549 "Failed to load extras order: %s",
1550 secfile_error());
1552 "Number of extras defined by the ruleset (= %d) are "
1553 "lower than the number in the savefile (= %d).",
1554 game.control.num_extra_types, (int)loading->extra.size);
1555 /* make sure that the size of the array is divisible by 4 */
1556 nmod = 4 * ((loading->extra.size + 3) / 4);
1557 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1558 for (j = 0; j < loading->extra.size; j++) {
1559 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1560 }
1561 free(modname);
1562 for (; j < nmod; j++) {
1563 loading->extra.order[j] = NULL;
1564 }
1565 }
1566
1567 /* Load multipliers. */
1568 loading->multiplier.size
1570 "savefile.multipliers_size");
1571 if (loading->multiplier.size) {
1572 const char **modname;
1573 int j;
1574
1575 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1576 "savefile.multipliers_vector");
1577 sg_failure_ret(loading->multiplier.size != 0,
1578 "Failed to load multipliers order: %s",
1579 secfile_error());
1580 /* It's OK for the set of multipliers in the savefile to differ
1581 * from those in the ruleset. */
1582 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1583 sizeof(*loading->multiplier.order));
1584 for (j = 0; j < loading->multiplier.size; j++) {
1585 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1586 if (!loading->multiplier.order[j]) {
1587 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1588 "discarding", modname[j]);
1589 }
1590 }
1591 free(modname);
1592 }
1593
1594 /* Load specialists. */
1595 loading->specialist.size
1597 "savefile.specialists_size");
1598 if (loading->specialist.size) {
1599 const char **modname;
1600 size_t nmod;
1601 int j;
1602
1603 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1604 "savefile.specialists_vector");
1605 sg_failure_ret(loading->specialist.size != 0,
1606 "Failed to load specialists order: %s",
1607 secfile_error());
1609 "Number of specialists defined by the ruleset (= %d) are "
1610 "lower than the number in the savefile (= %d).",
1611 game.control.num_specialist_types, (int)loading->specialist.size);
1612 /* make sure that the size of the array is divisible by 4 */
1613 /* That's not really needed with specialists at the moment, but done this way
1614 * for consistency with other types, and to be prepared for the time it needs
1615 * to be this way. */
1616 nmod = 4 * ((loading->specialist.size + 3) / 4);
1617 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1618 for (j = 0; j < loading->specialist.size; j++) {
1619 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1620 }
1621 free(modname);
1622 for (; j < nmod; j++) {
1623 loading->specialist.order[j] = NULL;
1624 }
1625 }
1626
1627 /* Load action order. */
1628 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1629 "savefile.action_size");
1630
1631 sg_failure_ret(loading->action.size > 0,
1632 "Failed to load action order: %s",
1633 secfile_error());
1634
1635 if (loading->action.size) {
1636 const char **modname;
1637 int j;
1638
1639 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1640 "savefile.action_vector");
1641
1642 loading->action.order = fc_calloc(loading->action.size,
1643 sizeof(*loading->action.order));
1644
1645 for (j = 0; j < loading->action.size; j++) {
1647
1648 if (real_action) {
1649 loading->action.order[j] = real_action->id;
1650 } else {
1651 log_sg("Unknown action \'%s\'", modname[j]);
1652 loading->action.order[j] = ACTION_NONE;
1653 }
1654 }
1655
1656 free(modname);
1657 }
1658
1659 /* Load action decision order. */
1660 loading->act_dec.size
1662 "savefile.action_decision_size");
1663
1664 sg_failure_ret(loading->act_dec.size > 0,
1665 "Failed to load action decision order: %s",
1666 secfile_error());
1667
1668 if (loading->act_dec.size) {
1669 const char **modname;
1670 int j;
1671
1672 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1673 "savefile.action_decision_vector");
1674
1675 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1676 sizeof(*loading->act_dec.order));
1677
1678 for (j = 0; j < loading->act_dec.size; j++) {
1679 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1681 }
1682
1683 free(modname);
1684 }
1685
1686 /* Load server side agent order. */
1687 loading->ssa.size
1689 "savefile.server_side_agent_size");
1690
1691 sg_failure_ret(loading->ssa.size > 0,
1692 "Failed to load server side agent order: %s",
1693 secfile_error());
1694
1695 if (loading->ssa.size) {
1696 const char **modname;
1697 int j;
1698
1699 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1700 "savefile.server_side_agent_list");
1701
1702 loading->ssa.order = fc_calloc(loading->ssa.size,
1703 sizeof(*loading->ssa.order));
1704
1705 for (j = 0; j < loading->ssa.size; j++) {
1706 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1708 }
1709
1710 free(modname);
1711 }
1712
1713 /* Load city options order. */
1714 loading->coptions.size
1716 "savefile.city_options_size");
1717
1718 sg_failure_ret(loading->coptions.size > 0,
1719 "Failed to load city options order: %s",
1720 secfile_error());
1721
1722 if (loading->coptions.size) {
1723 const char **modname;
1724 int j;
1725
1726 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1727 "savefile.city_options_vector");
1728
1729 loading->coptions.order = fc_calloc(loading->coptions.size,
1730 sizeof(*loading->coptions.order));
1731
1732 for (j = 0; j < loading->coptions.size; j++) {
1733 loading->coptions.order[j] = city_options_by_name(modname[j],
1735 }
1736
1737 free(modname);
1738 }
1739
1740 /* Terrain identifiers */
1742 pterr->identifier_load = '\0';
1744
1745 i = 0;
1747 "savefile.terrident%d.name", i)) != NULL) {
1749
1750 if (pterr != NULL) {
1751 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1752 "savefile.terrident%d.identifier", i);
1753
1754 pterr->identifier_load = *iptr;
1755 } else {
1756 log_error("Identifier for unknown terrain type %s.", terr_name);
1757 }
1758 i++;
1759 }
1760
1763 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1764 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1765 "%s and %s share a saved identifier",
1767 }
1770}
1771
1772/************************************************************************/
1776{
1777 int i;
1778
1779 /* Check status and return if not OK (sg_success FALSE). */
1780 sg_check_ret();
1781
1782 /* Save savefile options. */
1784
1785 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1786
1787 /* Save reason of the savefile generation. */
1788 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1789
1790 /* Save as accurate freeciv revision information as possible */
1791 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1792
1793 /* Freeciv version used in the very first launch of this game -
1794 * or even saving in pregame. */
1796 "savefile.orig_version");
1797
1798 /* Save rulesetdir at this point as this ruleset is required by this
1799 * savefile. */
1800 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1801
1802 if (game.control.version[0] != '\0') {
1803 /* Current ruleset has version information, save it.
1804 * This is never loaded, but exist in savegame file only for debugging purposes. */
1805 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1806 }
1807
1808 if (game.control.alt_dir[0] != '\0') {
1809 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1810 }
1811
1813 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1814 }
1815
1816 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1817
1818 /* Save improvement order in savegame, so we are not dependent on ruleset
1819 * order. If the game isn't started improvements aren't loaded so we can
1820 * not save the order. */
1822 "savefile.improvement_size");
1823 if (improvement_count() > 0) {
1824 const char *buf[improvement_count()];
1825
1826 improvement_iterate(pimprove) {
1827 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1829
1831 "savefile.improvement_vector");
1832 }
1833
1834 /* Save technology order in savegame, so we are not dependent on ruleset
1835 * order. If the game isn't started advances aren't loaded so we can not
1836 * save the order. */
1838 "savefile.technology_size");
1839 if (game.control.num_tech_types > 0) {
1840 const char *buf[game.control.num_tech_types];
1841
1842 buf[A_NONE] = "A_NONE";
1843 advance_iterate(a) {
1847 "savefile.technology_vector");
1848 }
1849
1850 /* Save activities order in the savegame. */
1852 "savefile.activities_size");
1853 if (ACTIVITY_LAST > 0) {
1854 const char **modname;
1855 int j;
1856
1857 i = 0;
1858
1860
1861 for (j = 0; j < ACTIVITY_LAST; j++) {
1863 }
1864
1867 "savefile.activities_vector");
1868 free(modname);
1869 }
1870
1871 /* Save specialists order in the savegame. */
1873 "savefile.specialists_size");
1874 {
1875 const char **modname;
1876
1877 i = 0;
1879
1883
1885 "savefile.specialists_vector");
1886
1887 free(modname);
1888 }
1889
1890 /* Save trait order in savegame. */
1892 "savefile.trait_size");
1893 {
1894 const char **modname;
1895 enum trait tr;
1896 int j;
1897
1898 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1899
1900 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1901 modname[j] = trait_name(tr);
1902 }
1903
1905 "savefile.trait_vector");
1906 free(modname);
1907 }
1908
1909 /* Save extras order in the savegame. */
1911 "savefile.extras_size");
1912 if (game.control.num_extra_types > 0) {
1913 const char **modname;
1914
1915 i = 0;
1917
1918 extra_type_iterate(pextra) {
1919 modname[i++] = extra_rule_name(pextra);
1921
1924 "savefile.extras_vector");
1925 free(modname);
1926 }
1927
1928 /* Save multipliers order in the savegame. */
1930 "savefile.multipliers_size");
1931 if (multiplier_count() > 0) {
1932 const char **modname;
1933
1935
1936 multipliers_iterate(pmul) {
1939
1942 "savefile.multipliers_vector");
1943 free(modname);
1944 }
1945
1946 /* Save city_option order in the savegame. */
1948 "savefile.city_options_size");
1949 if (CITYO_LAST > 0) {
1950 const char **modname;
1951 int j;
1952
1953 i = 0;
1954 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1955
1956 for (j = 0; j < CITYO_LAST; j++) {
1957 modname[i++] = city_options_name(j);
1958 }
1959
1961 CITYO_LAST,
1962 "savefile.city_options_vector");
1963 free(modname);
1964 }
1965
1966 /* Save action order in the savegame. */
1968 "savefile.action_size");
1969 if (NUM_ACTIONS > 0) {
1970 const char **modname;
1971 int j;
1972
1973 i = 0;
1974 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1975
1976 for (j = 0; j < NUM_ACTIONS; j++) {
1978 }
1979
1982 "savefile.action_vector");
1983 free(modname);
1984 }
1985
1986 /* Save action decision order in the savegame. */
1988 "savefile.action_decision_size");
1989 if (ACT_DEC_COUNT > 0) {
1990 const char **modname;
1991 int j;
1992
1993 i = 0;
1995
1996 for (j = 0; j < ACT_DEC_COUNT; j++) {
1998 }
1999
2002 "savefile.action_decision_vector");
2003 free(modname);
2004 }
2005
2006 /* Save server side agent order in the savegame. */
2008 "savefile.server_side_agent_size");
2009 if (SSA_COUNT > 0) {
2010 const char **modname;
2011 int j;
2012
2013 i = 0;
2014 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2015
2016 for (j = 0; j < SSA_COUNT; j++) {
2018 }
2019
2021 SSA_COUNT,
2022 "savefile.server_side_agent_list");
2023 free(modname);
2024 }
2025
2026 /* Save terrain character mapping in the savegame. */
2027 i = 0;
2029 char buf[2];
2030
2031 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2033 buf[1] = '\0';
2034 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2036}
2037
2038/************************************************************************/
2042 const char *option)
2043{
2044 /* Check status and return if not OK (sg_success FALSE). */
2045 sg_check_ret();
2046
2047 if (option == NULL) {
2048 /* no additional option */
2049 return;
2050 }
2051
2052 sz_strlcat(saving->secfile_options, option);
2053 secfile_replace_str(saving->file, saving->secfile_options,
2054 "savefile.options");
2055}
2056
2057/* =======================================================================
2058 * Load / save game status.
2059 * ======================================================================= */
2060
2061/************************************************************************/
2065{
2066 int i;
2067 const char *name;
2068
2069 /* Check status and return if not OK (sg_success FALSE). */
2070 sg_check_ret();
2071
2072 for (i = 0;
2074 "ruledata.government%d.name", i));
2075 i++) {
2077
2078 if (gov != NULL) {
2080 "ruledata.government%d.changes", i);
2081 }
2082 }
2083}
2084
2085/************************************************************************/
2088static void sg_load_game(struct loaddata *loading)
2089{
2090 const char *str;
2091 int i;
2092
2093 /* Check status and return if not OK (sg_success FALSE). */
2094 sg_check_ret();
2095
2096 /* Load server state. */
2097 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2098 "game.server_state");
2099 loading->server_state = server_states_by_name(str, strcmp);
2100 if (!server_states_is_valid(loading->server_state)) {
2101 /* Don't take any risk! */
2102 loading->server_state = S_S_INITIAL;
2103 }
2104
2106 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2107
2110 "game.meta_patches");
2112
2114 /* Do not overwrite this if the user requested a specific metaserver
2115 * from the command line (option --Metaserver). */
2119 "game.meta_server"));
2120 }
2121
2122 if ('\0' == srvarg.serverid[0]) {
2123 /* Do not overwrite this if the user requested a specific metaserver
2124 * from the command line (option --serverid). */
2127 "game.serverid"));
2128 }
2129 sz_strlcpy(server.game_identifier,
2130 secfile_lookup_str_default(loading->file, "", "game.id"));
2131 /* We are not checking game_identifier legality just yet.
2132 * That's done when we are sure that rand seed has been initialized,
2133 * so that we can generate new game_identifier, if needed.
2134 * See sq_load_sanitycheck(). */
2135
2137 "game.phase_mode");
2138 if (str != NULL) {
2141 log_error("Illegal phase mode \"%s\"", str);
2143 }
2144 } else {
2145 log_error("Phase mode missing");
2146 }
2147
2149 "game.phase_mode_stored");
2150 if (str != NULL) {
2153 log_error("Illegal stored phase mode \"%s\"", str);
2155 }
2156 } else {
2157 log_error("Stored phase mode missing");
2158 }
2161 "game.phase");
2165 "game.scoreturn");
2166
2169 "game.timeoutint");
2172 "game.timeoutintinc");
2175 "game.timeoutinc");
2178 "game.timeoutincmult");
2181 "game.timeoutcounter");
2182
2183 game.info.turn
2184 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2186 "game.year"), "%s", secfile_error());
2188 "game.world_peace_start"), "%s", secfile_error());
2190 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2191
2193 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2195 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2197 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2198
2200 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2202 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2204 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2205
2206 /* Savegame may have stored random_seed for documentation purposes only,
2207 * but we want to keep it for resaving. */
2208 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2209
2210 /* Global advances. */
2212 "game.global_advances");
2213 if (str != NULL) {
2214 sg_failure_ret(strlen(str) == loading->technology.size,
2215 "Invalid length of 'game.global_advances' ("
2216 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2217 strlen(str), loading->technology.size);
2218 for (i = 0; i < loading->technology.size; i++) {
2219 sg_failure_ret(str[i] == '1' || str[i] == '0',
2220 "Undefined value '%c' within 'game.global_advances'.",
2221 str[i]);
2222 if (str[i] == '1') {
2223 struct advance *padvance =
2224 advance_by_rule_name(loading->technology.order[i]);
2225
2226 if (padvance != NULL) {
2228 }
2229 }
2230 }
2231 }
2232
2234 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2235
2237 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2238}
2239
2240/************************************************************************/
2244{
2245 int set_count = 0;
2246
2248 char path[256];
2249
2250 fc_snprintf(path, sizeof(path),
2251 "ruledata.government%d", set_count++);
2252
2254 "%s.name", path);
2255 secfile_insert_int(saving->file, pgov->changed_to_times,
2256 "%s.changes", path);
2258}
2259
2260/************************************************************************/
2263static void sg_save_game(struct savedata *saving)
2264{
2266 char global_advances[game.control.num_tech_types + 1];
2267 int i;
2268
2269 /* Check status and return if not OK (sg_success FALSE). */
2270 sg_check_ret();
2271
2272 /* Game state: once the game is no longer a new game (ie, has been
2273 * started the first time), it should always be considered a running
2274 * game for savegame purposes. */
2275 if (saving->scenario && !game.scenario.players) {
2277 } else {
2279 }
2281 "game.server_state");
2282
2283 if (game.server.phase_timer != NULL) {
2287 "game.phase_seconds");
2288 }
2289
2291 "game.meta_patches");
2292 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2293
2294 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2295 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2296
2299 "game.phase_mode");
2302 "game.phase_mode_stored");
2304 "game.phase");
2306 "game.scoreturn");
2307
2309 "game.timeoutint");
2311 "game.timeoutintinc");
2313 "game.timeoutinc");
2315 "game.timeoutincmult");
2317 "game.timeoutcounter");
2318
2319 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2320 secfile_insert_int(saving->file, game.info.year, "game.year");
2321 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2323 "game.year_0_hack");
2324
2326 "game.globalwarming");
2328 "game.heating");
2330 "game.warminglevel");
2331
2333 "game.nuclearwinter");
2335 "game.cooling");
2337 "game.coolinglevel");
2338 /* For debugging purposes only.
2339 * Do not save it if it's 0 (not known);
2340 * this confuses people reading this 'document' less than
2341 * saving 0. */
2342 if (game.server.seed != 0) {
2344 "game.random_seed");
2345 }
2346
2347 /* Global advances. */
2348 for (i = 0; i < game.control.num_tech_types; i++) {
2349 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2350 }
2351 global_advances[i] = '\0';
2352 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2353
2354 if (!game_was_started()) {
2355 saving->save_players = FALSE;
2356 } else {
2357 if (saving->scenario) {
2358 saving->save_players = game.scenario.players;
2359 } else {
2360 saving->save_players = TRUE;
2361 }
2362#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2364 "game.last_turn_change_time");
2365#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2367 "game.last_turn_change_time");
2368#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2369 }
2370 secfile_insert_bool(saving->file, saving->save_players,
2371 "game.save_players");
2372
2373 if (srv_state != S_S_INITIAL) {
2374 const char *ainames[ai_type_get_count()];
2375
2376 i = 0;
2377 ai_type_iterate(ait) {
2378 ainames[i] = ait->name;
2379 i++;
2381
2383 "game.ai_types");
2384 }
2385}
2386
2387/* =======================================================================
2388 * Load / save random status.
2389 * ======================================================================= */
2390
2391/************************************************************************/
2394static void sg_load_random(struct loaddata *loading)
2395{
2396 /* Check status and return if not OK (sg_success FALSE). */
2397 sg_check_ret();
2398
2399 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2400 const char *str;
2401 int i;
2402
2404 "random.index_J"), "%s", secfile_error());
2406 "random.index_K"), "%s", secfile_error());
2408 "random.index_X"), "%s", secfile_error());
2409
2410 for (i = 0; i < 8; i++) {
2411 str = secfile_lookup_str(loading->file, "random.table%d",i);
2412 sg_failure_ret(NULL != str, "%s", secfile_error());
2413 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2414 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2415 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2416 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2417 }
2418 loading->rstate.is_init = TRUE;
2419 fc_rand_set_state(loading->rstate);
2420 } else {
2421 /* No random values - mark the setting. */
2422 (void) secfile_entry_by_path(loading->file, "random.saved");
2423
2424 /* We're loading a game without a seed (which is okay, if it's a scenario).
2425 * We need to generate the game seed now because it will be needed later
2426 * during the load. */
2428 loading->rstate = fc_rand_state();
2429 }
2430}
2431
2432/************************************************************************/
2435static void sg_save_random(struct savedata *saving)
2436{
2437 /* Check status and return if not OK (sg_success FALSE). */
2438 sg_check_ret();
2439
2440 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2441 int i;
2442 RANDOM_STATE rstate = fc_rand_state();
2443
2444 secfile_insert_bool(saving->file, TRUE, "random.saved");
2445 fc_assert(rstate.is_init);
2446
2447 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2448 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2449 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2450
2451 for (i = 0; i < 8; i++) {
2452 char vec[100];
2453
2454 fc_snprintf(vec, sizeof(vec),
2455 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2456 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2457 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2458 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2459 secfile_insert_str(saving->file, vec, "random.table%d", i);
2460 }
2461 } else {
2462 secfile_insert_bool(saving->file, FALSE, "random.saved");
2463 }
2464}
2465
2466/* =======================================================================
2467 * Load / save lua script data.
2468 * ======================================================================= */
2469
2470/************************************************************************/
2473static void sg_load_script(struct loaddata *loading)
2474{
2475 /* Check status and return if not OK (sg_success FALSE). */
2476 sg_check_ret();
2477
2479}
2480
2481/************************************************************************/
2484static void sg_save_script(struct savedata *saving)
2485{
2486 /* Check status and return if not OK (sg_success FALSE). */
2487 sg_check_ret();
2488
2490}
2491
2492/* =======================================================================
2493 * Load / save scenario data.
2494 * ======================================================================= */
2495
2496/************************************************************************/
2500{
2501 const char *buf;
2502 int game_version;
2503
2504 /* Check status and return if not OK (sg_success FALSE). */
2505 sg_check_ret();
2506
2507 /* Load version. */
2509 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2510 /* We require at least version 2.90.99 - and at that time we saved version
2511 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2512 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2513 "version 2.90.99 required.");
2514
2515 loading->full_version = game_version;
2516
2517 game.scenario.datafile[0] = '\0';
2518
2520 "scenario.is_scenario"), "%s", secfile_error());
2521 if (!game.scenario.is_scenario) {
2522 return;
2523 }
2524
2525 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2526 if (buf[0] != '\0') {
2528 }
2529
2531 "scenario.authors");
2532 if (buf[0] != '\0') {
2534 } else {
2535 game.scenario.authors[0] = '\0';
2536 }
2537
2539 "scenario.description");
2540 if (buf[0] != '\0') {
2542 } else {
2543 game.scenario_desc.description[0] = '\0';
2544 }
2546 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2548 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2551 "scenario.startpos_nations");
2554 "scenario.prevent_new_cities");
2557 "scenario.lake_flooding");
2560 "scenario.handmade");
2563 "scenario.allow_ai_type_fallback");
2564
2567 "scenario.ruleset_locked");
2568
2570 "scenario.datafile");
2571 if (buf[0] != '\0') {
2573 }
2574
2575 sg_failure_ret(loading->server_state == S_S_INITIAL
2576 || (loading->server_state == S_S_RUNNING
2577 && game.scenario.players),
2578 "Invalid scenario definition (server state '%s' and "
2579 "players are %s).",
2580 server_states_name(loading->server_state),
2581 game.scenario.players ? "saved" : "not saved");
2582}
2583
2584/************************************************************************/
2588{
2589 struct entry *mod_entry;
2590 int game_version;
2591
2592 /* Check status and return if not OK (sg_success FALSE). */
2593 sg_check_ret();
2594
2595 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2596#ifdef EMERGENCY_VERSION
2598#endif /* EMERGENCY_VERSION */
2599 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2600
2601 if (!saving->scenario || !game.scenario.is_scenario) {
2602 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2603 return;
2604 }
2605
2606 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2607
2608 /* Name is mandatory to the level that is saved even if empty. */
2609 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2611
2612 /* Authors list is saved only if it exist */
2613 if (game.scenario.authors[0] != '\0') {
2615 "scenario.authors");
2617 }
2618
2619 /* Description is saved only if it exist */
2620 if (game.scenario_desc.description[0] != '\0') {
2622 "scenario.description");
2624 }
2625
2626 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2627 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2629 "scenario.startpos_nations");
2632 "scenario.prevent_new_cities");
2633 }
2635 "scenario.lake_flooding");
2636 if (game.scenario.handmade) {
2638 "scenario.handmade");
2639 }
2642 "scenario.allow_ai_type_fallback");
2643 }
2644
2645 if (game.scenario.datafile[0] != '\0') {
2647 "scenario.datafile");
2648 }
2650 "scenario.ruleset_locked");
2651 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2653 "scenario.ruleset_caps");
2654 }
2655}
2656
2657/* =======================================================================
2658 * Load / save game settings.
2659 * ======================================================================= */
2660
2661/************************************************************************/
2665{
2666 /* Check status and return if not OK (sg_success FALSE). */
2667 sg_check_ret();
2668
2669 settings_game_load(loading->file, "settings");
2670
2671 /* Save current status of fogofwar. */
2673
2674 /* Add all compatibility settings here. */
2675}
2676
2677/************************************************************************/
2681{
2683
2684 /* Check status and return if not OK (sg_success FALSE). */
2685 sg_check_ret();
2686
2687 if (saving->scenario) {
2688 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2689 }
2690
2691 settings_game_save(saving->file, "settings");
2692 /* Restore real map generator. */
2694
2695 /* Add all compatibility settings here. */
2696}
2697
2698
2699/************************************************************************/
2703{
2704 struct city *pcity;
2705 int i, j;
2706 size_t length, length2;
2707 int *city_count;
2709 "savefile.city_counters_order_size");
2710
2711 if (0==length) {
2712
2713 return;
2714 }
2715
2716 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2717
2718 sg_failure_ret(loading->counter.order != 0,
2719 "Failed to load counter's ruleset order: %s",
2720 secfile_error());
2721 sg_failure_ret(loading->counter.size = length,
2722 "Counter vector in savegame have bad size: %s",
2723 secfile_error());
2724
2725 int corder[length];
2726
2727 for (i = 0; i < length; i++) {
2728
2729 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2731 }
2732
2733 i = 0;
2734 while (NULL != (city_count =
2736 "counters.c%d", i))) {
2737
2738 sg_failure_ret((length2 -1 == (size_t) length), ( "Bad city counters vector size. Should be " SIZE_T_PRINTF ". Is " SIZE_T_PRINTF "." ), length, length2 - 1);
2739
2741
2742 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2743
2744 for (j = 0; j < length; j++) {
2745
2746 pcity->counter_values[corder[j]] = city_count[j+1];
2747 }
2748 i++;
2749 }
2750}
2751
2752/************************************************************************/
2756{
2757 /* Check status and return if not OK (sg_success FALSE). */
2758 sg_check_ret();
2759
2760 const char **countnames;
2761 int *countvalues;
2762 int i, j, count;
2763
2765
2766 secfile_insert_int(saving->file, count,
2767 "savefile.city_counters_order_size");
2768
2769 if (0 == count) {
2770
2771 return;
2772 }
2773
2774 countnames = fc_calloc(count, sizeof(*countnames));
2775 for (j = 0; j < count; j++) {
2777 }
2778
2780 "savefile.city_counters_order_vector");
2781
2783
2784 // Saving city's counters
2785
2786 j = 0;
2787 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2788
2790
2791 city_list_iterate(_pplayer->cities, pcity) {
2792
2793 countvalues[0] = pcity->id;
2794 for (i = 0; i < count; ++i) {
2795
2796 countvalues[i+1] = pcity->counter_values[i];
2797 }
2798
2799 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2800 ++j;
2803
2805}
2806
2807/* =======================================================================
2808 * Load / save the main map.
2809 * ======================================================================= */
2810
2811/************************************************************************/
2814static void sg_load_map(struct loaddata *loading)
2815{
2816 /* Check status and return if not OK (sg_success FALSE). */
2817 sg_check_ret();
2818
2819 /* This defaults to TRUE even if map has not been generated.
2820 * We rely on that
2821 * 1) scenario maps have it explicitly right.
2822 * 2) when map is actually generated, it re-initialize this to FALSE. */
2824 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2825
2827 "map.altitude"),
2828 "%s", secfile_error());
2829
2831 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2832
2834
2835 /* Savegame may have stored random_seed for documentation purposes only,
2836 * but we want to keep it for resaving. */
2838 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2839
2840 if (S_S_INITIAL == loading->server_state
2842 /* Generator MAPGEN_SCENARIO is used;
2843 * this map was done with the map editor. */
2844
2845 /* Load tiles. */
2849
2850 /* Nothing more needed for a scenario. */
2851 return;
2852 }
2853
2854 if (S_S_INITIAL == loading->server_state) {
2855 /* Nothing more to do if it is not a scenario but in initial state. */
2856 return;
2857 }
2858
2860 if (wld.map.altitude_info) {
2862 }
2868}
2869
2870/************************************************************************/
2873static void sg_save_map(struct savedata *saving)
2874{
2875 /* Check status and return if not OK (sg_success FALSE). */
2876 sg_check_ret();
2877
2878 if (map_is_empty()) {
2879 /* No map. */
2880 return;
2881 }
2882
2883 if (saving->scenario) {
2885 "map.have_huts");
2887 "map.have_resources");
2888 } else {
2889 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2890 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2891 }
2892
2893 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2894
2895 /* For debugging purposes only.
2896 * Do not save it if it's 0 (not known);
2897 * this confuses people reading this 'document' less than
2898 * saving 0. */
2899 if (wld.map.server.seed != 0) {
2901 "map.random_seed");
2902 }
2903
2905 if (wld.map.altitude_info) {
2907 }
2913}
2914
2915/************************************************************************/
2919{
2920 /* Check status and return if not OK (sg_success FALSE). */
2921 sg_check_ret();
2922
2923 /* Initialize the map for the current topology. 'map.xsize' and
2924 * 'map.ysize' must be set. */
2926
2927 /* Allocate map. */
2929
2930 /* get the terrain type */
2931 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2932 "map.t%04d");
2934
2935 /* Check for special tile sprites. */
2936 whole_map_iterate(&(wld.map), ptile) {
2937 const char *spec_sprite;
2938 const char *label;
2939 int nat_x, nat_y;
2940
2942 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2943 nat_x, nat_y);
2944 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2945 nat_x, nat_y);
2946 if (NULL != ptile->spec_sprite) {
2947 ptile->spec_sprite = fc_strdup(spec_sprite);
2948 }
2949 if (label != NULL) {
2950 tile_set_label(ptile, label);
2951 }
2953}
2954
2955/************************************************************************/
2959{
2960 /* Check status and return if not OK (sg_success FALSE). */
2961 sg_check_ret();
2962
2963 /* Save the terrain type. */
2964 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2965 "map.t%04d");
2966
2967 /* Save special tile sprites. */
2968 whole_map_iterate(&(wld.map), ptile) {
2969 int nat_x, nat_y;
2970
2972 if (ptile->spec_sprite) {
2973 secfile_insert_str(saving->file, ptile->spec_sprite,
2974 "map.spec_sprite_%d_%d", nat_x, nat_y);
2975 }
2976 if (ptile->label != NULL) {
2977 secfile_insert_str(saving->file, ptile->label,
2978 "map.label_%d_%d", nat_x, nat_y);
2979 }
2981}
2982
2983/************************************************************************/
2987{
2988 int y;
2989
2990 /* Check status and return if not OK (sg_success FALSE). */
2991 sg_check_ret();
2992
2993 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
2994 const char *buffer = secfile_lookup_str(loading->file,
2995 "map.alt%04d", y);
2996 const char *ptr = buffer;
2997 int x;
2998
2999 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3000
3001 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3002 char token[TOKEN_SIZE];
3003 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3004 int number;
3005
3006 scanin(&ptr, ",", token, sizeof(token));
3007 sg_failure_ret(token[0] != '\0',
3008 "Map size not correct (map.alt%d).", y);
3009 sg_failure_ret(str_to_int(token, &number),
3010 "Got map alt %s in (%d, %d).", token, x, y);
3011 ptile->altitude = number;
3012 }
3013 }
3014}
3015
3016/************************************************************************/
3020{
3021 int y;
3022
3023 /* Check status and return if not OK (sg_success FALSE). */
3024 sg_check_ret();
3025
3026 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3028 int x;
3029
3030 line[0] = '\0';
3031 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3032 char token[TOKEN_SIZE];
3033 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3034
3035 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3036
3037 strcat(line, token);
3038 if (x + 1 < MAP_NATIVE_WIDTH) {
3039 strcat(line, ",");
3040 }
3041 }
3042
3043 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3044 }
3045}
3046
3047/************************************************************************/
3051{
3052 /* Check status and return if not OK (sg_success FALSE). */
3053 sg_check_ret();
3054
3055 /* Load extras. */
3056 halfbyte_iterate_extras(j, loading->extra.size) {
3057 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3058 loading->extra.order + 4 * j),
3059 loading->file, "map.e%02d_%04d", j);
3061
3062 if (S_S_INITIAL != loading->server_state
3065 whole_map_iterate(&(wld.map), ptile) {
3067 if (tile_has_extra(ptile, pres)) {
3068 tile_set_resource(ptile, pres);
3069
3070 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3071 BV_CLR(ptile->extras, extra_index(pres));
3072 }
3073 }
3076 }
3077}
3078
3079/************************************************************************/
3083{
3084 /* Check status and return if not OK (sg_success FALSE). */
3085 sg_check_ret();
3086
3087 /* Save extras. */
3089 int mod[4];
3090 int l;
3091
3092 for (l = 0; l < 4; l++) {
3093 if (4 * j + 1 > game.control.num_extra_types) {
3094 mod[l] = -1;
3095 } else {
3096 mod[l] = 4 * j + l;
3097 }
3098 }
3099 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3100 saving->file, "map.e%02d_%04d", j);
3102}
3103
3104/************************************************************************/
3109{
3110 struct nation_type *pnation;
3111 struct startpos *psp;
3112 struct tile *ptile;
3113 const char SEPARATOR = '#';
3114 const char *nation_names;
3115 int nat_x, nat_y;
3116 bool exclude;
3117 int i, startpos_count;
3118
3119 /* Check status and return if not OK (sg_success FALSE). */
3120 sg_check_ret();
3121
3123 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3124
3125 if (0 == startpos_count) {
3126 /* Nothing to do. */
3127 return;
3128 }
3129
3130 for (i = 0; i < startpos_count; i++) {
3131 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3132 || !secfile_lookup_int(loading->file, &nat_y,
3133 "map.startpos%d.y", i)) {
3134 log_sg("Warning: Undefined coordinates for startpos %d", i);
3135 continue;
3136 }
3137
3138 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3139 if (NULL == ptile) {
3140 log_error("Start position native coordinates (%d, %d) do not exist "
3141 "in this map. Skipping...", nat_x, nat_y);
3142 continue;
3143 }
3144
3145 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3146 "map.startpos%d.exclude", i);
3147
3148 psp = map_startpos_new(ptile);
3149
3151 "map.startpos%d.nations", i);
3152 if (NULL != nation_names && '\0' != nation_names[0]) {
3153 const size_t size = strlen(nation_names) + 1;
3154 char buf[size], *start, *end;
3155
3157 for (start = buf - 1; NULL != start; start = end) {
3158 start++;
3159 if ((end = strchr(start, SEPARATOR))) {
3160 *end = '\0';
3161 }
3162
3163 pnation = nation_by_rule_name(start);
3164 if (NO_NATION_SELECTED != pnation) {
3165 if (exclude) {
3166 startpos_disallow(psp, pnation);
3167 } else {
3168 startpos_allow(psp, pnation);
3169 }
3170 } else {
3171 log_verbose("Missing nation \"%s\".", start);
3172 }
3173 }
3174 }
3175 }
3176
3177 if (0 < map_startpos_count()
3178 && loading->server_state == S_S_INITIAL
3180 log_verbose("Number of starts (%d) are lower than rules.max_players "
3181 "(%d), lowering rules.max_players.",
3184 }
3185
3186 /* Re-initialize nation availability in light of start positions.
3187 * This has to be after loading [scenario] and [map].startpos and
3188 * before we seek nations for players. */
3190}
3191
3192/************************************************************************/
3196{
3197 struct tile *ptile;
3198 const char SEPARATOR = '#';
3199 int i = 0;
3200
3201 /* Check status and return if not OK (sg_success FALSE). */
3202 sg_check_ret();
3203
3205 return;
3206 }
3207
3209 "map.startpos_count");
3210
3212 int nat_x, nat_y;
3213
3214 ptile = startpos_tile(psp);
3215
3217 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3218 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3219
3221 "map.startpos%d.exclude", i);
3222 if (startpos_allows_all(psp)) {
3223 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3224 } else {
3225 const struct nation_hash *nations = startpos_raw_nations(psp);
3227
3228 nation_names[0] = '\0';
3229 nation_hash_iterate(nations, pnation) {
3230 if ('\0' == nation_names[0]) {
3232 sizeof(nation_names));
3233 } else {
3235 "%c%s", SEPARATOR, nation_rule_name(pnation));
3236 }
3239 "map.startpos%d.nations", i);
3240 }
3241 i++;
3243
3245}
3246
3247/************************************************************************/
3251{
3252 int y;
3253 struct tile *claimer = NULL;
3254 struct extra_type *placing = NULL;
3255
3256 /* Check status and return if not OK (sg_success FALSE). */
3257 sg_check_ret();
3258
3259 if (game.info.is_new_game) {
3260 /* No owner/source information for a new game / scenario. */
3261 return;
3262 }
3263
3264 /* Owner, ownership source, and infra turns are stored as plain numbers */
3265 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3266 const char *buffer1 = secfile_lookup_str(loading->file,
3267 "map.owner%04d", y);
3268 const char *buffer2 = secfile_lookup_str(loading->file,
3269 "map.source%04d", y);
3270 const char *buffer3 = secfile_lookup_str(loading->file,
3271 "map.eowner%04d", y);
3273 NULL,
3274 "map.placing%04d", y);
3276 NULL,
3277 "map.infra_turns%04d", y);
3278 const char *ptr1 = buffer1;
3279 const char *ptr2 = buffer2;
3280 const char *ptr3 = buffer3;
3281 const char *ptr_placing = buffer_placing;
3282 const char *ptr_turns = buffer_turns;
3283 int x;
3284
3288
3289 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3290 char token1[TOKEN_SIZE];
3291 char token2[TOKEN_SIZE];
3292 char token3[TOKEN_SIZE];
3294 char token_turns[TOKEN_SIZE];
3295 struct player *owner = NULL;
3296 struct player *eowner = NULL;
3297 int turns;
3298 int number;
3299 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3300
3301 scanin(&ptr1, ",", token1, sizeof(token1));
3302 sg_failure_ret(token1[0] != '\0',
3303 "Map size not correct (map.owner%d).", y);
3304 if (strcmp(token1, "-") == 0) {
3305 owner = NULL;
3306 } else {
3308 "Got map owner %s in (%d, %d).", token1, x, y);
3309 owner = player_by_number(number);
3310 }
3311
3312 scanin(&ptr2, ",", token2, sizeof(token2));
3313 sg_failure_ret(token2[0] != '\0',
3314 "Map size not correct (map.source%d).", y);
3315 if (strcmp(token2, "-") == 0) {
3316 claimer = NULL;
3317 } else {
3319 "Got map source %s in (%d, %d).", token2, x, y);
3320 claimer = index_to_tile(&(wld.map), number);
3321 }
3322
3323 scanin(&ptr3, ",", token3, sizeof(token3));
3324 sg_failure_ret(token3[0] != '\0',
3325 "Map size not correct (map.eowner%d).", y);
3326 if (strcmp(token3, "-") == 0) {
3327 eowner = NULL;
3328 } else {
3330 "Got base owner %s in (%d, %d).", token3, x, y);
3331 eowner = player_by_number(number);
3332 }
3333
3334 if (ptr_placing != NULL) {
3336 sg_failure_ret(token_placing[0] != '\0',
3337 "Map size not correct (map.placing%d).", y);
3338 if (strcmp(token_placing, "-") == 0) {
3339 placing = NULL;
3340 } else {
3342 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3343 placing = extra_by_number(number);
3344 }
3345 } else {
3346 placing = NULL;
3347 }
3348
3349 if (ptr_turns != NULL) {
3350 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3351 sg_failure_ret(token_turns[0] != '\0',
3352 "Map size not correct (map.infra_turns%d).", y);
3354 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3355 turns = number;
3356 } else {
3357 turns = 1;
3358 }
3359
3361 tile_claim_bases(ptile, eowner);
3362 ptile->placing = placing;
3363 ptile->infra_turns = turns;
3364 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3365 }
3366 }
3367}
3368
3369/************************************************************************/
3373{
3374 int y;
3375
3376 /* Check status and return if not OK (sg_success FALSE). */
3377 sg_check_ret();
3378
3379 if (saving->scenario && !saving->save_players) {
3380 /* Nothing to do for a scenario without saved players. */
3381 return;
3382 }
3383
3384 /* Store owner and ownership source as plain numbers. */
3385 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3387 int x;
3388
3389 line[0] = '\0';
3390 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3391 char token[TOKEN_SIZE];
3392 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3393
3394 if (!saving->save_players || tile_owner(ptile) == NULL) {
3395 strcpy(token, "-");
3396 } else {
3397 fc_snprintf(token, sizeof(token), "%d",
3398 player_number(tile_owner(ptile)));
3399 }
3400 strcat(line, token);
3401 if (x + 1 < MAP_NATIVE_WIDTH) {
3402 strcat(line, ",");
3403 }
3404 }
3405
3406 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3407 }
3408
3409 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3411 int x;
3412
3413 line[0] = '\0';
3414 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3415 char token[TOKEN_SIZE];
3416 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3417
3418 if (ptile->claimer == NULL) {
3419 strcpy(token, "-");
3420 } else {
3421 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3422 }
3423 strcat(line, token);
3424 if (x + 1 < MAP_NATIVE_WIDTH) {
3425 strcat(line, ",");
3426 }
3427 }
3428
3429 secfile_insert_str(saving->file, line, "map.source%04d", y);
3430 }
3431
3432 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3434 int x;
3435
3436 line[0] = '\0';
3437 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3438 char token[TOKEN_SIZE];
3439 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3440
3441 if (!saving->save_players || extra_owner(ptile) == NULL) {
3442 strcpy(token, "-");
3443 } else {
3444 fc_snprintf(token, sizeof(token), "%d",
3445 player_number(extra_owner(ptile)));
3446 }
3447 strcat(line, token);
3448 if (x + 1 < MAP_NATIVE_WIDTH) {
3449 strcat(line, ",");
3450 }
3451 }
3452
3453 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3454 }
3455
3456 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3458 int x;
3459
3460 line[0] = '\0';
3461 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3462 char token[TOKEN_SIZE];
3463 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3464
3465 if (ptile->placing == NULL) {
3466 strcpy(token, "-");
3467 } else {
3468 fc_snprintf(token, sizeof(token), "%d",
3469 extra_number(ptile->placing));
3470 }
3471 strcat(line, token);
3472 if (x + 1 < MAP_NATIVE_WIDTH) {
3473 strcat(line, ",");
3474 }
3475 }
3476
3477 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3478 }
3479
3480 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3482 int x;
3483
3484 line[0] = '\0';
3485 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3486 char token[TOKEN_SIZE];
3487 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3488
3489 if (ptile->placing != NULL) {
3490 fc_snprintf(token, sizeof(token), "%d",
3491 ptile->infra_turns);
3492 } else {
3493 fc_snprintf(token, sizeof(token), "0");
3494 }
3495 strcat(line, token);
3496 if (x + 1 < MAP_NATIVE_WIDTH) {
3497 strcat(line, ",");
3498 }
3499 }
3500
3501 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3502 }
3503}
3504
3505/************************************************************************/
3509{
3510 int x, y;
3511
3512 /* Check status and return if not OK (sg_success FALSE). */
3513 sg_check_ret();
3514
3515 sg_failure_ret(loading->worked_tiles == NULL,
3516 "City worked map not loaded!");
3517
3518 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3519 sizeof(*loading->worked_tiles));
3520
3521 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3522 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3523 y);
3524 const char *ptr = buffer;
3525
3526 sg_failure_ret(NULL != buffer,
3527 "Savegame corrupt - map line %d not found.", y);
3528 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3529 char token[TOKEN_SIZE];
3530 int number;
3531 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3532
3533 scanin(&ptr, ",", token, sizeof(token));
3534 sg_failure_ret('\0' != token[0],
3535 "Savegame corrupt - map size not correct.");
3536 if (strcmp(token, "-") == 0) {
3537 number = -1;
3538 } else {
3539 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3540 "Savegame corrupt - got tile worked by city "
3541 "id=%s in (%d, %d).", token, x, y);
3542 }
3543
3544 loading->worked_tiles[ptile->index] = number;
3545 }
3546 }
3547}
3548
3549/************************************************************************/
3553{
3554 int x, y;
3555
3556 /* Check status and return if not OK (sg_success FALSE). */
3557 sg_check_ret();
3558
3559 if (saving->scenario && !saving->save_players) {
3560 /* Nothing to do for a scenario without saved players. */
3561 return;
3562 }
3563
3564 /* Additionally save the tiles worked by the cities */
3565 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3567
3568 line[0] = '\0';
3569 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3570 char token[TOKEN_SIZE];
3571 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3572 struct city *pcity = tile_worked(ptile);
3573
3574 if (pcity == NULL) {
3575 strcpy(token, "-");
3576 } else {
3577 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3578 }
3579 strcat(line, token);
3580 if (x < MAP_NATIVE_WIDTH) {
3581 strcat(line, ",");
3582 }
3583 }
3584 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3585 }
3586}
3587
3588/************************************************************************/
3592{
3593 /* Check status and return if not OK (sg_success FALSE). */
3594 sg_check_ret();
3595
3596 players_iterate(pplayer) {
3597 /* Allocate player private map here; it is needed in different modules
3598 * besides this one ((i.e. sg_load_player_*()). */
3599 player_map_init(pplayer);
3601
3603 "game.save_known")) {
3604 int lines = player_slot_max_used_number()/32 + 1, j, p, l, i;
3605 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3606
3607 for (l = 0; l < lines; l++) {
3608 for (j = 0; j < 8; j++) {
3609 for (i = 0; i < 4; i++) {
3610 /* Only bother trying to load the map for this halfbyte if at least
3611 * one of the corresponding player slots is in use. */
3612 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3613 LOAD_MAP_CHAR(ch, ptile,
3614 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3615 |= ascii_hex2bin(ch, j),
3616 loading->file, "map.k%02d_%04d", l * 8 + j);
3617 break;
3618 }
3619 }
3620 }
3621 }
3622
3623 players_iterate(pplayer) {
3624 dbv_clr_all(&pplayer->tile_known);
3626
3627 /* HACK: we read the known data from hex into 32-bit integers, and
3628 * now we convert it to the known tile data of each player. */
3629 whole_map_iterate(&(wld.map), ptile) {
3630 players_iterate(pplayer) {
3631 p = player_index(pplayer);
3632 l = player_index(pplayer) / 32;
3633
3634 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3635 map_set_known(ptile, pplayer);
3636 }
3639
3640 FC_FREE(known);
3641 }
3642}
3643
3644/************************************************************************/
3648{
3649 /* Check status and return if not OK (sg_success FALSE). */
3650 sg_check_ret();
3651
3652 if (!saving->save_players) {
3653 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3654 return;
3655 } else {
3656 int lines = player_slot_max_used_number()/32 + 1;
3657
3659 "game.save_known");
3661 int j, p, l, i;
3662 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3663
3664 /* HACK: we convert the data into a 32-bit integer, and then save it as
3665 * hex. */
3666
3667 whole_map_iterate(&(wld.map), ptile) {
3668 players_iterate(pplayer) {
3669 if (map_is_known(ptile, pplayer)) {
3670 p = player_index(pplayer);
3671 l = p / 32;
3672 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3673 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3674 }
3677
3678 for (l = 0; l < lines; l++) {
3679 for (j = 0; j < 8; j++) {
3680 for (i = 0; i < 4; i++) {
3681 /* Only bother saving the map for this halfbyte if at least one
3682 * of the corresponding player slots is in use */
3683 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3684 /* put 4-bit segments of the 32-bit "known" field */
3686 + tile_index(ptile)], j),
3687 saving->file, "map.k%02d_%04d", l * 8 + j);
3688 break;
3689 }
3690 }
3691 }
3692 }
3693
3694 FC_FREE(known);
3695 }
3696 }
3697}
3698
3699/* =======================================================================
3700 * Load / save player data.
3701 *
3702 * This is split into two parts as some data can only be loaded if the
3703 * number of players is known and the corresponding player slots are
3704 * defined.
3705 * ======================================================================= */
3706
3707/************************************************************************/
3711{
3712 int i, k, nplayers;
3713 const char *str;
3714 bool shuffle_loaded = TRUE;
3715
3716 /* Check status and return if not OK (sg_success FALSE). */
3717 sg_check_ret();
3718
3719 if (S_S_INITIAL == loading->server_state
3720 || game.info.is_new_game) {
3721 /* Nothing more to do. */
3722 return;
3723 }
3724
3725 /* Load destroyed wonders: */
3727 "players.destroyed_wonders");
3728 sg_failure_ret(str != NULL, "%s", secfile_error());
3729 sg_failure_ret(strlen(str) == loading->improvement.size,
3730 "Invalid length for 'players.destroyed_wonders' ("
3731 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3732 strlen(str), loading->improvement.size);
3733 for (k = 0; k < loading->improvement.size; k++) {
3734 sg_failure_ret(str[k] == '1' || str[k] == '0',
3735 "Undefined value '%c' within "
3736 "'players.destroyed_wonders'.", str[k]);
3737
3738 if (str[k] == '1') {
3739 struct impr_type *pimprove =
3740 improvement_by_rule_name(loading->improvement.order[k]);
3741 if (pimprove) {
3744 }
3745 }
3746 }
3747
3748 server.identity_number
3749 = secfile_lookup_int_default(loading->file, server.identity_number,
3750 "players.identity_number_used");
3751
3752 /* First remove all defined players. */
3753 players_iterate(pplayer) {
3754 server_remove_player(pplayer);
3756
3757 /* Now, load the players from the savefile. */
3758 player_slots_iterate(pslot) {
3759 struct player *pplayer;
3760 struct rgbcolor *prgbcolor = NULL;
3761 int pslot_id = player_slot_index(pslot);
3762
3763 if (NULL == secfile_section_lookup(loading->file, "player%d",
3764 pslot_id)) {
3765 continue;
3766 }
3767
3768 /* Get player AI type. */
3769 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3770 player_slot_index(pslot));
3771 sg_failure_ret(str != NULL, "%s", secfile_error());
3772
3773 /* Get player color */
3774 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3775 pslot_id)) {
3776 if (game_was_started()) {
3777 log_sg("Game has started, yet player %d has no color defined.",
3778 pslot_id);
3779 /* This will be fixed up later */
3780 } else {
3781 log_verbose("No color defined for player %d.", pslot_id);
3782 /* Colors will be assigned on game start, or at end of savefile
3783 * loading if game has already started */
3784 }
3785 }
3786
3787 /* Create player. */
3788 pplayer = server_create_player(player_slot_index(pslot), str,
3789 prgbcolor,
3792 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3793
3794 server_player_init(pplayer, FALSE, FALSE);
3795
3796 /* Free the color definition. */
3798
3799 /* Multipliers (policies) */
3800
3801 /* First initialise player values with ruleset defaults; this will
3802 * cover any in the ruleset not known when the savefile was created. */
3803 multipliers_iterate(pmul) {
3804 pplayer->multipliers[multiplier_index(pmul)].value
3805 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3807
3808 /* Now override with any values from the savefile. */
3809 for (k = 0; k < loading->multiplier.size; k++) {
3810 const struct multiplier *pmul = loading->multiplier.order[k];
3811
3812 if (pmul) {
3814 int val =
3816 "player%d.multiplier%d.val",
3817 player_slot_index(pslot), k);
3818 int rval = (((CLIP(pmul->start, val, pmul->stop)
3819 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3820
3821 if (rval != val) {
3822 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3823 "was %d, clamped to %d", pslot_id,
3824 multiplier_rule_name(pmul), val, rval);
3825 }
3826 pplayer->multipliers[idx].value = rval;
3827
3828 val =
3830 pplayer->multipliers[idx].value,
3831 "player%d.multiplier%d.target",
3832 player_slot_index(pslot), k);
3833 rval = (((CLIP(pmul->start, val, pmul->stop)
3834 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3835
3836 if (rval != val) {
3837 log_verbose("Player %d had illegal value for multiplier_target "
3838 " \"%s\": was %d, clamped to %d", pslot_id,
3839 multiplier_rule_name(pmul), val, rval);
3840 }
3841 pplayer->multipliers[idx].target = rval;
3842
3843 pplayer->multipliers[idx].changed
3845 "player%d.multiplier%d.changed",
3846 player_slot_index(pslot), k);
3847 } /* else silently discard multiplier not in current ruleset */
3848 }
3849
3850 /* Must be loaded before tile owner is set. */
3851 pplayer->server.border_vision =
3853 "player%d.border_vision",
3854 player_slot_index(pslot));
3855
3857 "player%d.autoselect_weight",
3858 pslot_id);
3860
3861 /* check number of players */
3862 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3863 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3864 "(%d) from the loaded game does not match the number of "
3865 "players present (%d).", nplayers, player_count());
3866
3867 /* Load team information. */
3868 players_iterate(pplayer) {
3869 int team;
3870 struct team_slot *tslot = NULL;
3871
3873 "player%d.team_no",
3874 player_number(pplayer))
3876 "Invalid team definition for player %s (nb %d).",
3877 player_name(pplayer), player_number(pplayer));
3878 /* Should never fail when slot given is not nullptr */
3879 team_add_player(pplayer, team_new(tslot));
3881
3882 /* Loading the shuffle list is quite complex. At the time of saving the
3883 * shuffle data is saved as
3884 * shuffled_player_<number> = player_slot_id
3885 * where number is an increasing number and player_slot_id is a number
3886 * between 0 and the maximum number of player slots. Now we have to create
3887 * a list
3888 * shuffler_players[number] = player_slot_id
3889 * where all player slot IDs are used exactly one time. The code below
3890 * handles this ... */
3891 if (secfile_lookup_int_default(loading->file, -1,
3892 "players.shuffled_player_%d", 0) >= 0) {
3893 int slots = player_slot_count();
3894 int plrcount = player_count();
3897
3898 for (i = 0; i < slots; i++) {
3899 /* Array to save used numbers. */
3901 /* List of all player IDs (needed for set_shuffled_players()). It is
3902 * initialised with the value -1 to indicate that no value is set. */
3903 shuffled_players[i] = -1;
3904 }
3905
3906 /* Load shuffled player list. */
3907 for (i = 0; i < plrcount; i++) {
3908 int shuffle
3910 "players.shuffled_player_%d", i);
3911
3912 if (shuffle == -1) {
3913 log_sg("Missing player shuffle information (index %d) "
3914 "- reshuffle player list!", i);
3916 break;
3917 } else if (shuffled_player_set[shuffle]) {
3918 log_sg("Player shuffle %d used two times "
3919 "- reshuffle player list!", shuffle);
3921 break;
3922 }
3923 /* Set this ID as used. */
3925
3926 /* Save the player ID in the shuffle list. */
3928 }
3929
3930 if (shuffle_loaded) {
3931 /* Insert missing numbers. */
3932 int shuffle_index = plrcount;
3933
3934 for (i = 0; i < slots; i++) {
3935 if (!shuffled_player_set[i]) {
3937 }
3938
3939 /* shuffle_index must not grow higher than size of shuffled_players. */
3941 "Invalid player shuffle data!");
3942 }
3943
3944#ifdef FREECIV_DEBUG
3945 log_debug("[load shuffle] player_count() = %d", player_count());
3946 player_slots_iterate(pslot) {
3947 int plrid = player_slot_index(pslot);
3948
3949 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3951 shuffled_player_set[plrid] ? "is used" : "-");
3953#endif /* FREECIV_DEBUG */
3954
3955 /* Set shuffle list from savegame. */
3957 }
3958 }
3959
3960 if (!shuffle_loaded) {
3961 /* No shuffled players included or error loading them, so shuffle them
3962 * (this may include scenarios). */
3964 }
3965}
3966
3967/************************************************************************/
3971{
3972 /* Check status and return if not OK (sg_success FALSE). */
3973 sg_check_ret();
3974
3975 if (game.info.is_new_game) {
3976 /* Nothing to do. */
3977 return;
3978 }
3979
3980 players_iterate(pplayer) {
3981 sg_load_player_main(loading, pplayer);
3983 sg_load_player_units(loading, pplayer);
3985
3986 /* Check the success of the functions above. */
3987 sg_check_ret();
3988
3989 /* Print out some information */
3990 if (is_ai(pplayer)) {
3991 log_normal(_("%s has been added as %s level AI-controlled player "
3992 "(%s)."), player_name(pplayer),
3993 ai_level_translated_name(pplayer->ai_common.skill_level),
3994 ai_name(pplayer->ai));
3995 } else {
3996 log_normal(_("%s has been added as human player."),
3997 player_name(pplayer));
3998 }
4000
4001 /* Also load the transport status of the units here. It must be a special
4002 * case as all units must be known (unit on an allied transporter). */
4003 players_iterate(pplayer) {
4004 /* Load unit transport status. */
4007
4008 /* Savegame may contain nation assignments that are incompatible with the
4009 * current nationset. Ensure they are compatible, one way or another. */
4011
4012 /* Some players may have invalid nations in the ruleset. Once all players
4013 * are loaded, pick one of the remaining nations for them. */
4014 players_iterate(pplayer) {
4015 if (pplayer->nation == NO_NATION_SELECTED) {
4018 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4019 log_sg(_("%s had invalid nation; changing to %s."),
4020 player_name(pplayer), nation_plural_for_player(pplayer));
4021
4022 ai_traits_init(pplayer);
4023 }
4025
4026 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4029 if (pplayers_allied(plr, aplayer)) {
4031 DS_ALLIANCE);
4032
4035 log_sg("Illegal alliance structure detected: "
4036 "%s alliance to %s reduced to peace treaty.",
4041 }
4042 }
4045
4046 /* Update cached city illness. This can depend on trade routes,
4047 * so can't be calculated until all players have been loaded. */
4048 if (game.info.illness_on) {
4050 pcity->server.illness
4052 &(pcity->illness_trade), NULL);
4054 }
4055
4056 /* Update all city information. This must come after all cities are
4057 * loaded (in player_load) but before player (dumb) cities are loaded
4058 * in player_load_vision(). */
4059 players_iterate(plr) {
4060 city_list_iterate(plr->cities, pcity) {
4063 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4066
4067 /* Since the cities must be placed on the map to put them on the
4068 player map we do this afterwards */
4069 players_iterate(pplayer) {
4071 /* Check the success of the function above. */
4072 sg_check_ret();
4074
4075 /* Check shared vision and tiles. */
4076 players_iterate(pplayer) {
4077 BV_CLR_ALL(pplayer->gives_shared_vision);
4078 BV_CLR_ALL(pplayer->gives_shared_tiles);
4079 BV_CLR_ALL(pplayer->server.really_gives_vision);
4081
4082 /* Set up shared vision... */
4083 players_iterate(pplayer) {
4084 int plr1 = player_index(pplayer);
4085
4087 int plr2 = player_index(pplayer2);
4088
4090 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4091 give_shared_vision(pplayer, pplayer2);
4092 }
4094 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4095 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4096 }
4099
4100 /* ...and check it */
4103 /* TODO: Is there a good reason player is not marked as
4104 * giving shared vision to themselves -> really_gives_vision()
4105 * returning FALSE when pplayer1 == pplayer2 */
4106 if (pplayer1 != pplayer2
4109 sg_regr(3000900,
4110 _("%s did not give shared vision to team member %s."),
4113 }
4115 sg_regr(3000900,
4116 _("%s did not give shared vision to team member %s."),
4119 }
4120 }
4123
4126
4127 /* All vision is ready; this calls city_thaw_workers_queue(). */
4129
4130 /* Make sure everything is consistent. */
4131 players_iterate(pplayer) {
4132 unit_list_iterate(pplayer->units, punit) {
4134 struct tile *ptile = unit_tile(punit);
4135
4136 log_sg("%s doing illegal activity in savegame!",
4138 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4142 : "missing",
4143 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4145 }
4148
4151 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4153
4154 /* Player colors are always needed once game has started. Pre-2.4 savegames
4155 * lack them. This cannot be in compatibility conversion layer as we need
4156 * all the player data available to be able to assign best colors. */
4157 if (game_was_started()) {
4159 }
4160}
4161
4162/************************************************************************/
4165static void sg_save_players(struct savedata *saving)
4166{
4167 /* Check status and return if not OK (sg_success FALSE). */
4168 sg_check_ret();
4169
4170 if ((saving->scenario && !saving->save_players)
4171 || !game_was_started()) {
4172 /* Nothing to do for a scenario without saved players or a game in
4173 * INITIAL state. */
4174 return;
4175 }
4176
4177 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4178
4179 /* Save destroyed wonders as bitvector. Note that improvement order
4180 * is saved in 'savefile.improvement.order'. */
4181 {
4182 char destroyed[B_LAST+1];
4183
4184 improvement_iterate(pimprove) {
4185 if (is_great_wonder(pimprove)
4186 && great_wonder_is_destroyed(pimprove)) {
4187 destroyed[improvement_index(pimprove)] = '1';
4188 } else {
4189 destroyed[improvement_index(pimprove)] = '0';
4190 }
4192 destroyed[improvement_count()] = '\0';
4194 "players.destroyed_wonders");
4195 }
4196
4197 secfile_insert_int(saving->file, server.identity_number,
4198 "players.identity_number_used");
4199
4200 /* Save player order. */
4201 {
4202 int i = 0;
4203 shuffled_players_iterate(pplayer) {
4204 secfile_insert_int(saving->file, player_number(pplayer),
4205 "players.shuffled_player_%d", i);
4206 i++;
4208 }
4209
4210 /* Sort units. */
4212
4213 /* Save players. */
4214 players_iterate(pplayer) {
4215 sg_save_player_main(saving, pplayer);
4216 sg_save_player_cities(saving, pplayer);
4217 sg_save_player_units(saving, pplayer);
4219 sg_save_player_vision(saving, pplayer);
4221}
4222
4223/************************************************************************/
4227 struct player *plr)
4228{
4229 const char **slist;
4230 int i, plrno = player_number(plr);
4231 const char *str;
4232 struct government *gov;
4233 const char *level;
4234 const char *barb_str;
4235 size_t nval;
4236 const char *kind;
4237
4238 /* Check status and return if not OK (sg_success FALSE). */
4239 sg_check_ret();
4240
4241 /* Basic player data. */
4242 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4243 sg_failure_ret(str != NULL, "%s", secfile_error());
4245 sz_strlcpy(plr->username,
4247 "player%d.username", plrno));
4249 "player%d.unassigned_user", plrno),
4250 "%s", secfile_error());
4253 "player%d.orig_username", plrno));
4256 "player%d.ranked_username",
4257 plrno));
4259 "player%d.unassigned_ranked", plrno),
4260 "%s", secfile_error());
4262 "player%d.delegation_username",
4263 plrno);
4264 /* Defaults to no delegation. */
4265 if (strlen(str)) {
4267 }
4268
4269 /* Player flags */
4270 BV_CLR_ALL(plr->flags);
4271 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4272 for (i = 0; i < nval; i++) {
4273 const char *sval = slist[i];
4275
4276 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4277
4278 BV_SET(plr->flags, fid);
4279 }
4280 free(slist);
4281
4282 /* Nation */
4283 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4285 if (plr->nation != NULL) {
4286 ai_traits_init(plr);
4287 }
4288
4289 /* Government */
4290 str = secfile_lookup_str(loading->file, "player%d.government_name",
4291 plrno);
4293 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4294 plrno, str);
4295 plr->government = gov;
4296
4297 /* Target government */
4299 "player%d.target_government_name", plrno);
4300 if (str != NULL) {
4302 } else {
4303 plr->target_government = NULL;
4304 }
4307 "player%d.revolution_finishes", plrno);
4308
4309 /* Load diplomatic data (diplstate + embassy + vision).
4310 * Shared vision is loaded in sg_load_players(). */
4312 players_iterate(pplayer) {
4313 char buf[32];
4314 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4315 i = player_index(pplayer);
4316
4317 /* Load diplomatic status */
4318 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4319
4320 ds->type =
4322 diplstate_type, "%s.current", buf);
4323 ds->max_state =
4325 diplstate_type, "%s.closest", buf);
4326
4327 /* FIXME: If either party is barbarian, we cannot enforce below check */
4328#if 0
4329 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4330 sg_regr(3020000,
4331 "Player%d: War with player %d who has never been met. "
4332 "Reverted to No Contact state.", plrno, i);
4333 ds->type = DS_NO_CONTACT;
4334 }
4335#endif
4336
4337 if (valid_dst_closest(ds) != ds->max_state) {
4338 sg_regr(3020000,
4339 "Player%d: closest diplstate to player %d less than current. "
4340 "Updated.", plrno, i);
4341 ds->max_state = ds->type;
4342 }
4343
4344 ds->first_contact_turn =
4346 "%s.first_contact_turn", buf);
4347 ds->turns_left =
4348 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4349 ds->has_reason_to_cancel =
4351 "%s.has_reason_to_cancel", buf);
4352 ds->contact_turns_left =
4354 "%s.contact_turns_left", buf);
4355
4356 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4357 buf)) {
4358 BV_SET(plr->real_embassy, i);
4359 }
4360 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4361 * must be known. */
4363
4364 /* load ai data */
4366 char buf[32];
4367
4368 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4370
4372 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4373 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4375
4377 "player%d.adv.wonder_city",
4378 plrno);
4379
4380 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4381
4382 /* Some sane defaults */
4383 plr->ai_common.fuzzy = 0;
4384 plr->ai_common.expand = 100;
4385 plr->ai_common.science_cost = 100;
4386
4387
4389 "player%d.ai.level", plrno);
4390 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4391 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4393 } else {
4395 }
4396
4398 log_sg("Player%d: Invalid AI level \"%s\". "
4399 "Changed to \"%s\".", plrno, level,
4402 }
4403
4405 "player%d.ai.barb_type", plrno);
4407
4409 log_sg("Player%d: Invalid barbarian type \"%s\". "
4410 "Changed to \"None\".", plrno, barb_str);
4412 }
4413
4414 if (is_barbarian(plr)) {
4415 server.nbarbarians++;
4416 }
4417
4418 if (is_ai(plr)) {
4420 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4421 }
4422
4423 /* Load nation style. */
4424 {
4425 struct nation_style *style;
4426
4427 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4428
4429 sg_failure_ret(str != NULL, "%s", secfile_error());
4430 style = style_by_rule_name(str);
4431 if (style == NULL) {
4432 style = style_by_number(0);
4433 log_sg("Player%d: unsupported city_style_name \"%s\". "
4434 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4435 }
4436 plr->style = style;
4437 }
4438
4440 "player%d.idle_turns", plrno),
4441 "%s", secfile_error());
4442 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4443 if (sex_by_name(kind) == SEX_MALE) {
4444 plr->is_male = TRUE;
4445 } else {
4446 plr->is_male = FALSE;
4447 }
4449 "player%d.is_alive", plrno),
4450 "%s", secfile_error());
4452 "player%d.turns_alive", plrno),
4453 "%s", secfile_error());
4455 "player%d.last_war", plrno),
4456 "%s", secfile_error());
4458 "player%d.phase_done", plrno);
4460 "player%d.gold", plrno),
4461 "%s", secfile_error());
4463 "player%d.rates.tax", plrno),
4464 "%s", secfile_error());
4466 "player%d.rates.science", plrno),
4467 "%s", secfile_error());
4469 "player%d.rates.luxury", plrno),
4470 "%s", secfile_error());
4472 "player%d.infrapts",
4473 plrno);
4474 plr->server.bulbs_last_turn =
4476 "player%d.research.bulbs_last_turn", plrno);
4477
4478 /* Traits */
4479 if (plr->nation) {
4480 for (i = 0; i < loading->trait.size; i++) {
4481 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4482
4483 if (trait_is_valid(tr)) {
4484 int val;
4485
4486 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4487 plrno, i),
4488 "%s", secfile_error());
4489 plr->ai_common.traits[tr].val = val;
4490
4492 "player%d.trait%d.mod", plrno, i),
4493 "%s", secfile_error());
4494 plr->ai_common.traits[tr].mod = val;
4495 }
4496 }
4497 }
4498
4499 /* Achievements */
4500 {
4501 int count;
4502
4503 count = secfile_lookup_int_default(loading->file, -1,
4504 "player%d.achievement_count", plrno);
4505
4506 if (count > 0) {
4507 for (i = 0; i < count; i++) {
4508 const char *name;
4509 struct achievement *pach;
4510 bool first;
4511
4513 "player%d.achievement%d.name", plrno, i);
4515
4517 "Unknown achievement \"%s\".", name);
4518
4520 "player%d.achievement%d.first",
4521 plrno, i),
4522 "achievement error: %s", secfile_error());
4523
4524 sg_failure_ret(pach->first == NULL || !first,
4525 "Multiple players listed as first to get achievement \"%s\".",
4526 name);
4527
4528 BV_SET(pach->achievers, player_index(plr));
4529
4530 if (first) {
4531 pach->first = plr;
4532 }
4533 }
4534 }
4535 }
4536
4537 /* Player score. */
4538 plr->score.happy =
4540 "score%d.happy", plrno);
4541 plr->score.content =
4543 "score%d.content", plrno);
4544 plr->score.unhappy =
4546 "score%d.unhappy", plrno);
4547 plr->score.angry =
4549 "score%d.angry", plrno);
4550
4551 /* Make sure that the score about specialists in current ruleset that
4552 * were not present at saving time are set to zero. */
4554 plr->score.specialists[sp] = 0;
4556
4557 for (i = 0; i < loading->specialist.size; i++) {
4558 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4560 "score%d.specialists%d", plrno, i);
4561 }
4562
4563 plr->score.wonders =
4565 "score%d.wonders", plrno);
4566 plr->score.techs =
4568 "score%d.techs", plrno);
4569 plr->score.techout =
4571 "score%d.techout", plrno);
4572 plr->score.landarea =
4574 "score%d.landarea", plrno);
4575 plr->score.settledarea =
4577 "score%d.settledarea", plrno);
4578 plr->score.population =
4580 "score%d.population", plrno);
4581 plr->score.cities =
4583 "score%d.cities", plrno);
4584 plr->score.units =
4586 "score%d.units", plrno);
4587 plr->score.pollution =
4589 "score%d.pollution", plrno);
4590 plr->score.literacy =
4592 "score%d.literacy", plrno);
4593 plr->score.bnp =
4595 "score%d.bnp", plrno);
4596 plr->score.mfg =
4598 "score%d.mfg", plrno);
4599 plr->score.spaceship =
4601 "score%d.spaceship", plrno);
4602 plr->score.units_built =
4604 "score%d.units_built", plrno);
4605 plr->score.units_killed =
4607 "score%d.units_killed", plrno);
4608 plr->score.units_lost =
4610 "score%d.units_lost", plrno);
4611 plr->score.units_used =
4613 "score%d.units_used", plrno);
4614 plr->score.culture =
4616 "score%d.culture", plrno);
4617 plr->score.game =
4619 "score%d.total", plrno);
4620
4621 /* Load space ship data. */
4622 {
4623 struct player_spaceship *ship = &plr->spaceship;
4624 char prefix[32];
4625 const char *st;
4626 int ei;
4627
4628 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4631 &ei,
4632 "%s.state", prefix),
4633 "%s", secfile_error());
4634 ship->state = ei;
4635
4636 if (ship->state != SSHIP_NONE) {
4637 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4638 "%s.structurals", prefix),
4639 "%s", secfile_error());
4640 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4641 "%s.components", prefix),
4642 "%s", secfile_error());
4644 "%s.modules", prefix),
4645 "%s", secfile_error());
4647 "%s.fuel", prefix),
4648 "%s", secfile_error());
4649 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4650 "%s.propulsion", prefix),
4651 "%s", secfile_error());
4652 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4653 "%s.habitation", prefix),
4654 "%s", secfile_error());
4655 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4656 "%s.life_support", prefix),
4657 "%s", secfile_error());
4658 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4659 "%s.solar_panels", prefix),
4660 "%s", secfile_error());
4661
4662 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4663 sg_failure_ret(st != NULL, "%s", secfile_error())
4664 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4665 sg_failure_ret(st[i] == '1' || st[i] == '0',
4666 "Undefined value '%c' within '%s.structure'.", st[i],
4667 prefix)
4668
4669 if (!(st[i] == '0')) {
4670 BV_SET(ship->structure, i);
4671 }
4672 }
4673 if (ship->state >= SSHIP_LAUNCHED) {
4674 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4675 "%s.launch_year", prefix),
4676 "%s", secfile_error());
4677 }
4679 }
4680 }
4681
4682 /* Load lost wonder data. */
4683 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4684 /* If not present, probably an old savegame; nothing to be done */
4685 if (str != NULL) {
4686 int k;
4687
4688 sg_failure_ret(strlen(str) == loading->improvement.size,
4689 "Invalid length for 'player%d.lost_wonders' ("
4690 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4691 plrno, strlen(str), loading->improvement.size);
4692 for (k = 0; k < loading->improvement.size; k++) {
4693 sg_failure_ret(str[k] == '1' || str[k] == '0',
4694 "Undefined value '%c' within "
4695 "'player%d.lost_wonders'.", plrno, str[k]);
4696
4697 if (str[k] == '1') {
4698 struct impr_type *pimprove =
4699 improvement_by_rule_name(loading->improvement.order[k]);
4700 if (pimprove) {
4701 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4702 }
4703 }
4704 }
4705 }
4706
4707 plr->history =
4708 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4709 plr->server.huts =
4710 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4711}
4712
4713/************************************************************************/
4717 struct player *plr)
4718{
4719 int i, k, plrno = player_number(plr);
4720 struct player_spaceship *ship = &plr->spaceship;
4721 const char *flag_names[PLRF_COUNT];
4722 int set_count;
4723
4724 /* Check status and return if not OK (sg_success FALSE). */
4725 sg_check_ret();
4726
4727 set_count = 0;
4728 for (i = 0; i < PLRF_COUNT; i++) {
4729 if (player_has_flag(plr, i)) {
4731 }
4732 }
4733
4735 "player%d.flags", plrno);
4736
4737 secfile_insert_str(saving->file, ai_name(plr->ai),
4738 "player%d.ai_type", plrno);
4740 "player%d.name", plrno);
4742 "player%d.username", plrno);
4744 "player%d.unassigned_user", plrno);
4745 if (plr->rgb != NULL) {
4746 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4747 } else {
4748 /* Colorless players are ok in pregame */
4749 if (game_was_started()) {
4750 log_sg("Game has started, yet player %d has no color defined.", plrno);
4751 }
4752 }
4754 "player%d.ranked_username", plrno);
4756 "player%d.unassigned_ranked", plrno);
4758 "player%d.orig_username", plrno);
4761 : "",
4762 "player%d.delegation_username", plrno);
4764 "player%d.nation", plrno);
4765 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4766 "player%d.team_no", plrno);
4767
4770 "player%d.government_name", plrno);
4771
4772 if (plr->target_government) {
4775 "player%d.target_government_name", plrno);
4776 }
4777
4779 "player%d.style_by_name", plrno);
4780
4782 "player%d.idle_turns", plrno);
4783 if (plr->is_male) {
4785 "player%d.kind", plrno);
4786 } else {
4788 "player%d.kind", plrno);
4789 }
4791 "player%d.is_alive", plrno);
4793 "player%d.turns_alive", plrno);
4795 "player%d.last_war", plrno);
4797 "player%d.phase_done", plrno);
4798
4799 players_iterate(pplayer) {
4800 char buf[32];
4801 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4802
4803 i = player_index(pplayer);
4804
4805 /* save diplomatic state */
4806 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4807
4808 secfile_insert_enum(saving->file, ds->type,
4809 diplstate_type, "%s.current", buf);
4810 secfile_insert_enum(saving->file, ds->max_state,
4811 diplstate_type, "%s.closest", buf);
4812 secfile_insert_int(saving->file, ds->first_contact_turn,
4813 "%s.first_contact_turn", buf);
4814 secfile_insert_int(saving->file, ds->turns_left,
4815 "%s.turns_left", buf);
4816 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4817 "%s.has_reason_to_cancel", buf);
4818 secfile_insert_int(saving->file, ds->contact_turns_left,
4819 "%s.contact_turns_left", buf);
4821 "%s.embassy", buf);
4822 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4823 "%s.gives_shared_vision", buf);
4824 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4825 "%s.gives_shared_tiles", buf);
4827
4830 /* save ai data */
4832 "player%d.ai%d.love", plrno, i);
4833 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4835
4837 "player%d.adv.wonder_city", plrno);
4838
4839 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4840
4841 /* Multipliers (policies) */
4842 i = multiplier_count();
4843
4844 for (k = 0; k < i; k++) {
4846 "player%d.multiplier%d.val", plrno, k);
4848 "player%d.multiplier%d.target", plrno, k);
4850 "player%d.multiplier%d.changed", plrno, k);
4851 }
4852
4854 "player%d.ai.level", plrno);
4856 "player%d.ai.barb_type", plrno);
4858 "player%d.gold", plrno);
4860 "player%d.rates.tax", plrno);
4862 "player%d.rates.science", plrno);
4864 "player%d.rates.luxury", plrno);
4866 "player%d.infrapts", plrno);
4868 "player%d.research.bulbs_last_turn", plrno);
4869
4870 /* Save traits */
4871 {
4872 enum trait tr;
4873 int j;
4874
4875 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4877 "player%d.trait%d.val", plrno, j);
4879 "player%d.trait%d.mod", plrno, j);
4880 }
4881 }
4882
4883 /* Save achievements */
4884 {
4885 int j = 0;
4886
4888 if (achievement_player_has(pach, plr)) {
4890 "player%d.achievement%d.name", plrno, j);
4891 if (pach->first == plr) {
4893 "player%d.achievement%d.first", plrno, j);
4894 } else {
4896 "player%d.achievement%d.first", plrno, j);
4897 }
4898
4899 j++;
4900 }
4902
4903 secfile_insert_int(saving->file, j,
4904 "player%d.achievement_count", plrno);
4905 }
4906
4908 "player%d.revolution_finishes", plrno);
4909
4910 /* Player score */
4912 "score%d.happy", plrno);
4914 "score%d.content", plrno);
4916 "score%d.unhappy", plrno);
4918 "score%d.angry", plrno);
4921 "score%d.specialists%d", plrno, sp);
4924 "score%d.wonders", plrno);
4926 "score%d.techs", plrno);
4928 "score%d.techout", plrno);
4930 "score%d.landarea", plrno);
4932 "score%d.settledarea", plrno);
4934 "score%d.population", plrno);
4936 "score%d.cities", plrno);
4938 "score%d.units", plrno);
4940 "score%d.pollution", plrno);
4942 "score%d.literacy", plrno);
4943 secfile_insert_int(saving->file, plr->score.bnp,
4944 "score%d.bnp", plrno);
4945 secfile_insert_int(saving->file, plr->score.mfg,
4946 "score%d.mfg", plrno);
4948 "score%d.spaceship", plrno);
4950 "score%d.units_built", plrno);
4952 "score%d.units_killed", plrno);
4954 "score%d.units_lost", plrno);
4956 "score%d.units_used", plrno);
4958 "score%d.culture", plrno);
4959 secfile_insert_int(saving->file, plr->score.game,
4960 "score%d.total", plrno);
4961
4962 /* Save space ship status. */
4963 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4964 plrno);
4965 if (ship->state != SSHIP_NONE) {
4966 char buf[32];
4967 char st[NUM_SS_STRUCTURALS+1];
4968 int ssi;
4969
4970 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4971
4972 secfile_insert_int(saving->file, ship->structurals,
4973 "%s.structurals", buf);
4974 secfile_insert_int(saving->file, ship->components,
4975 "%s.components", buf);
4976 secfile_insert_int(saving->file, ship->modules,
4977 "%s.modules", buf);
4978 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4979 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4980 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4981 secfile_insert_int(saving->file, ship->life_support,
4982 "%s.life_support", buf);
4983 secfile_insert_int(saving->file, ship->solar_panels,
4984 "%s.solar_panels", buf);
4985
4986 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4987 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4988 }
4989 st[ssi] = '\0';
4990 secfile_insert_str(saving->file, st, "%s.structure", buf);
4991 if (ship->state >= SSHIP_LAUNCHED) {
4992 secfile_insert_int(saving->file, ship->launch_year,
4993 "%s.launch_year", buf);
4994 }
4995 }
4996
4997 /* Save lost wonders info. */
4998 {
4999 char lost[B_LAST+1];
5000
5001 improvement_iterate(pimprove) {
5002 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5003 lost[improvement_index(pimprove)] = '1';
5004 } else {
5005 lost[improvement_index(pimprove)] = '0';
5006 }
5008 lost[improvement_count()] = '\0';
5010 "player%d.lost_wonders", plrno);
5011 }
5012
5013 secfile_insert_int(saving->file, plr->history,
5014 "player%d.history", plrno);
5016 "player%d.hut_count", plrno);
5017
5019 "player%d.border_vision", plrno);
5020
5021 if (saving->scenario) {
5022 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5023 int def = 1; /* We want users to get a player in a scenario */
5024
5026 /* This isn't usable player */
5027 def = 0;
5028 }
5029
5030 secfile_insert_int(saving->file, def,
5031 "player%d.autoselect_weight", plrno);
5032 } else {
5034 "player%d.autoselect_weight", plrno);
5035 }
5036 }
5037}
5038
5039/************************************************************************/
5043 struct player *plr)
5044{
5045 int ncities, i, plrno = player_number(plr);
5046 bool tasks_handled;
5048
5049 /* Check status and return if not OK (sg_success FALSE). */
5050 sg_check_ret();
5051
5053 "player%d.ncities", plrno),
5054 "%s", secfile_error());
5055
5056 if (!plr->is_alive && ncities > 0) {
5057 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5058 ncities = 0;
5059 }
5060
5062 "player%d.wl_max_length",
5063 plrno);
5065 "player%d.routes_max_length", plrno);
5066
5067 /* Load all cities of the player. */
5068 for (i = 0; i < ncities; i++) {
5069 char buf[32];
5070 struct city *pcity;
5071
5072 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5073
5074 /* Create a dummy city. */
5081 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5082 }
5083
5086
5087 /* Load the information about the nationality of citizens. This is done
5088 * here because the city sanity check called by citizens_update() requires
5089 * that the city is registered. */
5091
5092 /* After everything is loaded, but before vision. */
5094
5095 /* adding the city contribution to fog-of-war */
5099
5101 }
5102
5104 for (i = 0; !tasks_handled; i++) {
5105 int city_id;
5106 struct city *pcity = NULL;
5107
5108 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5109 plrno, i);
5110
5111 if (city_id != -1) {
5112 pcity = player_city_by_number(plr, city_id);
5113 }
5114
5115 if (pcity != NULL) {
5116 const char *str;
5117 int nat_x, nat_y;
5118 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5119
5120 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5121 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5122
5123 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5124
5125 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5127
5129 "Unknown workertask activity %s", str);
5130
5131 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5132
5133 if (strcmp("-", str)) {
5135
5136 sg_failure_ret(ptask->tgt != NULL,
5137 "Unknown workertask target %s", str);
5138 } else {
5139 ptask->tgt = NULL;
5140
5141 if (ptask->act == ACTIVITY_IRRIGATE) {
5143 } else if (ptask->act == ACTIVITY_MINE) {
5144 ptask->act = ACTIVITY_MINE;
5145 }
5146 }
5147
5148 ptask->want = secfile_lookup_int_default(loading->file, 1,
5149 "player%d.task%d.want", plrno, i);
5150
5151 worker_task_list_append(pcity->task_reqs, ptask);
5152 } else {
5154 }
5155 }
5156}
5157
5158/************************************************************************/
5161static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5162 struct city *pcity, const char *citystr,
5164{
5165 struct player *past;
5166 const char *kind, *name, *str;
5167 int id, i, repair, sp_count = 0, workers = 0, value;
5168 int nat_x, nat_y;
5169 citizens size;
5170 const char *stylename;
5171 int partner;
5172 int want;
5173 int tmp_int;
5174 const struct civ_map *nmap = &(wld.map);
5175
5177 FALSE, "%s", secfile_error());
5179 FALSE, "%s", secfile_error());
5182 "%s has invalid center tile (%d, %d)",
5183 citystr, nat_x, nat_y);
5185 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5186
5187 /* Instead of dying, use 'citystr' string for damaged name. */
5189 "%s.name", citystr));
5190
5192 citystr), FALSE, "%s", secfile_error());
5193
5195 "%s.original", citystr);
5196 past = player_by_number(id);
5197 if (NULL != past) {
5198 pcity->original = past;
5199 }
5200
5201 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5202 citystr), FALSE, "%s", secfile_error());
5203 size = (citizens)value; /* set the correct type */
5204 sg_warn_ret_val(value == (int)size, FALSE,
5205 "Invalid city size: %d, set to %d", value, size);
5207
5208 for (i = 0; i < loading->specialist.size; i++) {
5209 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5210 citystr, i),
5211 FALSE, "%s", secfile_error());
5212 pcity->specialists[specialist_index(loading->specialist.order[i])]
5213 = (citizens)value;
5214 sp_count += value;
5215 }
5216
5217 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5218 for (i = 0; partner != 0; i++) {
5219 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5220 const char *dir;
5221 const char *good_str;
5222
5223 /* Append to routes list immediately, so the pointer can be found for freeing
5224 * even if we abort */
5226
5227 proute->partner = partner;
5228 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5230 "No traderoute direction found for %s", citystr);
5233 "Illegal route direction %s", dir);
5234 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5236 "No good found for %s", citystr);
5238 sg_warn_ret_val(proute->goods != NULL, FALSE,
5239 "Illegal good %s", good_str);
5240
5241 /* Next one */
5243 "%s.traderoute%d", citystr, i + 1);
5244 }
5245
5246 for (; i < routes_max; i++) {
5247 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5248 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5249 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5250 }
5251
5252 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5253 "%s.food_stock", citystr),
5254 FALSE, "%s", secfile_error());
5255 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5256 "%s.shield_stock", citystr),
5257 FALSE, "%s", secfile_error());
5258 pcity->history =
5259 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5260
5261 pcity->airlift =
5262 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5263 pcity->was_happy =
5264 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5265 citystr);
5266 pcity->had_famine =
5267 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5268 citystr);
5269
5270 pcity->turn_plague =
5271 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5272
5274 "%s.anarchy", citystr),
5275 FALSE, "%s", secfile_error());
5276 pcity->rapture =
5277 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5278 pcity->steal =
5279 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5280
5281 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5282 "%s.turn_founded", citystr),
5283 FALSE, "%s", secfile_error());
5285 "%s.acquire_t", citystr),
5286 FALSE, "%s", secfile_error());
5287 pcity->acquire_t = tmp_int;
5288 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5289 citystr), FALSE, "%s", secfile_error());
5290 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5291 citystr), FALSE, "%s", secfile_error());
5292
5293 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5294 "%s.turn_last_built", citystr),
5295 FALSE, "%s", secfile_error());
5296
5297 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5298 citystr);
5299 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5300 citystr);
5301 pcity->production = universal_by_rule_name(kind, name);
5302 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5303 "%s.currently_building: unknown \"%s\" \"%s\".",
5304 citystr, kind, name);
5305
5306 want = secfile_lookup_int_default(loading->file, 0,
5307 "%s.current_want", citystr);
5308 if (pcity->production.kind == VUT_IMPROVEMENT) {
5309 pcity->server.adv->
5310 building_want[improvement_index(pcity->production.value.building)]
5311 = want;
5312 }
5313
5314 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5315 citystr);
5316 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5317 citystr);
5320 "%s.changed_from: unknown \"%s\" \"%s\".",
5321 citystr, kind, name);
5322
5323 pcity->before_change_shields =
5324 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5325 "%s.before_change_shields", citystr);
5326 pcity->caravan_shields =
5328 "%s.caravan_shields", citystr);
5329 pcity->disbanded_shields =
5331 "%s.disbanded_shields", citystr);
5332 pcity->last_turns_shield_surplus =
5334 "%s.last_turns_shield_surplus",
5335 citystr);
5336
5338 "%s.style", citystr);
5339 if (stylename != NULL) {
5341 } else {
5342 pcity->style = 0;
5343 }
5344 if (pcity->style < 0) {
5345 pcity->style = city_style(pcity);
5346 }
5347
5348 pcity->server.synced = FALSE; /* Must re-sync with clients */
5349
5350 /* Initialise list of city improvements. */
5351 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5352 pcity->built[i].turn = I_NEVER;
5353 }
5354
5355 /* Load city improvements. */
5356 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5358 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5359 "Invalid length of '%s.improvements' ("
5360 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5361 citystr, strlen(str), loading->improvement.size);
5362 for (i = 0; i < loading->improvement.size; i++) {
5363 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5364 "Undefined value '%c' within '%s.improvements'.",
5365 str[i], citystr)
5366
5367 if (str[i] == '1') {
5368 struct impr_type *pimprove
5369 = improvement_by_rule_name(loading->improvement.order[i]);
5370
5371 if (pimprove) {
5372 city_add_improvement(pcity, pimprove);
5373 }
5374 }
5375 }
5376
5377 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5378 "No worked tiles map defined.");
5379
5381
5382 /* Load new savegame with variable (squared) city radius and worked
5383 * tiles map */
5384
5385 int radius_sq
5386 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5387 citystr);
5388 city_map_radius_sq_set(pcity, radius_sq);
5389
5391 if (loading->worked_tiles[ptile->index] == pcity->id) {
5392 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5393 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5394 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5395 TILE_XY(pcity->tile), TILE_XY(ptile));
5396 pcity->specialists[DEFAULT_SPECIALIST]++;
5397 sp_count++;
5398 } else {
5399 tile_set_worked(ptile, pcity);
5400 workers++;
5401 }
5402
5403#ifdef FREECIV_DEBUG
5404 /* Set this tile to unused; a check for not reset tiles is
5405 * included in game_load_internal() */
5406 loading->worked_tiles[ptile->index] = -1;
5407#endif /* FREECIV_DEBUG */
5408 }
5410
5411 if (tile_worked(city_tile(pcity)) != pcity) {
5412 struct city *pwork = tile_worked(city_tile(pcity));
5413
5414 if (NULL != pwork) {
5415 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5416 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5419
5420 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5421 pwork->specialists[DEFAULT_SPECIALIST]++;
5423 } else {
5424 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5427 }
5428
5429 /* Repair pcity */
5432 }
5433
5435 if (0 != repair) {
5436 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5437 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5439 workers, FREE_WORKED_TILES, sp_count);
5440
5441 /* Repair pcity */
5443 }
5444
5445 /* worklist_init() done in create_city_virtual() */
5446 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5447
5448 /* Load city options. */
5449 BV_CLR_ALL(pcity->city_options);
5450 for (i = 0; i < loading->coptions.size; i++) {
5451 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5452 citystr, i)) {
5453 BV_SET(pcity->city_options, loading->coptions.order[i]);
5454 }
5455 }
5457 "%s.wlcb", citystr),
5458 FALSE, "%s", secfile_error());
5459 pcity->wlcb = tmp_int;
5460
5461 /* Load the city rally point. */
5462 {
5463 int len = secfile_lookup_int_default(loading->file, 0,
5464 "%s.rally_point_length", citystr);
5465 int unconverted;
5466
5467 pcity->rally_point.length = len;
5468 if (len > 0) {
5470
5471 pcity->rally_point.orders
5472 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5473 pcity->rally_point.persistent
5475 "%s.rally_point_persistent", citystr);
5476 pcity->rally_point.vigilant
5478 "%s.rally_point_vigilant", citystr);
5479
5482 "%s.rally_point_orders", citystr);
5485 "%s.rally_point_dirs", citystr);
5488 "%s.rally_point_activities", citystr);
5489
5490 for (i = 0; i < len; i++) {
5491 struct unit_order *order = &pcity->rally_point.orders[i];
5492
5493 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5494 || rally_activities[i] == '\0') {
5495 log_sg("Invalid rally point.");
5496 free(pcity->rally_point.orders);
5497 pcity->rally_point.orders = NULL;
5498 pcity->rally_point.length = 0;
5499 break;
5500 }
5501 order->order = char2order(rally_orders[i]);
5502 order->dir = char2dir(rally_dirs[i]);
5503 order->activity = char2activity(rally_activities[i]);
5504
5506 "%s.rally_point_action_vec,%d",
5507 citystr, i);
5508
5509 if (unconverted == -1) {
5510 order->action = ACTION_NONE;
5511 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5512 /* Look up what action id the unconverted number represents. */
5513 order->action = loading->action.order[unconverted];
5514 } else {
5515 if (order->order == ORDER_PERFORM_ACTION) {
5516 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5517 pcity->id);
5518 }
5519
5520 order->action = ACTION_NONE;
5521 }
5522
5523 order->target
5525 "%s.rally_point_tgt_vec,%d",
5526 citystr, i);
5527 order->sub_target
5529 "%s.rally_point_sub_tgt_vec,%d",
5530 citystr, i);
5531 }
5532 } else {
5533 pcity->rally_point.orders = NULL;
5534
5535 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5536 citystr);
5537 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5538 citystr);
5539 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5540 citystr);
5541 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5542 citystr);
5543 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5544 citystr);
5545 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5546 citystr);
5548 "%s.rally_point_tgt_vec", citystr);
5550 "%s.rally_point_sub_tgt_vec", citystr);
5551 }
5552 }
5553
5554 /* Load the city manager parameters. */
5555 {
5556 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5557 "%s.cma_enabled", citystr);
5558 if (enabled) {
5559 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5560
5561 for (i = 0; i < O_LAST; i++) {
5563 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5565 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5566 }
5567
5569 loading->file, FALSE, "%s.max_growth", citystr);
5571 loading->file, FALSE, "%s.require_happy", citystr);
5573 loading->file, FALSE, "%s.allow_disorder", citystr);
5575 loading->file, FALSE, "%s.allow_specialists", citystr);
5577 loading->file, 0, "%s.happy_factor", citystr);
5578 pcity->cm_parameter = param;
5579 } else {
5580 pcity->cm_parameter = NULL;
5581
5582 for (i = 0; i < O_LAST; i++) {
5584 "%s.cma_minimal_surplus,%d", citystr, i);
5586 "%s.cma_factor,%d", citystr, i);
5587 }
5588
5589 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5590 citystr);
5591 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5592 citystr);
5593 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5594 citystr);
5595 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5596 citystr);
5597 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5598 citystr);
5599 }
5600 }
5601
5602 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5603
5604 return TRUE;
5605}
5606
5607/************************************************************************/
5611 struct player *plr,
5612 struct city *pcity,
5613 const char *citystr)
5614{
5616 citizens size;
5617
5619 player_slots_iterate(pslot) {
5620 int nationality;
5621
5622 nationality = secfile_lookup_int_default(loading->file, -1,
5623 "%s.citizen%d", citystr,
5624 player_slot_index(pslot));
5625 if (nationality > 0 && !player_slot_is_used(pslot)) {
5626 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5628 continue;
5629 }
5630
5631 if (nationality != -1 && player_slot_is_used(pslot)) {
5632 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5633 "Invalid value for citizens of player %d in %s: %d.",
5634 player_slot_index(pslot), city_name_get(pcity), nationality);
5635 citizens_nation_set(pcity, pslot, nationality);
5636 }
5638 /* Sanity check. */
5640 if (size != city_size_get(pcity)) {
5641 if (size != 0) {
5642 /* size == 0 can be result from the fact that ruleset had no
5643 * nationality enabled at saving time, so no citizens at all
5644 * were saved. But something more serious must be going on if
5645 * citizens have been saved partially - if some of them are there. */
5646 log_sg("City size and number of citizens does not match in %s "
5647 "(%d != %d)! Repairing ...", city_name_get(pcity),
5649 }
5651 }
5652 }
5653}
5654
5655/************************************************************************/
5659 struct player *plr)
5660{
5662 int i = 0;
5663 int plrno = player_number(plr);
5665
5666 /* Check status and return if not OK (sg_success FALSE). */
5667 sg_check_ret();
5668
5670 "player%d.ncities", plrno);
5671
5673 /* Initialise the nation list for the citizens information. */
5674 player_slots_iterate(pslot) {
5677 }
5678
5679 /* First determine length of longest worklist, rally point order, and the
5680 * nationalities we have. */
5682 int routes;
5683
5684 /* Check the sanity of the city. */
5687
5688 if (pcity->worklist.length > wlist_max_length) {
5689 wlist_max_length = pcity->worklist.length;
5690 }
5691
5692 if (pcity->rally_point.length > rally_point_max_length) {
5693 rally_point_max_length = pcity->rally_point.length;
5694 }
5695
5696 routes = city_num_trade_routes(pcity);
5697 if (routes > routes_max) {
5698 routes_max = routes;
5699 }
5700
5702 /* Find all nations of the citizens,*/
5703 players_iterate(pplayer) {
5704 if (!nations[player_index(pplayer)]
5705 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5706 nations[player_index(pplayer)] = TRUE;
5707 }
5709 }
5711
5713 "player%d.wl_max_length", plrno);
5715 "player%d.routes_max_length", plrno);
5716
5718 struct tile *pcenter = city_tile(pcity);
5719 char impr_buf[B_LAST + 1];
5720 char buf[32];
5721 int j, nat_x, nat_y;
5722
5723 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5724
5725
5727 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5728 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5729
5730 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5731
5732 if (pcity->original != NULL) {
5733 secfile_insert_int(saving->file, player_number(pcity->original),
5734 "%s.original", buf);
5735 } else {
5736 secfile_insert_int(saving->file, -1, "%s.original", buf);
5737 }
5738 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5739
5740 j = 0;
5742 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5743 buf, j++);
5745
5746 j = 0;
5748 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5749 buf, j);
5751 "%s.route_direction%d", buf, j);
5753 "%s.route_good%d", buf, j);
5754 j++;
5756
5757 /* Save dummy values to keep tabular format happy */
5758 for (; j < routes_max; j++) {
5759 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5761 "%s.route_direction%d", buf, j);
5763 "%s.route_good%d", buf, j);
5764 }
5765
5766 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5767 buf);
5768 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5769 buf);
5770 secfile_insert_int(saving->file, pcity->history, "%s.history",
5771 buf);
5772
5773 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5774 buf);
5775 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5776 buf);
5777 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5778 buf);
5779 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5780 buf);
5781
5782 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5783 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5784 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5785 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5786 buf);
5787 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5788 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5789 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5790 secfile_insert_int(saving->file, pcity->turn_last_built,
5791 "%s.turn_last_built", buf);
5792
5793 /* For visual debugging, variable length strings together here */
5794 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5795
5797 "%s.currently_building_kind", buf);
5799 "%s.currently_building_name", buf);
5800
5801 if (pcity->production.kind == VUT_IMPROVEMENT) {
5803 pcity->server.adv->
5804 building_want[improvement_index(pcity->production.value.building)],
5805 "%s.current_want", buf);
5806 } else {
5807 secfile_insert_int(saving->file, 0,
5808 "%s.current_want", buf);
5809 }
5810
5812 "%s.changed_from_kind", buf);
5814 "%s.changed_from_name", buf);
5815
5816 secfile_insert_int(saving->file, pcity->before_change_shields,
5817 "%s.before_change_shields", buf);
5818 secfile_insert_int(saving->file, pcity->caravan_shields,
5819 "%s.caravan_shields", buf);
5820 secfile_insert_int(saving->file, pcity->disbanded_shields,
5821 "%s.disbanded_shields", buf);
5822 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5823 "%s.last_turns_shield_surplus", buf);
5824
5826 "%s.style", buf);
5827
5828 /* Save the squared city radius and all tiles within the corresponding
5829 * city map. */
5830 secfile_insert_int(saving->file, pcity->city_radius_sq,
5831 "player%d.c%d.city_radius_sq", plrno, i);
5832 /* The tiles worked by the city are saved using the main map.
5833 * See also sg_save_map_worked(). */
5834
5835 /* Save improvement list as bytevector. Note that improvement order
5836 * is saved in savefile.improvement_order. */
5837 improvement_iterate(pimprove) {
5838 impr_buf[improvement_index(pimprove)]
5839 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5840 : '1';
5842 impr_buf[improvement_count()] = '\0';
5843
5845 "Invalid size of the improvement vector (%s.improvements: "
5846 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5847 strlen(impr_buf), sizeof(impr_buf));
5848 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5849
5850 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5851 buf);
5852
5853 for (j = 0; j < CITYO_LAST; j++) {
5854 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5855 "%s.option%d", buf, j);
5856 }
5857 secfile_insert_int(saving->file, pcity->wlcb,
5858 "%s.wlcb", buf);
5859
5860 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5861
5863 /* Save nationality of the citizens,*/
5864 players_iterate(pplayer) {
5865 if (nations[player_index(pplayer)]) {
5867 citizens_nation_get(pcity, pplayer->slot),
5868 "%s.citizen%d", buf, player_index(pplayer));
5869 }
5871 }
5872
5873 secfile_insert_int(saving->file, pcity->rally_point.length,
5874 "%s.rally_point_length", buf);
5875 if (pcity->rally_point.length) {
5876 int len = pcity->rally_point.length;
5877 char orders[len + 1], dirs[len + 1], activities[len + 1];
5878 int actions[len];
5879 int targets[len];
5880 int sub_targets[len];
5881
5882 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5883 "%s.rally_point_persistent", buf);
5884 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5885 "%s.rally_point_vigilant", buf);
5886
5887 for (j = 0; j < len; j++) {
5888 orders[j] = order2char(pcity->rally_point.orders[j].order);
5889 dirs[j] = '?';
5890 activities[j] = '?';
5891 targets[j] = NO_TARGET;
5892 sub_targets[j] = NO_TARGET;
5893 actions[j] = -1;
5894 switch (pcity->rally_point.orders[j].order) {
5895 case ORDER_MOVE:
5896 case ORDER_ACTION_MOVE:
5897 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5898 break;
5899 case ORDER_ACTIVITY:
5900 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5901 activities[j]
5902 = activity2char(pcity->rally_point.orders[j].activity);
5903 actions[j]
5904 = pcity->rally_point.orders[j].action;
5905 break;
5907 actions[j] = pcity->rally_point.orders[j].action;
5908 targets[j] = pcity->rally_point.orders[j].target;
5909 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5910 break;
5911 case ORDER_FULL_MP:
5912 case ORDER_LAST:
5913 break;
5914 }
5915
5916 if (actions[j] == ACTION_NONE) {
5917 actions[j] = -1;
5918 }
5919 }
5920 orders[len] = dirs[len] = activities[len] = '\0';
5921
5922 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5923 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5924 secfile_insert_str(saving->file, activities,
5925 "%s.rally_point_activities", buf);
5926
5928 "%s.rally_point_action_vec", buf);
5929 /* Fill in dummy values for order targets so the registry will save
5930 * the unit table in a tabular format. */
5931 for (j = len; j < rally_point_max_length; j++) {
5932 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5933 buf, j);
5934 }
5935
5936 secfile_insert_int_vec(saving->file, targets, len,
5937 "%s.rally_point_tgt_vec", buf);
5938 /* Fill in dummy values for order targets so the registry will save
5939 * the unit table in a tabular format. */
5940 for (j = len; j < rally_point_max_length; j++) {
5942 "%s.rally_point_tgt_vec,%d", buf, j);
5943 }
5944
5945 secfile_insert_int_vec(saving->file, sub_targets, len,
5946 "%s.rally_point_sub_tgt_vec", buf);
5947 /* Fill in dummy values for order targets so the registry will save
5948 * the unit table in a tabular format. */
5949 for (j = len; j < rally_point_max_length; j++) {
5950 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5951 buf, j);
5952 }
5953 } else {
5954 /* Put all the same fields into the savegame - otherwise the
5955 * registry code can't correctly use a tabular format and the
5956 * savegame will be bigger. */
5957 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5958 buf);
5959 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5960 buf);
5961 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5962 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5963 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5964 buf);
5965
5966 /* Fill in dummy values for order targets so the registry will save
5967 * the unit table in a tabular format. */
5968
5969 /* The start of a vector has no number. */
5970 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5971 buf);
5972 for (j = 1; j < rally_point_max_length; j++) {
5973 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5974 buf, j);
5975 }
5976
5977 /* The start of a vector has no number. */
5978 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5979 buf);
5980 for (j = 1; j < rally_point_max_length; j++) {
5982 "%s.rally_point_tgt_vec,%d", buf, j);
5983 }
5984
5985 /* The start of a vector has no number. */
5986 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5987 buf);
5988 for (j = 1; j < rally_point_max_length; j++) {
5989 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5990 buf, j);
5991 }
5992 }
5993
5994 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5995 "%s.cma_enabled", buf);
5996 if (pcity->cm_parameter) {
5998 pcity->cm_parameter->minimal_surplus, O_LAST,
5999 "%s.cma_minimal_surplus", buf);
6001 pcity->cm_parameter->factor, O_LAST,
6002 "%s.cma_factor", buf);
6003 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6004 "%s.max_growth", buf);
6005 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6006 "%s.require_happy", buf);
6007 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6008 "%s.allow_disorder", buf);
6010 pcity->cm_parameter->allow_specialists,
6011 "%s.allow_specialists", buf);
6012 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6013 "%s.happy_factor", buf);
6014 } else {
6015 int zeros[O_LAST];
6016
6017 memset(zeros, 0, sizeof(zeros));
6019 "%s.cma_minimal_surplus", buf);
6021 "%s.cma_factor", buf);
6022 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6023 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6024 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6025 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6026 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6027 }
6028
6029 i++;
6031
6032 i = 0;
6034 worker_task_list_iterate(pcity->task_reqs, ptask) {
6035 int nat_x, nat_y;
6036
6038 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6039 plrno, i);
6040 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6041 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6043 "player%d.task%d.activity",
6044 plrno, i);
6045 if (ptask->tgt != NULL) {
6047 "player%d.task%d.target",
6048 plrno, i);
6049 } else {
6050 secfile_insert_str(saving->file, "-",
6051 "player%d.task%d.target",
6052 plrno, i);
6053 }
6054 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6055
6056 i++;
6059}
6060
6061/************************************************************************/
6065 struct player *plr)
6066{
6067 int nunits, i, plrno = player_number(plr);
6068 size_t orders_max_length;
6069
6070 /* Check status and return if not OK (sg_success FALSE). */
6071 sg_check_ret();
6072
6074 "player%d.nunits", plrno),
6075 "%s", secfile_error());
6076 if (!plr->is_alive && nunits > 0) {
6077 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6078 nunits = 0; /* Some old savegames may be buggy. */
6079 }
6080
6082 "player%d.orders_max_length",
6083 plrno);
6084
6085 for (i = 0; i < nunits; i++) {
6086 struct unit *punit;
6087 struct city *pcity;
6088 const char *name;
6089 char buf[32];
6090 struct unit_type *type;
6091 struct tile *ptile;
6092
6093 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6094
6095 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6097 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6098
6099 /* Create a dummy unit. */
6100 punit = unit_virtual_create(plr, NULL, type, 0);
6103 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6104 }
6105
6108
6110 unit_list_prepend(pcity->units_supported, punit);
6111 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6112 log_sg("%s: bad home city %d.", buf, punit->homecity);
6114 }
6115
6116 ptile = unit_tile(punit);
6117
6118 /* allocate the unit's contribution to fog of war */
6121 /* NOTE: There used to be some map_set_known calls here. These were
6122 * unneeded since unfogging the tile when the unit sees it will
6123 * automatically reveal that tile. */
6124
6127 }
6128}
6129
6130/************************************************************************/
6134 struct player *plr, struct unit *punit,
6136 const char *unitstr)
6137{
6138 enum unit_activity activity;
6139 int nat_x, nat_y;
6140 struct extra_type *pextra = NULL;
6141 struct tile *ptile;
6142 int extra_id;
6143 int ei;
6144 const char *facing_str;
6145 int natnbr;
6146 int unconverted;
6147 const char *str;
6148 enum gen_action action;
6149
6151 unitstr), FALSE, "%s", secfile_error());
6153 FALSE, "%s", secfile_error());
6155 FALSE, "%s", secfile_error());
6156
6157 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6158 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6159 unitstr, nat_x, nat_y);
6160 unit_tile_set(punit, ptile);
6161
6164 "%s.facing", unitstr);
6165 if (facing_str[0] != 'x') {
6166 /* We don't touch punit->facing if savegame does not contain that
6167 * information. Initial orientation set by unit_virtual_create()
6168 * is as good as any. */
6169 enum direction8 facing = char2dir(facing_str[0]);
6170
6171 if (direction8_is_valid(facing)) {
6172 punit->facing = facing;
6173 } else {
6174 log_error("Illegal unit orientation '%s'", facing_str);
6175 }
6176 }
6177
6178 /* If savegame has unit nationality, it doesn't hurt to
6179 * internally set it even if nationality rules are disabled. */
6181 player_number(plr),
6182 "%s.nationality", unitstr);
6183
6185 if (punit->nationality == NULL) {
6186 punit->nationality = plr;
6187 }
6188
6190 "%s.homecity", unitstr), FALSE,
6191 "%s", secfile_error());
6193 "%s.moves", unitstr), FALSE,
6194 "%s", secfile_error());
6196 "%s.fuel", unitstr), FALSE,
6197 "%s", secfile_error());
6199 "%s.activity", unitstr), FALSE,
6200 "%s", secfile_error());
6201 activity = unit_activity_by_name(loading->activities.order[ei],
6204 "%s.action", unitstr), FALSE,
6205 "%s", secfile_error());
6206 if (ei == -1) {
6208 } else if (ei >= 0 && ei < loading->action.size) {
6209 action = loading->action.order[ei];
6210 } else {
6211 log_sg("Invalid action id for unit %d", punit->id);
6213 }
6214
6217 "%s.born", unitstr);
6220 "%s.current_form_turn", unitstr);
6221
6223 "%s.activity_tgt", unitstr);
6224
6225 if (extra_id != -2) {
6226 if (extra_id >= 0 && extra_id < loading->extra.size) {
6227 pextra = loading->extra.order[extra_id];
6228 set_unit_activity_targeted(punit, activity, pextra, action);
6229 } else if (activity == ACTIVITY_IRRIGATE) {
6233 punit);
6234 if (tgt != NULL) {
6236 } else {
6238 }
6239 } else if (activity == ACTIVITY_MINE) {
6241 EC_MINE,
6243 punit);
6244 if (tgt != NULL) {
6246 } else {
6248 }
6249 } else {
6250 set_unit_activity(punit, activity, action);
6251 }
6252 } else {
6254 } /* activity_tgt == NULL */
6255
6257 "%s.activity_count", unitstr), FALSE,
6258 "%s", secfile_error());
6259
6262 "%s.changed_from", unitstr);
6263
6265 "%s.changed_from_tgt", unitstr), FALSE,
6266 "%s", secfile_error());
6267
6268 if (extra_id >= 0 && extra_id < loading->extra.size) {
6269 punit->changed_from_target = loading->extra.order[extra_id];
6270 } else {
6272 }
6273
6276 "%s.changed_from_count", unitstr);
6277
6278 /* Special case: for a long time, we accidentally incremented
6279 * activity_count while a unit was sentried, so it could increase
6280 * without bound (bug #20641) and be saved in old savefiles.
6281 * We zero it to prevent potential trouble overflowing the range
6282 * in network packets, etc. */
6283 if (activity == ACTIVITY_SENTRY) {
6284 punit->activity_count = 0;
6285 }
6288 }
6289
6290 punit->veteran
6291 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6292 {
6293 /* Protect against change in veteran system in ruleset */
6294 const int levels = utype_veteran_levels(unit_type_get(punit));
6295
6296 if (punit->veteran >= levels) {
6297 fc_assert(levels >= 1);
6298 punit->veteran = levels - 1;
6299 }
6300 }
6303 "%s.done_moving", unitstr);
6306 "%s.battlegroup", unitstr);
6307
6309 "%s.go", unitstr)) {
6310 int gnat_x, gnat_y;
6311
6313 "%s.goto_x", unitstr), FALSE,
6314 "%s", secfile_error());
6316 "%s.goto_y", unitstr), FALSE,
6317 "%s", secfile_error());
6318
6320 } else {
6321 punit->goto_tile = NULL;
6322
6323 /* These variables are not used but needed for saving the unit table.
6324 * Load them to prevent unused variables errors. */
6325 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6326 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6327 }
6328
6329 /* Load AI data of the unit. */
6330 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6331
6334 "%s.server_side_agent",
6335 unitstr);
6336 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6337 /* Look up what server side agent the unconverted number represents. */
6338 punit->ssa_controller = loading->ssa.order[unconverted];
6339 } else {
6340 log_sg("Invalid server side agent %d for unit %d",
6341 unconverted, punit->id);
6342
6344 }
6345
6347 "%s.hp", unitstr), FALSE,
6348 "%s", secfile_error());
6349
6351 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6353 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6354 punit->moved
6355 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6358 "%s.paradropped", unitstr);
6359 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6360 if (str[0] != '\0') {
6362 }
6363
6364 /* The transport status (punit->transported_by) is loaded in
6365 * sg_player_units_transport(). */
6366
6367 /* Initialize upkeep values: these are hopefully initialized
6368 * elsewhere before use (specifically, in city_support(); but
6369 * fixme: check whether always correctly initialized?).
6370 * Below is mainly for units which don't have homecity --
6371 * otherwise these don't get initialized (and AI calculations
6372 * etc may use junk values). */
6376
6378 "%s.action_decision", unitstr),
6379 FALSE, "%s", secfile_error());
6380
6381 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6382 /* Look up what action decision want the unconverted number
6383 * represents. */
6384 punit->action_decision_want = loading->act_dec.order[unconverted];
6385 } else {
6386 log_sg("Invalid action decision want for unit %d", punit->id);
6387
6389 }
6390
6392 /* Load the tile to act against. */
6393 int adwt_x, adwt_y;
6394
6395 if (secfile_lookup_int(loading->file, &adwt_x,
6396 "%s.action_decision_tile_x", unitstr)
6398 "%s.action_decision_tile_y", unitstr)) {
6400 adwt_x, adwt_y);
6401 } else {
6404 log_sg("Bad action_decision_tile for unit %d", punit->id);
6405 }
6406 } else {
6407 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6408 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6410 }
6411
6413
6414 /* Load the unit orders */
6415 {
6416 int len = secfile_lookup_int_default(loading->file, 0,
6417 "%s.orders_length", unitstr);
6418
6419 if (len > 0) {
6420 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6421 int j;
6422
6423 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6427 "%s.orders_index", unitstr);
6430 "%s.orders_repeat", unitstr);
6433 "%s.orders_vigilant", unitstr);
6434
6437 "%s.orders_list", unitstr);
6440 "%s.dir_list", unitstr);
6443 "%s.activity_list", unitstr);
6444
6446
6447 for (j = 0; j < len; j++) {
6448 struct unit_order *order = &punit->orders.list[j];
6450 int order_sub_tgt;
6451
6452 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6453 || act_unitstr[j] == '\0') {
6454 log_sg("Invalid unit orders.");
6456 break;
6457 }
6458 order->order = char2order(orders_unitstr[j]);
6459 order->dir = char2dir(dir_unitstr[j]);
6460 order->activity = char2activity(act_unitstr[j]);
6461
6463 "%s.action_vec,%d",
6464 unitstr, j);
6465
6466 if (unconverted == -1) {
6467 order->action = ACTION_NONE;
6468 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6469 /* Look up what action id the unconverted number represents. */
6470 order->action = loading->action.order[unconverted];
6471 } else {
6472 if (order->order == ORDER_PERFORM_ACTION) {
6473 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6474 }
6475
6476 order->action = ACTION_NONE;
6477 }
6478
6479 if (order->order == ORDER_LAST
6480 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6481 || (order->order == ORDER_ACTION_MOVE
6482 && !direction8_is_valid(order->dir))
6483 || (order->order == ORDER_PERFORM_ACTION
6484 && !action_id_exists(order->action))
6485 || (order->order == ORDER_ACTIVITY
6486 && (order->activity == ACTIVITY_LAST
6487 || !action_id_exists(order->action)))) {
6488 /* An invalid order. Just drop the orders for this unit. */
6490 punit->orders.list = NULL;
6492 break;
6493 }
6494
6496 "%s.tgt_vec,%d",
6497 unitstr, j);
6499 "%s.sub_tgt_vec,%d",
6500 unitstr, j);
6501
6502 if (order->order == ORDER_PERFORM_ACTION) {
6503 /* Validate sub target */
6504 switch (action_id_get_sub_target_kind(order->action)) {
6505 case ASTK_BUILDING:
6506 /* Sub target is a building. */
6508 /* Sub target is invalid. */
6509 log_sg("Cannot find building %d for %s to %s",
6512 order->sub_target = B_LAST;
6513 } else {
6514 order->sub_target = order_sub_tgt;
6515 }
6516 break;
6517 case ASTK_TECH:
6518 /* Sub target is a technology. */
6519 if (order_sub_tgt == A_NONE
6521 && order_sub_tgt != A_FUTURE)) {
6522 /* Target tech is invalid. */
6523 log_sg("Cannot find tech %d for %s to steal",
6525 order->sub_target = A_NONE;
6526 } else {
6527 order->sub_target = order_sub_tgt;
6528 }
6529 break;
6530 case ASTK_EXTRA:
6532 /* These take an extra. */
6534 break;
6535 case ASTK_NONE:
6536 /* None of these can take a sub target. */
6538 "Specified sub target for action %d unsupported.",
6539 order->action);
6540 order->sub_target = NO_TARGET;
6541 break;
6542 case ASTK_COUNT:
6544 "Bad action action %d.",
6545 order->action);
6546 order->sub_target = NO_TARGET;
6547 break;
6548 }
6549 }
6550
6551 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6552 enum unit_activity act;
6553
6555 if (order_sub_tgt != EXTRA_NONE) {
6556 log_sg("Cannot find extra %d for %s to build",
6558 }
6559
6560 order->sub_target = EXTRA_NONE;
6561 } else {
6562 order->sub_target = order_sub_tgt;
6563 }
6564
6565 /* An action or an activity may require an extra target. */
6566 if (action_wants_extra) {
6567 act = action_id_get_activity(order->action);
6568 } else {
6569 act = order->activity;
6570 }
6571
6572 if (unit_activity_is_valid(act)
6574 && order->sub_target == EXTRA_NONE) {
6575 /* Missing required action extra target. */
6577 punit->orders.list = NULL;
6579 break;
6580 }
6581 } else if (order->order != ORDER_PERFORM_ACTION) {
6582 if (order_sub_tgt != -1) {
6583 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6584 order_sub_tgt, -1, order->order);
6585 }
6586 order->sub_target = NO_TARGET;
6587 }
6588 }
6589
6590 for (; j < orders_max_length; j++) {
6592 "%s.action_vec,%d", unitstr, j);
6594 "%s.tgt_vec,%d", unitstr, j);
6596 "%s.sub_tgt_vec,%d", unitstr, j);
6597 }
6598 } else {
6599 int j;
6600
6602 punit->orders.list = NULL;
6603
6604 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6605 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6606 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6607 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6608 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6609 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6610 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6611 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6612 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6613
6614 for (j = 1; j < orders_max_length; j++) {
6616 "%s.action_vec,%d", unitstr, j);
6618 "%s.tgt_vec,%d", unitstr, j);
6620 "%s.sub_tgt_vec,%d", unitstr, j);
6621 }
6622 }
6623 }
6624
6625 return TRUE;
6626}
6627
6628/************************************************************************/
6633 struct player *plr)
6634{
6635 int nunits, i, plrno = player_number(plr);
6636
6637 /* Check status and return if not OK (sg_success FALSE). */
6638 sg_check_ret();
6639
6640 /* Recheck the number of units for the player. This is a copied from
6641 * sg_load_player_units(). */
6643 "player%d.nunits", plrno),
6644 "%s", secfile_error());
6645 if (!plr->is_alive && nunits > 0) {
6646 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6647 nunits = 0; /* Some old savegames may be buggy. */
6648 }
6649
6650 for (i = 0; i < nunits; i++) {
6651 int id_unit, id_trans;
6652 struct unit *punit, *ptrans;
6653
6655 "player%d.u%d.id",
6656 plrno, i);
6658 fc_assert_action(punit != NULL, continue);
6659
6661 "player%d.u%d.transported_by",
6662 plrno, i);
6663 if (id_trans == -1) {
6664 /* Not transported. */
6665 continue;
6666 }
6667
6669 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6670
6671 if (ptrans) {
6672#ifndef FREECIV_NDEBUG
6673 bool load_success =
6674#endif
6676
6677 fc_assert_action(load_success, continue);
6678 }
6679 }
6680}
6681
6682/************************************************************************/
6686 struct player *plr)
6687{
6688 int i = 0;
6689 int longest_order = 0;
6690 int plrno = player_number(plr);
6691
6692 /* Check status and return if not OK (sg_success FALSE). */
6693 sg_check_ret();
6694
6696 "player%d.nunits", plrno);
6697
6698 /* Find the longest unit order so different order length won't break
6699 * storing units in the tabular format. */
6701 if (punit->has_orders) {
6702 if (longest_order < punit->orders.length) {
6704 }
6705 }
6707
6709 "player%d.orders_max_length", plrno);
6710
6712 char buf[32];
6713 char dirbuf[2] = " ";
6714 int nat_x, nat_y;
6715 int last_order, j;
6716
6717 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6718 dirbuf[0] = dir2char(punit->facing);
6719 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6720
6722 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6723 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6724
6725 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6728 "%s.nationality", buf);
6729 }
6730 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6731 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6732 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6734 "%s.type_by_name", buf);
6735
6736 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6738 "%s.activity_count", buf);
6739 if (punit->action == ACTION_NONE) {
6740 secfile_insert_int(saving->file, -1, "%s.action", buf);
6741 } else {
6742 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6743 }
6744 if (punit->activity_target == NULL) {
6745 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6746 } else {
6748 "%s.activity_tgt", buf);
6749 }
6750
6752 "%s.changed_from", buf);
6754 "%s.changed_from_count", buf);
6755 if (punit->changed_from_target == NULL) {
6756 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6757 } else {
6759 "%s.changed_from_tgt", buf);
6760 }
6761
6763 "%s.done_moving", buf);
6764 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6765 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6767 "%s.born", buf);
6769 "%s.current_form_turn", buf);
6771 "%s.battlegroup", buf);
6772
6773 if (punit->goto_tile) {
6775 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6776 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6777 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6778 } else {
6779 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6780 /* Set this values to allow saving it as table. */
6781 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6782 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6783 }
6784
6786 "%s.server_side_agent", buf);
6787
6788 /* Save AI data of the unit. */
6789 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6790
6792 "%s.ord_map", buf);
6794 "%s.ord_city", buf);
6795 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6797 "%s.paradropped", buf);
6799 ? unit_transport_get(punit)->id : -1,
6800 "%s.transported_by", buf);
6801 if (punit->carrying != NULL) {
6803 "%s.carrying", buf);
6804 } else {
6805 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6806 }
6807
6809 "%s.action_decision", buf);
6810
6811 /* Stored as tile rather than direction to make sure the target tile is
6812 * sane. */
6817 "%s.action_decision_tile_x", buf);
6819 "%s.action_decision_tile_y", buf);
6820 } else {
6821 /* Dummy values to get tabular format. */
6822 secfile_insert_int(saving->file, -1,
6823 "%s.action_decision_tile_x", buf);
6824 secfile_insert_int(saving->file, -1,
6825 "%s.action_decision_tile_y", buf);
6826 }
6827
6829 "%s.stay", buf);
6830
6831 if (punit->has_orders) {
6832 int len = punit->orders.length;
6833 char orders_buf[len + 1], dir_buf[len + 1];
6834 char act_buf[len + 1];
6835 int action_buf[len];
6836 int tgt_vec[len];
6837 int sub_tgt_vec[len];
6838
6839 last_order = len;
6840
6841 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6843 "%s.orders_index", buf);
6845 "%s.orders_repeat", buf);
6847 "%s.orders_vigilant", buf);
6848
6849 for (j = 0; j < len; j++) {
6851 dir_buf[j] = '?';
6852 act_buf[j] = '?';
6853 tgt_vec[j] = NO_TARGET;
6854 sub_tgt_vec[j] = -1;
6855 action_buf[j] = -1;
6856 switch (punit->orders.list[j].order) {
6857 case ORDER_MOVE:
6858 case ORDER_ACTION_MOVE:
6859 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6860 break;
6861 case ORDER_ACTIVITY:
6865 break;
6868 tgt_vec[j] = punit->orders.list[j].target;
6870 break;
6871 case ORDER_FULL_MP:
6872 case ORDER_LAST:
6873 break;
6874 }
6875
6876 if (action_buf[j] == ACTION_NONE) {
6877 action_buf[j] = -1;
6878 }
6879 }
6880 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6881
6882 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6883 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6884 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6885
6887 "%s.action_vec", buf);
6888 /* Fill in dummy values for order targets so the registry will save
6889 * the unit table in a tabular format. */
6890 for (j = last_order; j < longest_order; j++) {
6891 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6892 }
6893
6895 "%s.tgt_vec", buf);
6896 /* Fill in dummy values for order targets so the registry will save
6897 * the unit table in a tabular format. */
6898 for (j = last_order; j < longest_order; j++) {
6899 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6900 }
6901
6903 "%s.sub_tgt_vec", buf);
6904 /* Fill in dummy values for order targets so the registry will save
6905 * the unit table in a tabular format. */
6906 for (j = last_order; j < longest_order; j++) {
6907 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6908 }
6909 } else {
6910
6911 /* Put all the same fields into the savegame - otherwise the
6912 * registry code can't correctly use a tabular format and the
6913 * savegame will be bigger. */
6914 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6915 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6916 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6917 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6918 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6919 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6920 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6921
6922 /* Fill in dummy values for order targets so the registry will save
6923 * the unit table in a tabular format. */
6924
6925 /* The start of a vector has no number. */
6926 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6927 for (j = 1; j < longest_order; j++) {
6928 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6929 }
6930
6931 /* The start of a vector has no number. */
6932 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6933 for (j = 1; j < longest_order; j++) {
6934 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6935 }
6936
6937 /* The start of a vector has no number. */
6938 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6939 for (j = 1; j < longest_order; j++) {
6940 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6941 }
6942 }
6943
6944 i++;
6946}
6947
6948/************************************************************************/
6952 struct player *plr)
6953{
6954 int plrno = player_number(plr);
6955
6956 /* Check status and return if not OK (sg_success FALSE). */
6957 sg_check_ret();
6958
6959 /* Toss any existing attribute_block (should not exist) */
6960 if (plr->attribute_block.data) {
6962 plr->attribute_block.data = NULL;
6963 }
6964
6965 /* This is a big heap of opaque data for the client, check everything! */
6967 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6968
6969 if (0 > plr->attribute_block.length) {
6970 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6971 plr->attribute_block.length);
6972 plr->attribute_block.length = 0;
6973 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6974 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6976 plr->attribute_block.length = 0;
6977 } else if (0 < plr->attribute_block.length) {
6978 int part_nr, parts;
6979 int quoted_length;
6980 char *quoted;
6981#ifndef FREECIV_NDEBUG
6982 size_t actual_length;
6983#endif
6984
6987 "player%d.attribute_v2_block_length_quoted",
6988 plrno), "%s", secfile_error());
6991 "player%d.attribute_v2_block_parts", plrno),
6992 "%s", secfile_error());
6993
6995 quoted[0] = '\0';
6997 for (part_nr = 0; part_nr < parts; part_nr++) {
6998 const char *current =
7000 "player%d.attribute_v2_block_data.part%d",
7001 plrno, part_nr);
7002 if (!current) {
7003 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7004 break;
7005 }
7006 log_debug("attribute_v2_block_length_quoted=%d"
7007 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7008 quoted_length, strlen(quoted), strlen(current));
7009 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7010 strcat(quoted, current);
7011 }
7013 "attribute_v2_block_length_quoted=%d"
7014 " actual=" SIZE_T_PRINTF,
7016
7017#ifndef FREECIV_NDEBUG
7019#endif
7021 plr->attribute_block.data,
7022 plr->attribute_block.length);
7024 free(quoted);
7025 }
7026}
7027
7028/************************************************************************/
7032 struct player *plr)
7033{
7034 int plrno = player_number(plr);
7035
7036 /* Check status and return if not OK (sg_success FALSE). */
7037 sg_check_ret();
7038
7039 /* This is a big heap of opaque data from the client. Although the binary
7040 * format is not user editable, keep the lines short enough for debugging,
7041 * and hope that data compression will keep the file a reasonable size.
7042 * Note that the "quoted" format is a multiple of 3.
7043 */
7044#define PART_SIZE (3*256)
7045#define PART_ADJUST (3)
7046 if (plr->attribute_block.data) {
7047 char part[PART_SIZE + PART_ADJUST];
7048 int parts;
7049 int current_part_nr;
7051 plr->attribute_block.length);
7052 char *quoted_at = strchr(quoted, ':');
7053 size_t bytes_left = strlen(quoted);
7054 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7056
7058 "player%d.attribute_v2_block_length", plrno);
7060 "player%d.attribute_v2_block_length_quoted", plrno);
7061
7062 /* Try to wring some compression efficiencies out of the "quoted" format.
7063 * The first line has a variable length decimal, mis-aligning triples.
7064 */
7065 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7066 /* first line can be longer */
7067 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7068 } else {
7069 parts = 1;
7070 }
7071
7073 "player%d.attribute_v2_block_parts", plrno);
7074
7075 if (parts > 1) {
7077
7078 /* first line can be longer */
7080 part[size_of_current_part] = '\0';
7082 "player%d.attribute_v2_block_data.part%d",
7083 plrno, 0);
7086 current_part_nr = 1;
7087 } else {
7088 quoted_at = quoted;
7089 current_part_nr = 0;
7090 }
7091
7094
7096 part[size_of_current_part] = '\0';
7098 "player%d.attribute_v2_block_data.part%d",
7099 plrno,
7103 }
7104 fc_assert(bytes_left == 0);
7105 free(quoted);
7106 }
7107#undef PART_ADJUST
7108#undef PART_SIZE
7109}
7110
7111/************************************************************************/
7115 struct player *plr)
7116{
7117 int plrno = player_number(plr);
7118 int total_ncities =
7120 "player%d.dc_total", plrno);
7121 int i;
7122 bool someone_alive = FALSE;
7123
7124 /* Check status and return if not OK (sg_success FALSE). */
7125 sg_check_ret();
7126
7129 if (pteam_member->is_alive) {
7131 break;
7132 }
7134
7135 if (!someone_alive) {
7136 /* Reveal all for completely dead teams. */
7138 }
7139 }
7140
7141 if (-1 == total_ncities
7142 || !game.info.fogofwar
7144 "game.save_private_map")) {
7145 /* We have:
7146 * - a dead player;
7147 * - fogged cities are not saved for any reason;
7148 * - a savegame with fog of war turned off;
7149 * - or game.save_private_map is not set to FALSE in the scenario /
7150 * savegame. The players private knowledge is set to be what they could
7151 * see without fog of war. */
7152 whole_map_iterate(&(wld.map), ptile) {
7153 if (map_is_known(ptile, plr)) {
7154 struct city *pcity = tile_city(ptile);
7155
7156 update_player_tile_last_seen(plr, ptile);
7157 update_player_tile_knowledge(plr, ptile);
7158
7159 if (NULL != pcity) {
7160 update_dumb_city(plr, pcity);
7161 }
7162 }
7164
7165 /* Nothing more to do; */
7166 return;
7167 }
7168
7169 /* Load player map (terrain). */
7170 LOAD_MAP_CHAR(ch, ptile,
7171 map_get_player_tile(ptile, plr)->terrain
7172 = char2terrain(ch), loading->file,
7173 "player%d.map_t%04d", plrno);
7174
7175 /* Load player map (extras). */
7176 halfbyte_iterate_extras(j, loading->extra.size) {
7177 LOAD_MAP_CHAR(ch, ptile,
7179 ch, loading->extra.order + 4 * j),
7180 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7182
7183 whole_map_iterate(&(wld.map), ptile) {
7184 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7185
7187 if (BV_ISSET(plrtile->extras, extra_number(pres))) {
7188 plrtile->resource = pres;
7189 if (!terrain_has_resource(plrtile->terrain, pres)) {
7190 BV_CLR(plrtile->extras, extra_number(pres));
7191 }
7192 }
7195
7197 /* Load player map (border). */
7198 int x, y;
7199
7200 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7201 const char *buffer
7202 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7203 plrno, y);
7204 const char *buffer2
7205 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7206 plrno, y);
7207 const char *ptr = buffer;
7208 const char *ptr2 = buffer2;
7209
7210 sg_failure_ret(NULL != buffer,
7211 "Savegame corrupt - map line %d not found.", y);
7212 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7213 char token[TOKEN_SIZE];
7214 char token2[TOKEN_SIZE];
7215 int number;
7216 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7217
7218 scanin(&ptr, ",", token, sizeof(token));
7219 sg_failure_ret('\0' != token[0],
7220 "Savegame corrupt - map size not correct.");
7221 if (strcmp(token, "-") == 0) {
7222 map_get_player_tile(ptile, plr)->owner = NULL;
7223 } else {
7224 sg_failure_ret(str_to_int(token, &number),
7225 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7226 token, x, y);
7227 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7228 }
7229
7230 scanin(&ptr2, ",", token2, sizeof(token2));
7231 sg_failure_ret('\0' != token2[0],
7232 "Savegame corrupt - map size not correct.");
7233 if (strcmp(token2, "-") == 0) {
7234 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7235 } else {
7237 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7238 token, x, y);
7239 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7240 }
7241 }
7242 }
7243 }
7244
7245 /* Load player map (update time). */
7246 for (i = 0; i < 4; i++) {
7247 /* put 4-bit segments of 16-bit "updated" field */
7248 if (i == 0) {
7249 LOAD_MAP_CHAR(ch, ptile,
7250 map_get_player_tile(ptile, plr)->last_updated
7251 = ascii_hex2bin(ch, i),
7252 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7253 } else {
7254 LOAD_MAP_CHAR(ch, ptile,
7255 map_get_player_tile(ptile, plr)->last_updated
7256 |= ascii_hex2bin(ch, i),
7257 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7258 }
7259 }
7260
7261 /* Load player map known cities. */
7262 for (i = 0; i < total_ncities; i++) {
7263 struct vision_site *pdcity;
7264 char buf[32];
7265 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7266
7270 pdcity);
7272 } else {
7273 /* Error loading the data. */
7274 log_sg("Skipping seen city %d for player %d.", i, plrno);
7275 if (pdcity != NULL) {
7277 }
7278 }
7279 }
7280
7281 /* Repair inconsistent player maps. */
7282 whole_map_iterate(&(wld.map), ptile) {
7283 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7284 struct city *pcity = tile_city(ptile);
7285
7286 update_player_tile_knowledge(plr, ptile);
7287 reality_check_city(plr, ptile);
7288
7289 if (NULL != pcity) {
7290 update_dumb_city(plr, pcity);
7291 }
7292 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7293 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7294 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7295
7296 plrtile->owner = tile_owner(ptile);
7297 }
7299}
7300
7301/************************************************************************/
7305 struct player *plr,
7306 struct vision_site *pdcity,
7307 const char *citystr)
7308{
7309 const char *str;
7310 int i, id, size;
7311 citizens city_size;
7312 int nat_x, nat_y;
7313 const char *stylename;
7314 enum capital_type cap;
7315 const char *vname;
7316
7318 citystr),
7319 FALSE, "%s", secfile_error());
7321 citystr),
7322 FALSE, "%s", secfile_error());
7323 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7324 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7325 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7326
7327 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7328 citystr),
7329 FALSE, "%s", secfile_error());
7330 pdcity->owner = player_by_number(id);
7331 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7332 "%s has invalid owner (%d); skipping.", citystr, id);
7333
7334 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7335 citystr),
7336 FALSE, "%s", secfile_error());
7337 if (id >= 0) {
7338 pdcity->original = player_by_number(id);
7339 sg_warn_ret_val(NULL != pdcity->original, FALSE,
7340 "%s has invalid original owner (%d); skipping.", citystr, id);
7341 } else {
7342 pdcity->original = nullptr;
7343 }
7344
7346 "%s.id", citystr),
7347 FALSE, "%s", secfile_error());
7349 "%s has invalid id (%d); skipping.", citystr, id);
7350
7352 "%s.size", citystr),
7353 FALSE, "%s", secfile_error());
7354 city_size = (citizens)size; /* set the correct type */
7355 sg_warn_ret_val(size == (int)city_size, FALSE,
7356 "Invalid city size: %d; set to %d.", size, city_size);
7357 vision_site_size_set(pdcity, city_size);
7358
7359 /* Initialise list of improvements */
7360 BV_CLR_ALL(pdcity->improvements);
7361 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7363 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7364 "Invalid length of '%s.improvements' ("
7365 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7366 citystr, strlen(str), loading->improvement.size);
7367 for (i = 0; i < loading->improvement.size; i++) {
7368 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7369 "Undefined value '%c' within '%s.improvements'.",
7370 str[i], citystr)
7371
7372 if (str[i] == '1') {
7373 struct impr_type *pimprove =
7374 improvement_by_rule_name(loading->improvement.order[i]);
7375 if (pimprove) {
7376 BV_SET(pdcity->improvements, improvement_index(pimprove));
7377 }
7378 }
7379 }
7380
7382 "%s.name", citystr);
7383
7384 if (vname != NULL) {
7385 pdcity->name = fc_strdup(vname);
7386 }
7387
7389 "%s.occupied", citystr);
7391 "%s.walls", citystr);
7393 "%s.happy", citystr);
7395 "%s.unhappy", citystr);
7397 "%s.style", citystr);
7398 if (stylename != NULL) {
7400 } else {
7401 pdcity->style = 0;
7402 }
7403 if (pdcity->style < 0) {
7404 pdcity->style = 0;
7405 }
7406
7407 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7408 "%s.city_image", citystr);
7409
7411 "%s.capital", citystr),
7413
7415 pdcity->capital = cap;
7416 } else {
7417 pdcity->capital = CAPITAL_NOT;
7418 }
7419
7420 return TRUE;
7421}
7422
7423/************************************************************************/
7427 struct player *plr)
7428{
7429 int i, plrno = player_number(plr);
7430
7431 /* Check status and return if not OK (sg_success FALSE). */
7432 sg_check_ret();
7433
7435 /* The player can see all, there's no reason to save the private map. */
7436 return;
7437 }
7438
7439 /* Save the map (terrain). */
7440 SAVE_MAP_CHAR(ptile,
7442 saving->file, "player%d.map_t%04d", plrno);
7443
7445 /* Save the map (borders). */
7446 int x, y;
7447
7448 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7450
7451 line[0] = '\0';
7452 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7453 char token[TOKEN_SIZE];
7454 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7455 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7456
7457 if (plrtile == NULL || plrtile->owner == NULL) {
7458 strcpy(token, "-");
7459 } else {
7460 fc_snprintf(token, sizeof(token), "%d",
7461 player_number(plrtile->owner));
7462 }
7463 strcat(line, token);
7464 if (x < MAP_NATIVE_WIDTH) {
7465 strcat(line, ",");
7466 }
7467 }
7468 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7469 plrno, y);
7470 }
7471
7472 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7474
7475 line[0] = '\0';
7476 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7477 char token[TOKEN_SIZE];
7478 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7479 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7480
7481 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7482 strcpy(token, "-");
7483 } else {
7484 fc_snprintf(token, sizeof(token), "%d",
7485 player_number(plrtile->extras_owner));
7486 }
7487 strcat(line, token);
7488 if (x < MAP_NATIVE_WIDTH) {
7489 strcat(line, ",");
7490 }
7491 }
7492 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7493 plrno, y);
7494 }
7495 }
7496
7497 /* Save the map (extras). */
7499 int mod[4];
7500 int l;
7501
7502 for (l = 0; l < 4; l++) {
7503 if (4 * j + 1 > game.control.num_extra_types) {
7504 mod[l] = -1;
7505 } else {
7506 mod[l] = 4 * j + l;
7507 }
7508 }
7509
7510 SAVE_MAP_CHAR(ptile,
7512 map_get_player_tile(ptile, plr)->resource,
7513 mod),
7514 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7516
7517 /* Save the map (update time). */
7518 for (i = 0; i < 4; i++) {
7519 /* put 4-bit segments of 16-bit "updated" field */
7520 SAVE_MAP_CHAR(ptile,
7522 map_get_player_tile(ptile, plr)->last_updated, i),
7523 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7524 }
7525
7526 /* Save known cities. */
7527 i = 0;
7528 whole_map_iterate(&(wld.map), ptile) {
7529 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7530 char impr_buf[B_LAST + 1];
7531 char buf[32];
7532
7533 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7534
7535 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7536 int nat_x, nat_y;
7537
7539 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7540 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7541
7542 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7544 "%s.owner", buf);
7545 if (pdcity->original != nullptr) {
7547 "%s.original", buf);
7548 } else {
7549 secfile_insert_int(saving->file, -1, "%s.original", buf);
7550 }
7551
7553 "%s.size", buf);
7554 secfile_insert_bool(saving->file, pdcity->occupied,
7555 "%s.occupied", buf);
7556 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7557 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7558 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7560 "%s.style", buf);
7561 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7563 "%s.capital", buf);
7564
7565 /* Save improvement list as bitvector. Note that improvement order
7566 * is saved in savefile.improvement.order. */
7567 improvement_iterate(pimprove) {
7568 impr_buf[improvement_index(pimprove)]
7569 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7570 ? '1' : '0';
7572 impr_buf[improvement_count()] = '\0';
7574 "Invalid size of the improvement vector (%s.improvements: "
7575 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7576 buf, strlen(impr_buf), sizeof(impr_buf));
7577 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7578 if (pdcity->name != NULL) {
7579 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7580 }
7581
7582 i++;
7583 }
7585
7586 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7587}
7588
7589/* =======================================================================
7590 * Load / save the researches.
7591 * ======================================================================= */
7592
7593/************************************************************************/
7597{
7598 struct research *presearch;
7599 int count;
7600 int number;
7601 const char *str;
7602 int i, j;
7603 int *vlist_research;
7604
7606 /* Check status and return if not OK (sg_success FALSE). */
7607 sg_check_ret();
7608
7609 /* Initialize all researches. */
7613
7614 /* May be unsaved (e.g. scenario case). */
7615 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7616 for (i = 0; i < count; i++) {
7618 "research.r%d.number", i),
7619 "%s", secfile_error());
7620 presearch = research_by_number(number);
7622 "Invalid research number %d in 'research.r%d.number'",
7623 number, i);
7624
7625 presearch->tech_goal = technology_load(loading->file,
7626 "research.r%d.goal", i);
7628 &presearch->future_tech,
7629 "research.r%d.futuretech", i),
7630 "%s", secfile_error());
7632 &presearch->bulbs_researched,
7633 "research.r%d.bulbs", i),
7634 "%s", secfile_error());
7636 &presearch->bulbs_researching_saved,
7637 "research.r%d.bulbs_before", i),
7638 "%s", secfile_error());
7639 presearch->researching_saved = technology_load(loading->file,
7640 "research.r%d.saved", i);
7641 presearch->researching = technology_load(loading->file,
7642 "research.r%d.now", i);
7644 &presearch->free_bulbs,
7645 "research.r%d.free_bulbs", i),
7646 "%s", secfile_error());
7647
7648 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7649 sg_failure_ret(str != NULL, "%s", secfile_error());
7650 sg_failure_ret(strlen(str) == loading->technology.size,
7651 "Invalid length of 'research.r%d.done' ("
7652 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7653 i, strlen(str), loading->technology.size);
7654 for (j = 0; j < loading->technology.size; j++) {
7655 sg_failure_ret(str[j] == '1' || str[j] == '0',
7656 "Undefined value '%c' within 'research.r%d.done'.",
7657 str[j], i);
7658
7659 if (str[j] == '1') {
7660 struct advance *padvance =
7661 advance_by_rule_name(loading->technology.order[j]);
7662
7663 if (padvance) {
7665 TECH_KNOWN);
7666 }
7667 }
7668 }
7669
7671 size_t count_res;
7672 int tn;
7673
7675 "research.r%d.vbs", i);
7676
7677 for (tn = 0; tn < count_res; tn++) {
7678 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7679
7680 if (padvance != NULL) {
7681 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7682 = vlist_research[tn];
7683 }
7684 }
7685 }
7686 }
7687
7688 /* In case of tech_leakage, we can update research only after all the
7689 * researches have been loaded */
7693}
7694
7695/************************************************************************/
7699{
7700 char invs[A_LAST];
7701 int i = 0;
7702 int *vlist_research;
7703
7705 /* Check status and return if not OK (sg_success FALSE). */
7706 sg_check_ret();
7707
7708 if (saving->save_players) {
7711 "research.r%d.number", i);
7712 technology_save(saving->file, "research.r%d.goal",
7713 i, presearch->tech_goal);
7714 secfile_insert_int(saving->file, presearch->future_tech,
7715 "research.r%d.futuretech", i);
7716 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7717 "research.r%d.bulbs_before", i);
7721 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7725 "research.r%d.vbs", i);
7726 if (vlist_research) {
7728 }
7729 }
7730 technology_save(saving->file, "research.r%d.saved",
7731 i, presearch->researching_saved);
7732 secfile_insert_int(saving->file, presearch->bulbs_researched,
7733 "research.r%d.bulbs", i);
7734 technology_save(saving->file, "research.r%d.now",
7735 i, presearch->researching);
7736 secfile_insert_int(saving->file, presearch->free_bulbs,
7737 "research.r%d.free_bulbs", i);
7738 /* Save technology lists as bytevector. Note that technology order is
7739 * saved in savefile.technology.order */
7740 advance_index_iterate(A_NONE, tech_id) {
7741 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7743 == TECH_KNOWN ? '1' : '0');
7746 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7747 i++;
7749 secfile_insert_int(saving->file, i, "research.count");
7750 }
7751}
7752
7753/* =======================================================================
7754 * Load / save the event cache. Should be the last thing to do.
7755 * ======================================================================= */
7756
7757/************************************************************************/
7761{
7762 /* Check status and return if not OK (sg_success FALSE). */
7763 sg_check_ret();
7764
7765 event_cache_load(loading->file, "event_cache");
7766}
7767
7768/************************************************************************/
7772{
7773 /* Check status and return if not OK (sg_success FALSE). */
7774 sg_check_ret();
7775
7776 if (saving->scenario) {
7777 /* Do _not_ save events in a scenario. */
7778 return;
7779 }
7780
7781 event_cache_save(saving->file, "event_cache");
7782}
7783
7784/* =======================================================================
7785 * Load / save the open treaties
7786 * ======================================================================= */
7787
7788/************************************************************************/
7792{
7793 int tidx;
7794 const char *plr0;
7795
7796 /* Check status and return if not OK (sg_success FALSE). */
7797 sg_check_ret();
7798
7799 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7800 "treaty%d.plr0", tidx)) != NULL ;
7801 tidx++) {
7802 const char *plr1;
7803 const char *ct;
7804 int cidx;
7805 struct player *p0, *p1;
7806
7807 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7808
7809 p0 = player_by_name(plr0);
7810 p1 = player_by_name(plr1);
7811
7812 if (p0 == NULL || p1 == NULL) {
7813 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7814 } else {
7815 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7816
7819
7820 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7821 "treaty%d.clause%d.type",
7822 tidx, cidx)) != NULL ;
7823 cidx++ ) {
7825 const char *plrx;
7826
7827 if (!clause_type_is_valid(type)) {
7828 log_error("Invalid clause type \"%s\"", ct);
7829 } else {
7830 struct player *pgiver = NULL;
7831
7832 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7833 tidx, cidx);
7834
7835 if (!fc_strcasecmp(plrx, plr0)) {
7836 pgiver = p0;
7837 } else if (!fc_strcasecmp(plrx, plr1)) {
7838 pgiver = p1;
7839 } else {
7840 log_error("Clause giver %s is not participant of the treaty"
7841 "between %s and %s", plrx, plr0, plr1);
7842 }
7843
7844 if (pgiver != NULL) {
7845 int value;
7846
7847 value = secfile_lookup_int_default(loading->file, 0,
7848 "treaty%d.clause%d.value",
7849 tidx, cidx);
7850
7851 add_clause(ptreaty, pgiver, type, value, NULL);
7852 }
7853 }
7854 }
7855
7856 /* These must be after clauses have been added so that acceptance
7857 * does not get cleared by what seems like changes to the treaty. */
7859 "treaty%d.accept0", tidx);
7861 "treaty%d.accept1", tidx);
7862 }
7863 }
7864}
7865
7866typedef struct {
7867 int tidx;
7870
7871/************************************************************************/
7874static void treaty_save(struct treaty *ptr, void *data_in)
7875{
7876 char tpath[512];
7877 int cidx = 0;
7879
7880 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7881
7882 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7883 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7884 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7885 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7886
7888 char cpath[512];
7889
7890 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7891
7892 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7893 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7894 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7896}
7897
7898/************************************************************************/
7902{
7903 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7904
7906}
7907
7908/* =======================================================================
7909 * Load / save the history report
7910 * ======================================================================= */
7911
7912/************************************************************************/
7916{
7918 int turn;
7919
7920 /* Check status and return if not OK (sg_success FALSE). */
7921 sg_check_ret();
7922
7923 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7924
7925 if (turn != -2) {
7926 hist->turn = turn;
7927 }
7928
7929 if (turn + 1 >= game.info.turn) {
7930 const char *str;
7931
7932 str = secfile_lookup_str(loading->file, "history.title");
7933 sg_failure_ret(str != NULL, "%s", secfile_error());
7934 sz_strlcpy(hist->title, str);
7935 str = secfile_lookup_str(loading->file, "history.body");
7936 sg_failure_ret(str != NULL, "%s", secfile_error());
7937 sz_strlcpy(hist->body, str);
7938 }
7939}
7940
7941/************************************************************************/
7944static void sg_save_history(struct savedata *saving)
7945{
7947
7948 secfile_insert_int(saving->file, hist->turn, "history.turn");
7949
7950 if (hist->turn + 1 >= game.info.turn) {
7951 secfile_insert_str(saving->file, hist->title, "history.title");
7952 secfile_insert_str(saving->file, hist->body, "history.body");
7953 }
7954}
7955
7956/* =======================================================================
7957 * Load / save the mapimg definitions.
7958 * ======================================================================= */
7959
7960/************************************************************************/
7963static void sg_load_mapimg(struct loaddata *loading)
7964{
7965 int mapdef_count, i;
7966
7967 /* Check status and return if not OK (sg_success FALSE). */
7968 sg_check_ret();
7969
7970 /* Clear all defined map images. */
7971 while (mapimg_count() > 0) {
7972 mapimg_delete(0);
7973 }
7974
7976 "mapimg.count");
7977 log_verbose("Saved map image definitions: %d.", mapdef_count);
7978
7979 if (0 >= mapdef_count) {
7980 return;
7981 }
7982
7983 for (i = 0; i < mapdef_count; i++) {
7984 const char *p;
7985
7986 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7987 if (NULL == p) {
7988 log_verbose("[Mapimg %4d] Missing definition.", i);
7989 continue;
7990 }
7991
7992 if (!mapimg_define(p, FALSE)) {
7993 log_error("Invalid map image definition %4d: %s.", i, p);
7994 }
7995
7996 log_verbose("Mapimg %4d loaded.", i);
7997 }
7998}
7999
8000/************************************************************************/
8003static void sg_save_mapimg(struct savedata *saving)
8004{
8005 /* Check status and return if not OK (sg_success FALSE). */
8006 sg_check_ret();
8007
8008 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8009 if (mapimg_count() > 0) {
8010 int i;
8011
8012 for (i = 0; i < mapimg_count(); i++) {
8013 char buf[MAX_LEN_MAPDEF];
8014
8015 mapimg_id2str(i, buf, sizeof(buf));
8016 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8017 }
8018 }
8019}
8020
8021/* =======================================================================
8022 * Sanity checks for loading / saving a game.
8023 * ======================================================================= */
8024
8025/************************************************************************/
8029{
8030 int players;
8031
8032 /* Check status and return if not OK (sg_success FALSE). */
8033 sg_check_ret();
8034
8035 if (game.info.is_new_game) {
8036 /* Nothing to do for new games (or not started scenarios). */
8037 return;
8038 }
8039
8040 /* Old savegames may have maxplayers lower than current player count,
8041 * fix. */
8042 players = normal_player_count();
8043 if (game.server.max_players < players) {
8044 log_verbose("Max players lower than current players, fixing");
8045 game.server.max_players = players;
8046 }
8047
8048 /* Fix ferrying sanity */
8049 players_iterate(pplayer) {
8050 unit_list_iterate_safe(pplayer->units, punit) {
8053 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8059 }
8062
8063 /* Fix stacking issues. We don't rely on the savegame preserving
8064 * alliance invariants (old savegames often did not) so if there are any
8065 * unallied units on the same tile we just bounce them. */
8066 players_iterate(pplayer) {
8068 resolve_unit_stacks(pplayer, aplayer, TRUE);
8071
8072 /* Recalculate the potential buildings for each city. Has caused some
8073 * problems with game random state.
8074 * This also changes the game state if you save the game directly after
8075 * loading it and compare the results. */
8076 players_iterate(pplayer) {
8077 /* Building advisor needs data phase open in order to work */
8078 adv_data_phase_init(pplayer, FALSE);
8079 building_advisor(pplayer);
8080 /* Close data phase again so it can be opened again when game starts. */
8081 adv_data_phase_done(pplayer);
8083
8084 /* Prevent a buggy or intentionally crafted save game from crashing
8085 * Freeciv. See hrm Bug #887748 */
8086 players_iterate(pplayer) {
8087 city_list_iterate(pplayer->cities, pcity) {
8088 worker_task_list_iterate(pcity->task_reqs, ptask) {
8089 if (!worker_task_is_sane(ptask)) {
8090 log_error("[city id: %d] Bad worker task %d.",
8091 pcity->id, ptask->act);
8092 worker_task_list_remove(pcity->task_reqs, ptask);
8093 free(ptask);
8094 ptask = NULL;
8095 }
8099
8100 /* Check worked tiles map */
8101#ifdef FREECIV_DEBUG
8102 if (loading->worked_tiles != NULL) {
8103 /* check the entire map for unused worked tiles */
8104 whole_map_iterate(&(wld.map), ptile) {
8105 if (loading->worked_tiles[ptile->index] != -1) {
8106 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8107 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8108 }
8110 }
8111#endif /* FREECIV_DEBUG */
8112
8113 /* Check researching technologies and goals. */
8115 if (presearch->researching != A_UNSET
8116 && !is_future_tech(presearch->researching)
8117 && (valid_advance_by_number(presearch->researching) == NULL
8119 != TECH_PREREQS_KNOWN))) {
8120 log_sg(_("%s had invalid researching technology."),
8122 presearch->researching = A_UNSET;
8123 }
8124 if (presearch->tech_goal != A_UNSET
8125 && !is_future_tech(presearch->tech_goal)
8126 && (valid_advance_by_number(presearch->tech_goal) == NULL
8129 == TECH_KNOWN))) {
8130 log_sg(_("%s had invalid technology goal."),
8132 presearch->tech_goal = A_UNSET;
8133 }
8134
8137
8138 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8139 players_iterate(pplayer) {
8140 int unique_count[U_LAST];
8141
8142 memset(unique_count, 0, sizeof(unique_count));
8143
8144 unit_list_iterate(pplayer->units, punit) {
8147
8150 log_sg(_("%s has multiple units of type %s though it should be possible "
8151 "to have only one."),
8153 }
8156
8157 players_iterate(pplayer) {
8158 unit_list_iterate_safe(pplayer->units, punit) {
8160 punit->orders.list)) {
8161 log_sg("Invalid unit orders for unit %d.", punit->id);
8163 }
8166
8167 /* Check max rates (rules may have changed since saving) */
8168 players_iterate(pplayer) {
8171
8172 if (0 == strlen(server.game_identifier)
8173 || !is_base64url(server.game_identifier)) {
8174 /* This uses fc_rand(), so random state has to be initialized before. */
8175 randomize_base64url_string(server.game_identifier,
8176 sizeof(server.game_identifier));
8177 }
8178
8179 /* Restore game random state, just in case various initialization code
8180 * inexplicably altered the previously existing state. */
8181 if (!game.info.is_new_game) {
8182 fc_rand_set_state(loading->rstate);
8183 }
8184
8185 /* At the end do the default sanity checks. */
8186 sanity_check();
8187}
8188
8189/************************************************************************/
8193{
8194 /* Check status and return if not OK (sg_success FALSE). */
8195 sg_check_ret();
8196}
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
const char * achievement_rule_name(struct achievement *pach)
struct achievement * achievement_by_rule_name(const char *name)
#define achievements_iterate_end
#define achievements_iterate(_ach_)
static struct action * actions[MAX_NUM_ACTIONS]
Definition actions.c:57
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:417
#define NUM_ACTIONS
Definition actions.h:59
#define action_id_get_activity(act_id)
Definition actions.h:462
#define ACTION_NONE
Definition actions.h:55
void building_advisor(struct player *pplayer)
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:263
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:566
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
int ai_type_get_count(void)
Definition ai.c:327
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define ai_type_iterate_end
Definition ai.h:372
#define ai_type_iterate(NAME_ai)
Definition ai.h:365
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:142
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:174
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
void citizens_init(struct city *pcity)
Definition citizens.c:32
void citizens_update(struct city *pcity, struct player *plr)
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:148
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c:1145
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
const char * city_style_rule_name(const int style)
Definition city.c:1765
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3455
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2870
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1180
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3382
void destroy_city_virtual(struct city *pcity)
Definition city.c:3541
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:514
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define cities_iterate(pcity)
Definition city.h:509
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:83
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define output_type_iterate(output)
Definition city.h:842
#define FREE_WORKED_TILES
Definition city.h:879
#define MAX_CITY_SIZE
Definition city.h:103
#define city_list_iterate_end
Definition city.h:507
#define I_NEVER
Definition city.h:244
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define output_type_iterate_end
Definition city.h:848
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2776
bool send_city_suppression(bool now)
Definition citytools.c:2170
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:136
void city_thaw_workers(struct city *pcity)
Definition citytools.c:146
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2847
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3451
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:366
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:851
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
char * incite_cost
Definition comments.c:76
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
int counter_index(const struct counter *pcount)
Definition counters.c:174
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
int counters_get_city_counters_count(void)
Definition counters.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:108
struct treaty * ptreaty
Definition diplodlg_g.h:28
void treaty_add(struct treaty *ptreaty)
Definition diptreaty.c:377
void init_treaty(struct treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
bool add_clause(struct treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
#define clause_list_iterate_end
Definition diptreaty.h:73
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:71
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1128
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h:213
int Tech_type_id
Definition fc_types.h:236
unsigned char citizens
Definition fc_types.h:247
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:126
#define MAX_LEN_NAME
Definition fc_types.h:66
@ O_LAST
Definition fc_types.h:101
int Multiplier_type_id
Definition fc_types.h:245
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct unit * game_unit_by_number(int id)
Definition game.c:115
void initialize_globals(void)
Definition game.c:688
struct city * game_city_by_number(int id)
Definition game.c:106
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h: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:114
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
struct impr_type * improvement_by_number(const Impr_type_id id)
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c:502
void adv_city_alloc(struct city *pcity)
Definition infracache.c:489
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_fatal(message,...)
Definition log.h:101
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1804
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2021
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1820
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1843
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1916
void map_init_topology(struct civ_map *nmap)
Definition map.c:315
void main_map_allocate(void)
Definition map.c:534
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_startpos_count(void)
Definition map.c:2008
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1903
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1787
#define map_startpos_iterate(NAME_psp)
Definition map.h:136
#define map_startpos_iterate_end
Definition map.h:139
#define whole_map_iterate(_map, _tile)
Definition map.h:573
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define whole_map_iterate_end
Definition map.h:582
map_generator
Definition map_types.h:46
@ MAPGEN_SCENARIO
Definition map_types.h:47
void assign_continent_numbers(void)
void player_map_init(struct player *pplayer)
Definition maphand.c:1226
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1472
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2171
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:899
bool send_tile_suppression(bool now)
Definition maphand.c:473
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:343
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1201
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1403
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1372
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1183
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1164
void map_calculate_borders(void)
Definition maphand.c:2329
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1637
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1314
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1207
int mapimg_count(void)
Definition mapimg.c:573
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
void set_meta_patches_string(const char *string)
Definition meta.c:172
char * meta_addr_port(void)
Definition meta.c:203
const char * default_meta_patches_string(void)
Definition meta.c:83
const char * get_meta_patches_string(void)
Definition meta.c:107
#define DEFAULT_META_SERVER_ADDR
Definition meta.h:21
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
static struct nation_type * nations
Definition nation.c:46
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nation_hash_iterate_end
Definition nation.h:95
#define NO_NATION_SELECTED
Definition nation.h:30
void event_cache_load(struct section_file *file, const char *section)
Definition notify.c:783
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:903
int parts
Definition packhand.c:132
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
int player_count(void)
Definition player.c:817
int player_slot_count(void)
Definition player.c:418
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:463
int player_number(const struct player *pplayer)
Definition player.c:837
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:159
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_max_used_number(void)
Definition player.c:476
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
struct player * player_by_name(const char *name)
Definition player.c:881
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:240
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
int player_index(const struct player *pplayer)
Definition player.c:829
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:861
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1497
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1489
#define players_iterate_end
Definition player.h:542
dipl_reason
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:194
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:194
#define players_iterate(_pplayer)
Definition player.h:537
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:560
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define player_slots_iterate(_pslot)
Definition player.h:528
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:562
#define players_iterate_alive_end
Definition player.h:552
#define player_slots_iterate_end
Definition player.h:532
#define players_iterate_alive(_pplayer)
Definition player.h:547
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2270
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1896
int normal_player_count(void)
Definition plrhand.c:3209
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2059
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2458
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2408
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3255
void shuffle_players(void)
Definition plrhand.c:2383
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1945
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1620
void assign_player_colors(void)
Definition plrhand.c:1736
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3242
void fit_nationset_to_players(void)
Definition plrhand.c:2664
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
bool fc_rand_is_init(void)
Definition rand.c:200
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:51
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
bool entry_str_set_gt_marking(struct entry *pentry, bool gt_marking)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
float secfile_lookup_float_default(const struct section_file *secfile, float def, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
#define secfile_insert_int_vec(secfile, values, dim, path,...)
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define secfile_insert_float(secfile, value, path,...)
struct history_report * history_report_get(void)
Definition report.c:1859
const char * universal_rule_name(const struct universal *psource)
const char * universal_type_rule_name(const struct universal *psource)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:668
const char * research_name_translation(const struct research *presearch)
Definition research.c:156
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:637
struct research * research_by_number(int number)
Definition research.c:118
int research_number(const struct research *presearch)
Definition research.c:109
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1353
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
void research_update(struct research *presearch)
Definition research.c:501
#define researches_iterate(_presearch)
Definition research.h:155
#define researches_iterate_end
Definition research.h:158
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Definition rgbcolor.c:74
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, char *path,...)
Definition rgbcolor.c:121
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9188
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:226
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:236
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:147
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:248
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:198
#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:7944
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1198
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2755
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3019
static void unit_ordering_apply(void)
Definition savegame3.c:1079
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3710
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:3591
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3250
bool sg_success
Definition savecompat.c:34
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:152
static char * quote_block(const void *const data, int length)
Definition savegame3.c:897
#define halfbyte_iterate_extras_end
Definition savegame3.c:260
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:255
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2814
static enum unit_orders char2order(char order)
Definition savegame3.c:710
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:918
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:3082
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3552
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4165
#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:7874
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5658
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5610
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5042
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2918
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:6133
static char activity2char(int activity)
Definition savegame3.c:823
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:679
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1336
static enum unit_activity char2activity(char activity)
Definition savegame3.c:874
static void unit_ordering_calc(void)
Definition savegame3.c:1050
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2664
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6064
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1250
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2435
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3195
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7596
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3508
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:172
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2041
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2394
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1775
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6632
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7915
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7901
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3372
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7698
static void savegame3_save_real(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:527
#define TOKEN_SIZE
Definition savegame3.c:276
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2473
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2499
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2088
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:698
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4226
static char order2char(enum unit_orders order)
Definition savegame3.c:737
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7791
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2587
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1133
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6685
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2243
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1165
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1263
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7426
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:5161
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1227
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8192
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7963
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6951
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7031
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2064
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2873
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7114
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2958
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:8003
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:7304
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2702
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3108
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:623
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3970
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:2986
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1299
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7771
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3050
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8028
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7760
void savegame3_load(struct section_file *file)
Definition savegame3.c:458
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1100
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2263
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4716
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2484
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2680
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3647
void script_server_state_save(struct section_file *file)
void script_server_state_load(struct section_file *file)
void settings_game_load(struct section_file *file, const char *section)
Definition settings.c:4913
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4825
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
sex_t sex_by_name(const char *name)
Definition sex.c:27
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
bool str_to_int(const char *str, int *pint)
Definition shared.c:515
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
bool is_base64url(const char *s)
Definition shared.c:321
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1923
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:343
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX_LEN_PATH
Definition shared.h:32
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
@ SSHIP_LAUNCHED
Definition spaceship.h:85
@ SSHIP_NONE
Definition spaceship.h:84
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
void server_game_init(bool keep_ruleset_value)
Definition srv_main.c:3497
const char * aifill(int amount)
Definition srv_main.c:2506
bool game_was_started(void)
Definition srv_main.c:354
void identity_number_reserve(int id)
Definition srv_main.c:2035
struct server_arguments srvarg
Definition srv_main.c:181
void init_game_seed(void)
Definition srv_main.c:208
void update_nations_with_startpos(void)
Definition srv_main.c:2311
enum server_states server_state(void)
Definition srv_main.c:338
void server_game_free(void)
Definition srv_main.c:3521
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
Definition city.h:317
size_t length
Definition city.h:414
bool multiresearch
Definition game.h: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:64
struct section_file * file
Definition savecompat.h:48
int great_wonder_owners[B_LAST]
bool global_advances[A_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char version[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char datafile[MAX_LEN_NAME]
char authors[MAX_LEN_PACKET/3]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:116
struct ai_trait * traits
Definition player.h:126
enum barbarian_type barbarian_type
Definition player.h:122
int science_cost
Definition player.h:119
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:124
int expand
Definition player.h:118
int fuzzy
Definition player.h:117
enum diplstate_type type
Definition player.h:199
int infra_points
Definition player.h:67
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int angry
Definition player.h:89
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:281
int bulbs_last_turn
Definition player.h:351
struct player_ai ai_common
Definition player.h:288
bv_plr_flags flags
Definition player.h:292
bool is_male
Definition player.h:257
int wonders[B_LAST]
Definition player.h:305
bool unassigned_ranked
Definition player.h:255
struct government * target_government
Definition player.h:259
int autoselect_weight
Definition player.h:299
char username[MAX_LEN_NAME]
Definition player.h:252
int revolution_finishes
Definition player.h:273
int nturns_idle
Definition player.h:265
struct government * government
Definition player.h:258
struct team * team
Definition player.h:261
int turns_alive
Definition player.h:266
const struct ai_type * ai
Definition player.h:289
struct unit_list * units
Definition player.h:282
char ranked_username[MAX_LEN_NAME]
Definition player.h:254
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
bv_player real_embassy
Definition player.h:277
struct player::@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:7868
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:467
struct team * team_new(struct team_slot *tslot)
Definition team.c:317
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:244
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:271
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:272
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:240
void init_tech(struct research *research, bool update)
Definition techtools.c:1094
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:255
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:272
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1097
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
void tile_set_worked(struct tile *ptile, struct city *pcity)
Definition tile.c:106
#define tile_index(_pt_)
Definition tile.h:89
#define tile_worked(_tile)
Definition tile.h:115
#define tile_terrain(_tile)
Definition tile.h:111
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
void timer_stop(struct timer *t)
Definition timing.c:305
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:379
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
void free_unit_orders(struct unit *punit)
Definition unit.c:1806
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2447
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1274
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2518
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:865
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1661
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2726
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target, enum gen_action trigger_action)
Definition unit.c:1132
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1766
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1284
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1114
#define unit_tile(_pu)
Definition unit.h:404
#define BATTLEGROUP_NONE
Definition unit.h:193
unit_orders
Definition unit.h:38
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#define unit_owner(_pu)
Definition unit.h:403
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1401
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5004
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1225
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1062
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1773
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1593
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2631
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1566
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define unit_type_iterate(_p)
Definition unittype.h:862
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:869
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:129
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT