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 store random_seed for documentation purposes only,
2207 * we don't need it. Just silence "unused entry" warning. */
2208 (void) secfile_entry_lookup(loading->file, "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_int_default(loading->file, 0, "game.last_turn_change_time") / 100.0;
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
2740 pcity = game_city_by_number(city_count[0]);
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 store random_seed for documentation purposes only,
2836 * we don't need it. Just silence "unused entry" warning. */
2837 (void) secfile_entry_lookup(loading->file, "map.random_seed");
2838
2839 if (S_S_INITIAL == loading->server_state
2841 /* Generator MAPGEN_SCENARIO is used;
2842 * this map was done with the map editor. */
2843
2844 /* Load tiles. */
2848
2849 /* Nothing more needed for a scenario. */
2850 return;
2851 }
2852
2853 if (S_S_INITIAL == loading->server_state) {
2854 /* Nothing more to do if it is not a scenario but in initial state. */
2855 return;
2856 }
2857
2859 if (wld.map.altitude_info) {
2861 }
2867}
2868
2869/************************************************************************/
2872static void sg_save_map(struct savedata *saving)
2873{
2874 /* Check status and return if not OK (sg_success FALSE). */
2875 sg_check_ret();
2876
2877 if (map_is_empty()) {
2878 /* No map. */
2879 return;
2880 }
2881
2882 if (saving->scenario) {
2884 "map.have_huts");
2886 "map.have_resources");
2887 } else {
2888 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2889 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2890 }
2891
2892 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2893
2894 /* For debugging purposes only.
2895 * Do not save it if it's 0 (not known);
2896 * this confuses people reading this 'document' less than
2897 * saving 0. */
2898 if (wld.map.server.seed) {
2900 "map.random_seed");
2901 }
2902
2904 if (wld.map.altitude_info) {
2906 }
2912}
2913
2914/************************************************************************/
2918{
2919 /* Check status and return if not OK (sg_success FALSE). */
2920 sg_check_ret();
2921
2922 /* Initialize the map for the current topology. 'map.xsize' and
2923 * 'map.ysize' must be set. */
2925
2926 /* Allocate map. */
2928
2929 /* get the terrain type */
2930 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2931 "map.t%04d");
2933
2934 /* Check for special tile sprites. */
2935 whole_map_iterate(&(wld.map), ptile) {
2936 const char *spec_sprite;
2937 const char *label;
2938 int nat_x, nat_y;
2939
2941 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2942 nat_x, nat_y);
2943 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2944 nat_x, nat_y);
2945 if (NULL != ptile->spec_sprite) {
2946 ptile->spec_sprite = fc_strdup(spec_sprite);
2947 }
2948 if (label != NULL) {
2949 tile_set_label(ptile, label);
2950 }
2952}
2953
2954/************************************************************************/
2958{
2959 /* Check status and return if not OK (sg_success FALSE). */
2960 sg_check_ret();
2961
2962 /* Save the terrain type. */
2963 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2964 "map.t%04d");
2965
2966 /* Save special tile sprites. */
2967 whole_map_iterate(&(wld.map), ptile) {
2968 int nat_x, nat_y;
2969
2971 if (ptile->spec_sprite) {
2972 secfile_insert_str(saving->file, ptile->spec_sprite,
2973 "map.spec_sprite_%d_%d", nat_x, nat_y);
2974 }
2975 if (ptile->label != NULL) {
2976 secfile_insert_str(saving->file, ptile->label,
2977 "map.label_%d_%d", nat_x, nat_y);
2978 }
2980}
2981
2982/************************************************************************/
2986{
2987 int y;
2988
2989 /* Check status and return if not OK (sg_success FALSE). */
2990 sg_check_ret();
2991
2992 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
2993 const char *buffer = secfile_lookup_str(loading->file,
2994 "map.alt%04d", y);
2995 const char *ptr = buffer;
2996 int x;
2997
2998 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
2999
3000 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3001 char token[TOKEN_SIZE];
3002 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3003 int number;
3004
3005 scanin(&ptr, ",", token, sizeof(token));
3006 sg_failure_ret(token[0] != '\0',
3007 "Map size not correct (map.alt%d).", y);
3008 sg_failure_ret(str_to_int(token, &number),
3009 "Got map alt %s in (%d, %d).", token, x, y);
3010 ptile->altitude = number;
3011 }
3012 }
3013}
3014
3015/************************************************************************/
3019{
3020 int y;
3021
3022 /* Check status and return if not OK (sg_success FALSE). */
3023 sg_check_ret();
3024
3025 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3027 int x;
3028
3029 line[0] = '\0';
3030 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3031 char token[TOKEN_SIZE];
3032 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3033
3034 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3035
3036 strcat(line, token);
3037 if (x + 1 < MAP_NATIVE_WIDTH) {
3038 strcat(line, ",");
3039 }
3040 }
3041
3042 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3043 }
3044}
3045
3046/************************************************************************/
3050{
3051 /* Check status and return if not OK (sg_success FALSE). */
3052 sg_check_ret();
3053
3054 /* Load extras. */
3055 halfbyte_iterate_extras(j, loading->extra.size) {
3056 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3057 loading->extra.order + 4 * j),
3058 loading->file, "map.e%02d_%04d", j);
3060
3061 if (S_S_INITIAL != loading->server_state
3064 whole_map_iterate(&(wld.map), ptile) {
3066 if (tile_has_extra(ptile, pres)) {
3067 tile_set_resource(ptile, pres);
3068
3069 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3070 BV_CLR(ptile->extras, extra_index(pres));
3071 }
3072 }
3075 }
3076}
3077
3078/************************************************************************/
3082{
3083 /* Check status and return if not OK (sg_success FALSE). */
3084 sg_check_ret();
3085
3086 /* Save extras. */
3088 int mod[4];
3089 int l;
3090
3091 for (l = 0; l < 4; l++) {
3092 if (4 * j + 1 > game.control.num_extra_types) {
3093 mod[l] = -1;
3094 } else {
3095 mod[l] = 4 * j + l;
3096 }
3097 }
3098 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3099 saving->file, "map.e%02d_%04d", j);
3101}
3102
3103/************************************************************************/
3108{
3109 struct nation_type *pnation;
3110 struct startpos *psp;
3111 struct tile *ptile;
3112 const char SEPARATOR = '#';
3113 const char *nation_names;
3114 int nat_x, nat_y;
3115 bool exclude;
3116 int i, startpos_count;
3117
3118 /* Check status and return if not OK (sg_success FALSE). */
3119 sg_check_ret();
3120
3122 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3123
3124 if (0 == startpos_count) {
3125 /* Nothing to do. */
3126 return;
3127 }
3128
3129 for (i = 0; i < startpos_count; i++) {
3130 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3131 || !secfile_lookup_int(loading->file, &nat_y,
3132 "map.startpos%d.y", i)) {
3133 log_sg("Warning: Undefined coordinates for startpos %d", i);
3134 continue;
3135 }
3136
3137 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3138 if (NULL == ptile) {
3139 log_error("Start position native coordinates (%d, %d) do not exist "
3140 "in this map. Skipping...", nat_x, nat_y);
3141 continue;
3142 }
3143
3144 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3145 "map.startpos%d.exclude", i);
3146
3147 psp = map_startpos_new(ptile);
3148
3150 "map.startpos%d.nations", i);
3151 if (NULL != nation_names && '\0' != nation_names[0]) {
3152 const size_t size = strlen(nation_names) + 1;
3153 char buf[size], *start, *end;
3154
3156 for (start = buf - 1; NULL != start; start = end) {
3157 start++;
3158 if ((end = strchr(start, SEPARATOR))) {
3159 *end = '\0';
3160 }
3161
3162 pnation = nation_by_rule_name(start);
3163 if (NO_NATION_SELECTED != pnation) {
3164 if (exclude) {
3165 startpos_disallow(psp, pnation);
3166 } else {
3167 startpos_allow(psp, pnation);
3168 }
3169 } else {
3170 log_verbose("Missing nation \"%s\".", start);
3171 }
3172 }
3173 }
3174 }
3175
3176 if (0 < map_startpos_count()
3177 && loading->server_state == S_S_INITIAL
3179 log_verbose("Number of starts (%d) are lower than rules.max_players "
3180 "(%d), lowering rules.max_players.",
3183 }
3184
3185 /* Re-initialize nation availability in light of start positions.
3186 * This has to be after loading [scenario] and [map].startpos and
3187 * before we seek nations for players. */
3189}
3190
3191/************************************************************************/
3195{
3196 struct tile *ptile;
3197 const char SEPARATOR = '#';
3198 int i = 0;
3199
3200 /* Check status and return if not OK (sg_success FALSE). */
3201 sg_check_ret();
3202
3204 return;
3205 }
3206
3208 "map.startpos_count");
3209
3211 int nat_x, nat_y;
3212
3213 ptile = startpos_tile(psp);
3214
3216 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3217 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3218
3220 "map.startpos%d.exclude", i);
3221 if (startpos_allows_all(psp)) {
3222 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3223 } else {
3224 const struct nation_hash *nations = startpos_raw_nations(psp);
3226
3227 nation_names[0] = '\0';
3228 nation_hash_iterate(nations, pnation) {
3229 if ('\0' == nation_names[0]) {
3231 sizeof(nation_names));
3232 } else {
3234 "%c%s", SEPARATOR, nation_rule_name(pnation));
3235 }
3238 "map.startpos%d.nations", i);
3239 }
3240 i++;
3242
3244}
3245
3246/************************************************************************/
3250{
3251 int y;
3252 struct tile *claimer = NULL;
3253 struct extra_type *placing = NULL;
3254
3255 /* Check status and return if not OK (sg_success FALSE). */
3256 sg_check_ret();
3257
3258 if (game.info.is_new_game) {
3259 /* No owner/source information for a new game / scenario. */
3260 return;
3261 }
3262
3263 /* Owner, ownership source, and infra turns are stored as plain numbers */
3264 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3265 const char *buffer1 = secfile_lookup_str(loading->file,
3266 "map.owner%04d", y);
3267 const char *buffer2 = secfile_lookup_str(loading->file,
3268 "map.source%04d", y);
3269 const char *buffer3 = secfile_lookup_str(loading->file,
3270 "map.eowner%04d", y);
3272 NULL,
3273 "map.placing%04d", y);
3275 NULL,
3276 "map.infra_turns%04d", y);
3277 const char *ptr1 = buffer1;
3278 const char *ptr2 = buffer2;
3279 const char *ptr3 = buffer3;
3280 const char *ptr_placing = buffer_placing;
3281 const char *ptr_turns = buffer_turns;
3282 int x;
3283
3287
3288 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3289 char token1[TOKEN_SIZE];
3290 char token2[TOKEN_SIZE];
3291 char token3[TOKEN_SIZE];
3293 char token_turns[TOKEN_SIZE];
3294 struct player *owner = NULL;
3295 struct player *eowner = NULL;
3296 int turns;
3297 int number;
3298 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3299
3300 scanin(&ptr1, ",", token1, sizeof(token1));
3301 sg_failure_ret(token1[0] != '\0',
3302 "Map size not correct (map.owner%d).", y);
3303 if (strcmp(token1, "-") == 0) {
3304 owner = NULL;
3305 } else {
3307 "Got map owner %s in (%d, %d).", token1, x, y);
3308 owner = player_by_number(number);
3309 }
3310
3311 scanin(&ptr2, ",", token2, sizeof(token2));
3312 sg_failure_ret(token2[0] != '\0',
3313 "Map size not correct (map.source%d).", y);
3314 if (strcmp(token2, "-") == 0) {
3315 claimer = NULL;
3316 } else {
3318 "Got map source %s in (%d, %d).", token2, x, y);
3319 claimer = index_to_tile(&(wld.map), number);
3320 }
3321
3322 scanin(&ptr3, ",", token3, sizeof(token3));
3323 sg_failure_ret(token3[0] != '\0',
3324 "Map size not correct (map.eowner%d).", y);
3325 if (strcmp(token3, "-") == 0) {
3326 eowner = NULL;
3327 } else {
3329 "Got base owner %s in (%d, %d).", token3, x, y);
3330 eowner = player_by_number(number);
3331 }
3332
3333 if (ptr_placing != NULL) {
3335 sg_failure_ret(token_placing[0] != '\0',
3336 "Map size not correct (map.placing%d).", y);
3337 if (strcmp(token_placing, "-") == 0) {
3338 placing = NULL;
3339 } else {
3341 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3342 placing = extra_by_number(number);
3343 }
3344 } else {
3345 placing = NULL;
3346 }
3347
3348 if (ptr_turns != NULL) {
3349 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3350 sg_failure_ret(token_turns[0] != '\0',
3351 "Map size not correct (map.infra_turns%d).", y);
3353 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3354 turns = number;
3355 } else {
3356 turns = 1;
3357 }
3358
3360 tile_claim_bases(ptile, eowner);
3361 ptile->placing = placing;
3362 ptile->infra_turns = turns;
3363 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3364 }
3365 }
3366}
3367
3368/************************************************************************/
3372{
3373 int y;
3374
3375 /* Check status and return if not OK (sg_success FALSE). */
3376 sg_check_ret();
3377
3378 if (saving->scenario && !saving->save_players) {
3379 /* Nothing to do for a scenario without saved players. */
3380 return;
3381 }
3382
3383 /* Store owner and ownership source as plain numbers. */
3384 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3386 int x;
3387
3388 line[0] = '\0';
3389 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3390 char token[TOKEN_SIZE];
3391 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3392
3393 if (!saving->save_players || tile_owner(ptile) == NULL) {
3394 strcpy(token, "-");
3395 } else {
3396 fc_snprintf(token, sizeof(token), "%d",
3397 player_number(tile_owner(ptile)));
3398 }
3399 strcat(line, token);
3400 if (x + 1 < MAP_NATIVE_WIDTH) {
3401 strcat(line, ",");
3402 }
3403 }
3404
3405 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3406 }
3407
3408 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3410 int x;
3411
3412 line[0] = '\0';
3413 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3414 char token[TOKEN_SIZE];
3415 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3416
3417 if (ptile->claimer == NULL) {
3418 strcpy(token, "-");
3419 } else {
3420 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3421 }
3422 strcat(line, token);
3423 if (x + 1 < MAP_NATIVE_WIDTH) {
3424 strcat(line, ",");
3425 }
3426 }
3427
3428 secfile_insert_str(saving->file, line, "map.source%04d", y);
3429 }
3430
3431 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3433 int x;
3434
3435 line[0] = '\0';
3436 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3437 char token[TOKEN_SIZE];
3438 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3439
3440 if (!saving->save_players || extra_owner(ptile) == NULL) {
3441 strcpy(token, "-");
3442 } else {
3443 fc_snprintf(token, sizeof(token), "%d",
3444 player_number(extra_owner(ptile)));
3445 }
3446 strcat(line, token);
3447 if (x + 1 < MAP_NATIVE_WIDTH) {
3448 strcat(line, ",");
3449 }
3450 }
3451
3452 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3453 }
3454
3455 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3457 int x;
3458
3459 line[0] = '\0';
3460 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3461 char token[TOKEN_SIZE];
3462 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3463
3464 if (ptile->placing == NULL) {
3465 strcpy(token, "-");
3466 } else {
3467 fc_snprintf(token, sizeof(token), "%d",
3468 extra_number(ptile->placing));
3469 }
3470 strcat(line, token);
3471 if (x + 1 < MAP_NATIVE_WIDTH) {
3472 strcat(line, ",");
3473 }
3474 }
3475
3476 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3477 }
3478
3479 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3481 int x;
3482
3483 line[0] = '\0';
3484 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3485 char token[TOKEN_SIZE];
3486 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3487
3488 if (ptile->placing != NULL) {
3489 fc_snprintf(token, sizeof(token), "%d",
3490 ptile->infra_turns);
3491 } else {
3492 fc_snprintf(token, sizeof(token), "0");
3493 }
3494 strcat(line, token);
3495 if (x + 1 < MAP_NATIVE_WIDTH) {
3496 strcat(line, ",");
3497 }
3498 }
3499
3500 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3501 }
3502}
3503
3504/************************************************************************/
3508{
3509 int x, y;
3510
3511 /* Check status and return if not OK (sg_success FALSE). */
3512 sg_check_ret();
3513
3514 sg_failure_ret(loading->worked_tiles == NULL,
3515 "City worked map not loaded!");
3516
3517 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3518 sizeof(*loading->worked_tiles));
3519
3520 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3521 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3522 y);
3523 const char *ptr = buffer;
3524
3525 sg_failure_ret(NULL != buffer,
3526 "Savegame corrupt - map line %d not found.", y);
3527 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3528 char token[TOKEN_SIZE];
3529 int number;
3530 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3531
3532 scanin(&ptr, ",", token, sizeof(token));
3533 sg_failure_ret('\0' != token[0],
3534 "Savegame corrupt - map size not correct.");
3535 if (strcmp(token, "-") == 0) {
3536 number = -1;
3537 } else {
3538 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3539 "Savegame corrupt - got tile worked by city "
3540 "id=%s in (%d, %d).", token, x, y);
3541 }
3542
3543 loading->worked_tiles[ptile->index] = number;
3544 }
3545 }
3546}
3547
3548/************************************************************************/
3552{
3553 int x, y;
3554
3555 /* Check status and return if not OK (sg_success FALSE). */
3556 sg_check_ret();
3557
3558 if (saving->scenario && !saving->save_players) {
3559 /* Nothing to do for a scenario without saved players. */
3560 return;
3561 }
3562
3563 /* Additionally save the tiles worked by the cities */
3564 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3566
3567 line[0] = '\0';
3568 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3569 char token[TOKEN_SIZE];
3570 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3571 struct city *pcity = tile_worked(ptile);
3572
3573 if (pcity == NULL) {
3574 strcpy(token, "-");
3575 } else {
3576 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3577 }
3578 strcat(line, token);
3579 if (x < MAP_NATIVE_WIDTH) {
3580 strcat(line, ",");
3581 }
3582 }
3583 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3584 }
3585}
3586
3587/************************************************************************/
3591{
3592 /* Check status and return if not OK (sg_success FALSE). */
3593 sg_check_ret();
3594
3595 players_iterate(pplayer) {
3596 /* Allocate player private map here; it is needed in different modules
3597 * besides this one ((i.e. sg_load_player_*()). */
3598 player_map_init(pplayer);
3600
3602 "game.save_known")) {
3603 int lines = player_slot_max_used_number()/32 + 1, j, p, l, i;
3604 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3605
3606 for (l = 0; l < lines; l++) {
3607 for (j = 0; j < 8; j++) {
3608 for (i = 0; i < 4; i++) {
3609 /* Only bother trying to load the map for this halfbyte if at least
3610 * one of the corresponding player slots is in use. */
3611 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3612 LOAD_MAP_CHAR(ch, ptile,
3613 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3614 |= ascii_hex2bin(ch, j),
3615 loading->file, "map.k%02d_%04d", l * 8 + j);
3616 break;
3617 }
3618 }
3619 }
3620 }
3621
3622 players_iterate(pplayer) {
3623 dbv_clr_all(&pplayer->tile_known);
3625
3626 /* HACK: we read the known data from hex into 32-bit integers, and
3627 * now we convert it to the known tile data of each player. */
3628 whole_map_iterate(&(wld.map), ptile) {
3629 players_iterate(pplayer) {
3630 p = player_index(pplayer);
3631 l = player_index(pplayer) / 32;
3632
3633 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3634 map_set_known(ptile, pplayer);
3635 }
3638
3639 FC_FREE(known);
3640 }
3641}
3642
3643/************************************************************************/
3647{
3648 /* Check status and return if not OK (sg_success FALSE). */
3649 sg_check_ret();
3650
3651 if (!saving->save_players) {
3652 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3653 return;
3654 } else {
3655 int lines = player_slot_max_used_number()/32 + 1;
3656
3658 "game.save_known");
3660 int j, p, l, i;
3661 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3662
3663 /* HACK: we convert the data into a 32-bit integer, and then save it as
3664 * hex. */
3665
3666 whole_map_iterate(&(wld.map), ptile) {
3667 players_iterate(pplayer) {
3668 if (map_is_known(ptile, pplayer)) {
3669 p = player_index(pplayer);
3670 l = p / 32;
3671 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3672 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3673 }
3676
3677 for (l = 0; l < lines; l++) {
3678 for (j = 0; j < 8; j++) {
3679 for (i = 0; i < 4; i++) {
3680 /* Only bother saving the map for this halfbyte if at least one
3681 * of the corresponding player slots is in use */
3682 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3683 /* put 4-bit segments of the 32-bit "known" field */
3685 + tile_index(ptile)], j),
3686 saving->file, "map.k%02d_%04d", l * 8 + j);
3687 break;
3688 }
3689 }
3690 }
3691 }
3692
3693 FC_FREE(known);
3694 }
3695 }
3696}
3697
3698/* =======================================================================
3699 * Load / save player data.
3700 *
3701 * This is splitted into two parts as some data can only be loaded if the
3702 * number of players is known and the corresponding player slots are
3703 * defined.
3704 * ======================================================================= */
3705
3706/************************************************************************/
3710{
3711 int i, k, nplayers;
3712 const char *str;
3713 bool shuffle_loaded = TRUE;
3714
3715 /* Check status and return if not OK (sg_success FALSE). */
3716 sg_check_ret();
3717
3718 if (S_S_INITIAL == loading->server_state
3719 || game.info.is_new_game) {
3720 /* Nothing more to do. */
3721 return;
3722 }
3723
3724 /* Load destroyed wonders: */
3726 "players.destroyed_wonders");
3727 sg_failure_ret(str != NULL, "%s", secfile_error());
3728 sg_failure_ret(strlen(str) == loading->improvement.size,
3729 "Invalid length for 'players.destroyed_wonders' ("
3730 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3731 strlen(str), loading->improvement.size);
3732 for (k = 0; k < loading->improvement.size; k++) {
3733 sg_failure_ret(str[k] == '1' || str[k] == '0',
3734 "Undefined value '%c' within "
3735 "'players.destroyed_wonders'.", str[k]);
3736
3737 if (str[k] == '1') {
3738 struct impr_type *pimprove =
3739 improvement_by_rule_name(loading->improvement.order[k]);
3740 if (pimprove) {
3743 }
3744 }
3745 }
3746
3747 server.identity_number
3748 = secfile_lookup_int_default(loading->file, server.identity_number,
3749 "players.identity_number_used");
3750
3751 /* First remove all defined players. */
3752 players_iterate(pplayer) {
3753 server_remove_player(pplayer);
3755
3756 /* Now, load the players from the savefile. */
3757 player_slots_iterate(pslot) {
3758 struct player *pplayer;
3759 struct rgbcolor *prgbcolor = NULL;
3760 int pslot_id = player_slot_index(pslot);
3761
3762 if (NULL == secfile_section_lookup(loading->file, "player%d",
3763 pslot_id)) {
3764 continue;
3765 }
3766
3767 /* Get player AI type. */
3768 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3769 player_slot_index(pslot));
3770 sg_failure_ret(str != NULL, "%s", secfile_error());
3771
3772 /* Get player color */
3773 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3774 pslot_id)) {
3775 if (game_was_started()) {
3776 log_sg("Game has started, yet player %d has no color defined.",
3777 pslot_id);
3778 /* This will be fixed up later */
3779 } else {
3780 log_verbose("No color defined for player %d.", pslot_id);
3781 /* Colors will be assigned on game start, or at end of savefile
3782 * loading if game has already started */
3783 }
3784 }
3785
3786 /* Create player. */
3787 pplayer = server_create_player(player_slot_index(pslot), str,
3788 prgbcolor,
3791 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3792
3793 server_player_init(pplayer, FALSE, FALSE);
3794
3795 /* Free the color definition. */
3797
3798 /* Multipliers (policies) */
3799
3800 /* First initialise player values with ruleset defaults; this will
3801 * cover any in the ruleset not known when the savefile was created. */
3802 multipliers_iterate(pmul) {
3803 pplayer->multipliers[multiplier_index(pmul)].value
3804 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3806
3807 /* Now override with any values from the savefile. */
3808 for (k = 0; k < loading->multiplier.size; k++) {
3809 const struct multiplier *pmul = loading->multiplier.order[k];
3810
3811 if (pmul) {
3813 int val =
3815 "player%d.multiplier%d.val",
3816 player_slot_index(pslot), k);
3817 int rval = (((CLIP(pmul->start, val, pmul->stop)
3818 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3819
3820 if (rval != val) {
3821 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3822 "was %d, clamped to %d", pslot_id,
3823 multiplier_rule_name(pmul), val, rval);
3824 }
3825 pplayer->multipliers[idx].value = rval;
3826
3827 val =
3829 pplayer->multipliers[idx].value,
3830 "player%d.multiplier%d.target",
3831 player_slot_index(pslot), k);
3832 rval = (((CLIP(pmul->start, val, pmul->stop)
3833 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3834
3835 if (rval != val) {
3836 log_verbose("Player %d had illegal value for multiplier_target "
3837 " \"%s\": was %d, clamped to %d", pslot_id,
3838 multiplier_rule_name(pmul), val, rval);
3839 }
3840 pplayer->multipliers[idx].target = rval;
3841
3842 pplayer->multipliers[idx].changed
3844 "player%d.multiplier%d.changed",
3845 player_slot_index(pslot), k);
3846 } /* else silently discard multiplier not in current ruleset */
3847 }
3848
3849 /* Must be loaded before tile owner is set. */
3850 pplayer->server.border_vision =
3852 "player%d.border_vision",
3853 player_slot_index(pslot));
3854
3856 "player%d.autoselect_weight",
3857 pslot_id);
3859
3860 /* check number of players */
3861 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3862 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3863 "(%d) from the loaded game does not match the number of "
3864 "players present (%d).", nplayers, player_count());
3865
3866 /* Load team informations. */
3867 players_iterate(pplayer) {
3868 int team;
3869 struct team_slot *tslot = NULL;
3870
3872 "player%d.team_no",
3873 player_number(pplayer))
3875 "Invalid team definition for player %s (nb %d).",
3876 player_name(pplayer), player_number(pplayer));
3877 /* Should never fail when slot given is not nullptr */
3878 team_add_player(pplayer, team_new(tslot));
3880
3881 /* Loading the shuffle list is quite complex. At the time of saving the
3882 * shuffle data is saved as
3883 * shuffled_player_<number> = player_slot_id
3884 * where number is an increasing number and player_slot_id is a number
3885 * between 0 and the maximum number of player slots. Now we have to create
3886 * a list
3887 * shuffler_players[number] = player_slot_id
3888 * where all player slot IDs are used exactly one time. The code below
3889 * handles this ... */
3890 if (secfile_lookup_int_default(loading->file, -1,
3891 "players.shuffled_player_%d", 0) >= 0) {
3892 int slots = player_slot_count();
3893 int plrcount = player_count();
3896
3897 for (i = 0; i < slots; i++) {
3898 /* Array to save used numbers. */
3900 /* List of all player IDs (needed for set_shuffled_players()). It is
3901 * initialised with the value -1 to indicate that no value is set. */
3902 shuffled_players[i] = -1;
3903 }
3904
3905 /* Load shuffled player list. */
3906 for (i = 0; i < plrcount; i++) {
3907 int shuffle
3909 "players.shuffled_player_%d", i);
3910
3911 if (shuffle == -1) {
3912 log_sg("Missing player shuffle information (index %d) "
3913 "- reshuffle player list!", i);
3915 break;
3916 } else if (shuffled_player_set[shuffle]) {
3917 log_sg("Player shuffle %d used two times "
3918 "- reshuffle player list!", shuffle);
3920 break;
3921 }
3922 /* Set this ID as used. */
3924
3925 /* Save the player ID in the shuffle list. */
3927 }
3928
3929 if (shuffle_loaded) {
3930 /* Insert missing numbers. */
3931 int shuffle_index = plrcount;
3932
3933 for (i = 0; i < slots; i++) {
3934 if (!shuffled_player_set[i]) {
3936 }
3937
3938 /* shuffle_index must not grow higher than size of shuffled_players. */
3940 "Invalid player shuffle data!");
3941 }
3942
3943#ifdef FREECIV_DEBUG
3944 log_debug("[load shuffle] player_count() = %d", player_count());
3945 player_slots_iterate(pslot) {
3946 int plrid = player_slot_index(pslot);
3947
3948 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3950 shuffled_player_set[plrid] ? "is used" : "-");
3952#endif /* FREECIV_DEBUG */
3953
3954 /* Set shuffle list from savegame. */
3956 }
3957 }
3958
3959 if (!shuffle_loaded) {
3960 /* No shuffled players included or error loading them, so shuffle them
3961 * (this may include scenarios). */
3963 }
3964}
3965
3966/************************************************************************/
3970{
3971 /* Check status and return if not OK (sg_success FALSE). */
3972 sg_check_ret();
3973
3974 if (game.info.is_new_game) {
3975 /* Nothing to do. */
3976 return;
3977 }
3978
3979 players_iterate(pplayer) {
3980 sg_load_player_main(loading, pplayer);
3982 sg_load_player_units(loading, pplayer);
3984
3985 /* Check the success of the functions above. */
3986 sg_check_ret();
3987
3988 /* print out some informations */
3989 if (is_ai(pplayer)) {
3990 log_normal(_("%s has been added as %s level AI-controlled player "
3991 "(%s)."), player_name(pplayer),
3992 ai_level_translated_name(pplayer->ai_common.skill_level),
3993 ai_name(pplayer->ai));
3994 } else {
3995 log_normal(_("%s has been added as human player."),
3996 player_name(pplayer));
3997 }
3999
4000 /* Also load the transport status of the units here. It must be a special
4001 * case as all units must be known (unit on an allied transporter). */
4002 players_iterate(pplayer) {
4003 /* Load unit transport status. */
4006
4007 /* Savegame may contain nation assignments that are incompatible with the
4008 * current nationset. Ensure they are compatible, one way or another. */
4010
4011 /* Some players may have invalid nations in the ruleset. Once all players
4012 * are loaded, pick one of the remaining nations for them. */
4013 players_iterate(pplayer) {
4014 if (pplayer->nation == NO_NATION_SELECTED) {
4017 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4018 log_sg(_("%s had invalid nation; changing to %s."),
4019 player_name(pplayer), nation_plural_for_player(pplayer));
4020
4021 ai_traits_init(pplayer);
4022 }
4024
4025 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4028 if (pplayers_allied(plr, aplayer)) {
4030 DS_ALLIANCE);
4031
4034 log_sg("Illegal alliance structure detected: "
4035 "%s alliance to %s reduced to peace treaty.",
4040 }
4041 }
4044
4045 /* Update cached city illness. This can depend on trade routes,
4046 * so can't be calculated until all players have been loaded. */
4047 if (game.info.illness_on) {
4048 cities_iterate(pcity) {
4049 pcity->server.illness
4050 = city_illness_calc(pcity, NULL, NULL,
4051 &(pcity->illness_trade), NULL);
4053 }
4054
4055 /* Update all city information. This must come after all cities are
4056 * loaded (in player_load) but before player (dumb) cities are loaded
4057 * in player_load_vision(). */
4058 players_iterate(plr) {
4059 city_list_iterate(plr->cities, pcity) {
4060 city_refresh(pcity);
4061 sanity_check_city(pcity);
4062 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4065
4066 /* Since the cities must be placed on the map to put them on the
4067 player map we do this afterwards */
4068 players_iterate(pplayer) {
4070 /* Check the success of the function above. */
4071 sg_check_ret();
4073
4074 /* Check shared vision and tiles. */
4075 players_iterate(pplayer) {
4076 BV_CLR_ALL(pplayer->gives_shared_vision);
4077 BV_CLR_ALL(pplayer->gives_shared_tiles);
4078 BV_CLR_ALL(pplayer->server.really_gives_vision);
4080
4081 /* Set up shared vision... */
4082 players_iterate(pplayer) {
4083 int plr1 = player_index(pplayer);
4084
4086 int plr2 = player_index(pplayer2);
4087
4089 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4090 give_shared_vision(pplayer, pplayer2);
4091 }
4093 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4094 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4095 }
4098
4099 /* ...and check it */
4102 /* TODO: Is there a good reason player is not marked as
4103 * giving shared vision to themselves -> really_gives_vision()
4104 * returning FALSE when pplayer1 == pplayer2 */
4105 if (pplayer1 != pplayer2
4108 sg_regr(3000900,
4109 _("%s did not give shared vision to team member %s."),
4112 }
4114 sg_regr(3000900,
4115 _("%s did not give shared vision to team member %s."),
4118 }
4119 }
4122
4125
4126 /* All vision is ready; this calls city_thaw_workers_queue(). */
4128
4129 /* Make sure everything is consistent. */
4130 players_iterate(pplayer) {
4131 unit_list_iterate(pplayer->units, punit) {
4133 struct tile *ptile = unit_tile(punit);
4134
4135 log_sg("%s doing illegal activity in savegame!",
4137 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4141 : "missing",
4142 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4144 }
4147
4148 cities_iterate(pcity) {
4149 city_refresh(pcity);
4150 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4152
4153 /* Player colors are always needed once game has started. Pre-2.4 savegames
4154 * lack them. This cannot be in compatibility conversion layer as we need
4155 * all the player data available to be able to assign best colors. */
4156 if (game_was_started()) {
4158 }
4159}
4160
4161/************************************************************************/
4164static void sg_save_players(struct savedata *saving)
4165{
4166 /* Check status and return if not OK (sg_success FALSE). */
4167 sg_check_ret();
4168
4169 if ((saving->scenario && !saving->save_players)
4170 || !game_was_started()) {
4171 /* Nothing to do for a scenario without saved players or a game in
4172 * INITIAL state. */
4173 return;
4174 }
4175
4176 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4177
4178 /* Save destroyed wonders as bitvector. Note that improvement order
4179 * is saved in 'savefile.improvement.order'. */
4180 {
4181 char destroyed[B_LAST+1];
4182
4183 improvement_iterate(pimprove) {
4184 if (is_great_wonder(pimprove)
4185 && great_wonder_is_destroyed(pimprove)) {
4186 destroyed[improvement_index(pimprove)] = '1';
4187 } else {
4188 destroyed[improvement_index(pimprove)] = '0';
4189 }
4191 destroyed[improvement_count()] = '\0';
4193 "players.destroyed_wonders");
4194 }
4195
4196 secfile_insert_int(saving->file, server.identity_number,
4197 "players.identity_number_used");
4198
4199 /* Save player order. */
4200 {
4201 int i = 0;
4202 shuffled_players_iterate(pplayer) {
4203 secfile_insert_int(saving->file, player_number(pplayer),
4204 "players.shuffled_player_%d", i);
4205 i++;
4207 }
4208
4209 /* Sort units. */
4211
4212 /* Save players. */
4213 players_iterate(pplayer) {
4214 sg_save_player_main(saving, pplayer);
4215 sg_save_player_cities(saving, pplayer);
4216 sg_save_player_units(saving, pplayer);
4218 sg_save_player_vision(saving, pplayer);
4220}
4221
4222/************************************************************************/
4226 struct player *plr)
4227{
4228 const char **slist;
4229 int i, plrno = player_number(plr);
4230 const char *str;
4231 struct government *gov;
4232 const char *level;
4233 const char *barb_str;
4234 size_t nval;
4235 const char *kind;
4236
4237 /* Check status and return if not OK (sg_success FALSE). */
4238 sg_check_ret();
4239
4240 /* Basic player data. */
4241 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4242 sg_failure_ret(str != NULL, "%s", secfile_error());
4244 sz_strlcpy(plr->username,
4246 "player%d.username", plrno));
4248 "player%d.unassigned_user", plrno),
4249 "%s", secfile_error());
4252 "player%d.orig_username", plrno));
4255 "player%d.ranked_username",
4256 plrno));
4258 "player%d.unassigned_ranked", plrno),
4259 "%s", secfile_error());
4261 "player%d.delegation_username",
4262 plrno);
4263 /* Defaults to no delegation. */
4264 if (strlen(str)) {
4266 }
4267
4268 /* Player flags */
4269 BV_CLR_ALL(plr->flags);
4270 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4271 for (i = 0; i < nval; i++) {
4272 const char *sval = slist[i];
4274
4275 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4276
4277 BV_SET(plr->flags, fid);
4278 }
4279 free(slist);
4280
4281 /* Nation */
4282 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4284 if (plr->nation != NULL) {
4285 ai_traits_init(plr);
4286 }
4287
4288 /* Government */
4289 str = secfile_lookup_str(loading->file, "player%d.government_name",
4290 plrno);
4292 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4293 plrno, str);
4294 plr->government = gov;
4295
4296 /* Target government */
4298 "player%d.target_government_name", plrno);
4299 if (str != NULL) {
4301 } else {
4302 plr->target_government = NULL;
4303 }
4306 "player%d.revolution_finishes", plrno);
4307
4308 /* Load diplomatic data (diplstate + embassy + vision).
4309 * Shared vision is loaded in sg_load_players(). */
4311 players_iterate(pplayer) {
4312 char buf[32];
4313 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4314 i = player_index(pplayer);
4315
4316 /* Load diplomatic status */
4317 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4318
4319 ds->type =
4321 diplstate_type, "%s.current", buf);
4322 ds->max_state =
4324 diplstate_type, "%s.closest", buf);
4325
4326 /* FIXME: If either party is barbarian, we cannot enforce below check */
4327#if 0
4328 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4329 sg_regr(3020000,
4330 "Player%d: War with player %d who has never been met. "
4331 "Reverted to No Contact state.", plrno, i);
4332 ds->type = DS_NO_CONTACT;
4333 }
4334#endif
4335
4336 if (valid_dst_closest(ds) != ds->max_state) {
4337 sg_regr(3020000,
4338 "Player%d: closest diplstate to player %d less than current. "
4339 "Updated.", plrno, i);
4340 ds->max_state = ds->type;
4341 }
4342
4343 ds->first_contact_turn =
4345 "%s.first_contact_turn", buf);
4346 ds->turns_left =
4347 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4348 ds->has_reason_to_cancel =
4350 "%s.has_reason_to_cancel", buf);
4351 ds->contact_turns_left =
4353 "%s.contact_turns_left", buf);
4354
4355 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4356 buf)) {
4357 BV_SET(plr->real_embassy, i);
4358 }
4359 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4360 * must be known. */
4362
4363 /* load ai data */
4365 char buf[32];
4366
4367 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4369
4371 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4372 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4374
4376 "player%d.adv.wonder_city",
4377 plrno);
4378
4379 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4380
4381 /* Some sane defaults */
4382 plr->ai_common.fuzzy = 0;
4383 plr->ai_common.expand = 100;
4384 plr->ai_common.science_cost = 100;
4385
4386
4388 "player%d.ai.level", plrno);
4389 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4390 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4392 } else {
4394 }
4395
4397 log_sg("Player%d: Invalid AI level \"%s\". "
4398 "Changed to \"%s\".", plrno, level,
4401 }
4402
4404 "player%d.ai.barb_type", plrno);
4406
4408 log_sg("Player%d: Invalid barbarian type \"%s\". "
4409 "Changed to \"None\".", plrno, barb_str);
4411 }
4412
4413 if (is_barbarian(plr)) {
4414 server.nbarbarians++;
4415 }
4416
4417 if (is_ai(plr)) {
4419 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4420 }
4421
4422 /* Load nation style. */
4423 {
4424 struct nation_style *style;
4425
4426 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4427
4428 sg_failure_ret(str != NULL, "%s", secfile_error());
4429 style = style_by_rule_name(str);
4430 if (style == NULL) {
4431 style = style_by_number(0);
4432 log_sg("Player%d: unsupported city_style_name \"%s\". "
4433 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4434 }
4435 plr->style = style;
4436 }
4437
4439 "player%d.idle_turns", plrno),
4440 "%s", secfile_error());
4441 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4442 if (sex_by_name(kind) == SEX_MALE) {
4443 plr->is_male = TRUE;
4444 } else {
4445 plr->is_male = FALSE;
4446 }
4448 "player%d.is_alive", plrno),
4449 "%s", secfile_error());
4451 "player%d.turns_alive", plrno),
4452 "%s", secfile_error());
4454 "player%d.last_war", plrno),
4455 "%s", secfile_error());
4457 "player%d.phase_done", plrno);
4459 "player%d.gold", plrno),
4460 "%s", secfile_error());
4462 "player%d.rates.tax", plrno),
4463 "%s", secfile_error());
4465 "player%d.rates.science", plrno),
4466 "%s", secfile_error());
4468 "player%d.rates.luxury", plrno),
4469 "%s", secfile_error());
4471 "player%d.infrapts",
4472 plrno);
4473 plr->server.bulbs_last_turn =
4475 "player%d.research.bulbs_last_turn", plrno);
4476
4477 /* Traits */
4478 if (plr->nation) {
4479 for (i = 0; i < loading->trait.size; i++) {
4480 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4481
4482 if (trait_is_valid(tr)) {
4483 int val;
4484
4485 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4486 plrno, i),
4487 "%s", secfile_error());
4488 plr->ai_common.traits[tr].val = val;
4489
4491 "player%d.trait%d.mod", plrno, i),
4492 "%s", secfile_error());
4493 plr->ai_common.traits[tr].mod = val;
4494 }
4495 }
4496 }
4497
4498 /* Achievements */
4499 {
4500 int count;
4501
4502 count = secfile_lookup_int_default(loading->file, -1,
4503 "player%d.achievement_count", plrno);
4504
4505 if (count > 0) {
4506 for (i = 0; i < count; i++) {
4507 const char *name;
4508 struct achievement *pach;
4509 bool first;
4510
4512 "player%d.achievement%d.name", plrno, i);
4514
4516 "Unknown achievement \"%s\".", name);
4517
4519 "player%d.achievement%d.first",
4520 plrno, i),
4521 "achievement error: %s", secfile_error());
4522
4523 sg_failure_ret(pach->first == NULL || !first,
4524 "Multiple players listed as first to get achievement \"%s\".",
4525 name);
4526
4527 BV_SET(pach->achievers, player_index(plr));
4528
4529 if (first) {
4530 pach->first = plr;
4531 }
4532 }
4533 }
4534 }
4535
4536 /* Player score. */
4537 plr->score.happy =
4539 "score%d.happy", plrno);
4540 plr->score.content =
4542 "score%d.content", plrno);
4543 plr->score.unhappy =
4545 "score%d.unhappy", plrno);
4546 plr->score.angry =
4548 "score%d.angry", plrno);
4549
4550 /* Make sure that the score about specialists in current ruleset that
4551 * were not present at saving time are set to zero. */
4553 plr->score.specialists[sp] = 0;
4555
4556 for (i = 0; i < loading->specialist.size; i++) {
4557 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4559 "score%d.specialists%d", plrno, i);
4560 }
4561
4562 plr->score.wonders =
4564 "score%d.wonders", plrno);
4565 plr->score.techs =
4567 "score%d.techs", plrno);
4568 plr->score.techout =
4570 "score%d.techout", plrno);
4571 plr->score.landarea =
4573 "score%d.landarea", plrno);
4574 plr->score.settledarea =
4576 "score%d.settledarea", plrno);
4577 plr->score.population =
4579 "score%d.population", plrno);
4580 plr->score.cities =
4582 "score%d.cities", plrno);
4583 plr->score.units =
4585 "score%d.units", plrno);
4586 plr->score.pollution =
4588 "score%d.pollution", plrno);
4589 plr->score.literacy =
4591 "score%d.literacy", plrno);
4592 plr->score.bnp =
4594 "score%d.bnp", plrno);
4595 plr->score.mfg =
4597 "score%d.mfg", plrno);
4598 plr->score.spaceship =
4600 "score%d.spaceship", plrno);
4601 plr->score.units_built =
4603 "score%d.units_built", plrno);
4604 plr->score.units_killed =
4606 "score%d.units_killed", plrno);
4607 plr->score.units_lost =
4609 "score%d.units_lost", plrno);
4610 plr->score.units_used =
4612 "score%d.units_used", plrno);
4613 plr->score.culture =
4615 "score%d.culture", plrno);
4616 plr->score.game =
4618 "score%d.total", plrno);
4619
4620 /* Load space ship data. */
4621 {
4622 struct player_spaceship *ship = &plr->spaceship;
4623 char prefix[32];
4624 const char *st;
4625 int ei;
4626
4627 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4630 &ei,
4631 "%s.state", prefix),
4632 "%s", secfile_error());
4633 ship->state = ei;
4634
4635 if (ship->state != SSHIP_NONE) {
4636 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4637 "%s.structurals", prefix),
4638 "%s", secfile_error());
4639 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4640 "%s.components", prefix),
4641 "%s", secfile_error());
4643 "%s.modules", prefix),
4644 "%s", secfile_error());
4646 "%s.fuel", prefix),
4647 "%s", secfile_error());
4648 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4649 "%s.propulsion", prefix),
4650 "%s", secfile_error());
4651 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4652 "%s.habitation", prefix),
4653 "%s", secfile_error());
4654 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4655 "%s.life_support", prefix),
4656 "%s", secfile_error());
4657 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4658 "%s.solar_panels", prefix),
4659 "%s", secfile_error());
4660
4661 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4662 sg_failure_ret(st != NULL, "%s", secfile_error())
4663 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4664 sg_failure_ret(st[i] == '1' || st[i] == '0',
4665 "Undefined value '%c' within '%s.structure'.", st[i],
4666 prefix)
4667
4668 if (!(st[i] == '0')) {
4669 BV_SET(ship->structure, i);
4670 }
4671 }
4672 if (ship->state >= SSHIP_LAUNCHED) {
4673 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4674 "%s.launch_year", prefix),
4675 "%s", secfile_error());
4676 }
4678 }
4679 }
4680
4681 /* Load lost wonder data. */
4682 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4683 /* If not present, probably an old savegame; nothing to be done */
4684 if (str != NULL) {
4685 int k;
4686
4687 sg_failure_ret(strlen(str) == loading->improvement.size,
4688 "Invalid length for 'player%d.lost_wonders' ("
4689 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4690 plrno, strlen(str), loading->improvement.size);
4691 for (k = 0; k < loading->improvement.size; k++) {
4692 sg_failure_ret(str[k] == '1' || str[k] == '0',
4693 "Undefined value '%c' within "
4694 "'player%d.lost_wonders'.", plrno, str[k]);
4695
4696 if (str[k] == '1') {
4697 struct impr_type *pimprove =
4698 improvement_by_rule_name(loading->improvement.order[k]);
4699 if (pimprove) {
4700 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4701 }
4702 }
4703 }
4704 }
4705
4706 plr->history =
4707 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4708 plr->server.huts =
4709 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4710}
4711
4712/************************************************************************/
4716 struct player *plr)
4717{
4718 int i, k, plrno = player_number(plr);
4719 struct player_spaceship *ship = &plr->spaceship;
4720 const char *flag_names[PLRF_COUNT];
4721 int set_count;
4722
4723 /* Check status and return if not OK (sg_success FALSE). */
4724 sg_check_ret();
4725
4726 set_count = 0;
4727 for (i = 0; i < PLRF_COUNT; i++) {
4728 if (player_has_flag(plr, i)) {
4730 }
4731 }
4732
4734 "player%d.flags", plrno);
4735
4736 secfile_insert_str(saving->file, ai_name(plr->ai),
4737 "player%d.ai_type", plrno);
4739 "player%d.name", plrno);
4741 "player%d.username", plrno);
4743 "player%d.unassigned_user", plrno);
4744 if (plr->rgb != NULL) {
4745 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4746 } else {
4747 /* Colorless players are ok in pregame */
4748 if (game_was_started()) {
4749 log_sg("Game has started, yet player %d has no color defined.", plrno);
4750 }
4751 }
4753 "player%d.ranked_username", plrno);
4755 "player%d.unassigned_ranked", plrno);
4757 "player%d.orig_username", plrno);
4760 : "",
4761 "player%d.delegation_username", plrno);
4763 "player%d.nation", plrno);
4764 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4765 "player%d.team_no", plrno);
4766
4769 "player%d.government_name", plrno);
4770
4771 if (plr->target_government) {
4774 "player%d.target_government_name", plrno);
4775 }
4776
4778 "player%d.style_by_name", plrno);
4779
4781 "player%d.idle_turns", plrno);
4782 if (plr->is_male) {
4784 "player%d.kind", plrno);
4785 } else {
4787 "player%d.kind", plrno);
4788 }
4790 "player%d.is_alive", plrno);
4792 "player%d.turns_alive", plrno);
4794 "player%d.last_war", plrno);
4796 "player%d.phase_done", plrno);
4797
4798 players_iterate(pplayer) {
4799 char buf[32];
4800 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4801
4802 i = player_index(pplayer);
4803
4804 /* save diplomatic state */
4805 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4806
4807 secfile_insert_enum(saving->file, ds->type,
4808 diplstate_type, "%s.current", buf);
4809 secfile_insert_enum(saving->file, ds->max_state,
4810 diplstate_type, "%s.closest", buf);
4811 secfile_insert_int(saving->file, ds->first_contact_turn,
4812 "%s.first_contact_turn", buf);
4813 secfile_insert_int(saving->file, ds->turns_left,
4814 "%s.turns_left", buf);
4815 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4816 "%s.has_reason_to_cancel", buf);
4817 secfile_insert_int(saving->file, ds->contact_turns_left,
4818 "%s.contact_turns_left", buf);
4820 "%s.embassy", buf);
4821 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4822 "%s.gives_shared_vision", buf);
4823 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4824 "%s.gives_shared_tiles", buf);
4826
4829 /* save ai data */
4831 "player%d.ai%d.love", plrno, i);
4832 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4834
4836 "player%d.adv.wonder_city", plrno);
4837
4838 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4839
4840 /* Multipliers (policies) */
4841 i = multiplier_count();
4842
4843 for (k = 0; k < i; k++) {
4845 "player%d.multiplier%d.val", plrno, k);
4847 "player%d.multiplier%d.target", plrno, k);
4849 "player%d.multiplier%d.changed", plrno, k);
4850 }
4851
4853 "player%d.ai.level", plrno);
4855 "player%d.ai.barb_type", plrno);
4857 "player%d.gold", plrno);
4859 "player%d.rates.tax", plrno);
4861 "player%d.rates.science", plrno);
4863 "player%d.rates.luxury", plrno);
4865 "player%d.infrapts", plrno);
4867 "player%d.research.bulbs_last_turn", plrno);
4868
4869 /* Save traits */
4870 {
4871 enum trait tr;
4872 int j;
4873
4874 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4876 "player%d.trait%d.val", plrno, j);
4878 "player%d.trait%d.mod", plrno, j);
4879 }
4880 }
4881
4882 /* Save achievements */
4883 {
4884 int j = 0;
4885
4887 if (achievement_player_has(pach, plr)) {
4889 "player%d.achievement%d.name", plrno, j);
4890 if (pach->first == plr) {
4892 "player%d.achievement%d.first", plrno, j);
4893 } else {
4895 "player%d.achievement%d.first", plrno, j);
4896 }
4897
4898 j++;
4899 }
4901
4902 secfile_insert_int(saving->file, j,
4903 "player%d.achievement_count", plrno);
4904 }
4905
4907 "player%d.revolution_finishes", plrno);
4908
4909 /* Player score */
4911 "score%d.happy", plrno);
4913 "score%d.content", plrno);
4915 "score%d.unhappy", plrno);
4917 "score%d.angry", plrno);
4920 "score%d.specialists%d", plrno, sp);
4923 "score%d.wonders", plrno);
4925 "score%d.techs", plrno);
4927 "score%d.techout", plrno);
4929 "score%d.landarea", plrno);
4931 "score%d.settledarea", plrno);
4933 "score%d.population", plrno);
4935 "score%d.cities", plrno);
4937 "score%d.units", plrno);
4939 "score%d.pollution", plrno);
4941 "score%d.literacy", plrno);
4942 secfile_insert_int(saving->file, plr->score.bnp,
4943 "score%d.bnp", plrno);
4944 secfile_insert_int(saving->file, plr->score.mfg,
4945 "score%d.mfg", plrno);
4947 "score%d.spaceship", plrno);
4949 "score%d.units_built", plrno);
4951 "score%d.units_killed", plrno);
4953 "score%d.units_lost", plrno);
4955 "score%d.units_used", plrno);
4957 "score%d.culture", plrno);
4958 secfile_insert_int(saving->file, plr->score.game,
4959 "score%d.total", plrno);
4960
4961 /* Save space ship status. */
4962 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4963 plrno);
4964 if (ship->state != SSHIP_NONE) {
4965 char buf[32];
4966 char st[NUM_SS_STRUCTURALS+1];
4967 int ssi;
4968
4969 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4970
4971 secfile_insert_int(saving->file, ship->structurals,
4972 "%s.structurals", buf);
4973 secfile_insert_int(saving->file, ship->components,
4974 "%s.components", buf);
4975 secfile_insert_int(saving->file, ship->modules,
4976 "%s.modules", buf);
4977 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4978 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4979 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4980 secfile_insert_int(saving->file, ship->life_support,
4981 "%s.life_support", buf);
4982 secfile_insert_int(saving->file, ship->solar_panels,
4983 "%s.solar_panels", buf);
4984
4985 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4986 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4987 }
4988 st[ssi] = '\0';
4989 secfile_insert_str(saving->file, st, "%s.structure", buf);
4990 if (ship->state >= SSHIP_LAUNCHED) {
4991 secfile_insert_int(saving->file, ship->launch_year,
4992 "%s.launch_year", buf);
4993 }
4994 }
4995
4996 /* Save lost wonders info. */
4997 {
4998 char lost[B_LAST+1];
4999
5000 improvement_iterate(pimprove) {
5001 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5002 lost[improvement_index(pimprove)] = '1';
5003 } else {
5004 lost[improvement_index(pimprove)] = '0';
5005 }
5007 lost[improvement_count()] = '\0';
5009 "player%d.lost_wonders", plrno);
5010 }
5011
5012 secfile_insert_int(saving->file, plr->history,
5013 "player%d.history", plrno);
5015 "player%d.hut_count", plrno);
5016
5018 "player%d.border_vision", plrno);
5019
5020 if (saving->scenario) {
5021 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5022 int def = 1; /* We want users to get a player in a scenario */
5023
5025 /* This isn't usable player */
5026 def = 0;
5027 }
5028
5029 secfile_insert_int(saving->file, def,
5030 "player%d.autoselect_weight", plrno);
5031 } else {
5033 "player%d.autoselect_weight", plrno);
5034 }
5035 }
5036}
5037
5038/************************************************************************/
5042 struct player *plr)
5043{
5044 int ncities, i, plrno = player_number(plr);
5045 bool tasks_handled;
5047
5048 /* Check status and return if not OK (sg_success FALSE). */
5049 sg_check_ret();
5050
5052 "player%d.ncities", plrno),
5053 "%s", secfile_error());
5054
5055 if (!plr->is_alive && ncities > 0) {
5056 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5057 ncities = 0;
5058 }
5059
5061 "player%d.wl_max_length",
5062 plrno);
5064 "player%d.routes_max_length", plrno);
5065
5066 /* Load all cities of the player. */
5067 for (i = 0; i < ncities; i++) {
5068 char buf[32];
5069 struct city *pcity;
5070
5071 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5072
5073 /* Create a dummy city. */
5074 pcity = create_city_virtual(plr, NULL, buf);
5075 adv_city_alloc(pcity);
5076 if (!sg_load_player_city(loading, plr, pcity, buf,
5078 adv_city_free(pcity);
5079 destroy_city_virtual(pcity);
5080 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5081 }
5082
5084 idex_register_city(&wld, pcity);
5085
5086 /* Load the information about the nationality of citizens. This is done
5087 * here because the city sanity check called by citizens_update() requires
5088 * that the city is registered. */
5090
5091 /* After everything is loaded, but before vision. */
5092 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
5093
5094 /* adding the city contribution to fog-of-war */
5095 pcity->server.vision = vision_new(plr, city_tile(pcity));
5097 city_refresh_vision(pcity);
5098
5099 city_list_append(plr->cities, pcity);
5100 }
5101
5103 for (i = 0; !tasks_handled; i++) {
5104 int city_id;
5105 struct city *pcity = NULL;
5106
5107 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5108 plrno, i);
5109
5110 if (city_id != -1) {
5111 pcity = player_city_by_number(plr, city_id);
5112 }
5113
5114 if (pcity != NULL) {
5115 const char *str;
5116 int nat_x, nat_y;
5117 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5118
5119 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5120 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5121
5122 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5123
5124 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5126
5128 "Unknown workertask activity %s", str);
5129
5130 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5131
5132 if (strcmp("-", str)) {
5134
5135 sg_failure_ret(ptask->tgt != NULL,
5136 "Unknown workertask target %s", str);
5137 } else {
5138 ptask->tgt = NULL;
5139
5140 if (ptask->act == ACTIVITY_IRRIGATE) {
5142 } else if (ptask->act == ACTIVITY_MINE) {
5143 ptask->act = ACTIVITY_MINE;
5144 }
5145 }
5146
5147 ptask->want = secfile_lookup_int_default(loading->file, 1,
5148 "player%d.task%d.want", plrno, i);
5149
5151 } else {
5153 }
5154 }
5155}
5156
5157/************************************************************************/
5160static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5161 struct city *pcity, const char *citystr,
5163{
5164 struct player *past;
5165 const char *kind, *name, *str;
5166 int id, i, repair, sp_count = 0, workers = 0, value;
5167 int nat_x, nat_y;
5168 citizens size;
5169 const char *stylename;
5170 int partner;
5171 int want;
5172 int tmp_int;
5173 const struct civ_map *nmap = &(wld.map);
5174
5176 FALSE, "%s", secfile_error());
5178 FALSE, "%s", secfile_error());
5179 pcity->tile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5180 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5181 "%s has invalid center tile (%d, %d)",
5182 citystr, nat_x, nat_y);
5184 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5185
5186 /* Instead of dying, use 'citystr' string for damaged name. */
5188 "%s.name", citystr));
5189
5190 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5191 citystr), FALSE, "%s", secfile_error());
5192
5194 "%s.original", citystr);
5195 past = player_by_number(id);
5196 if (NULL != past) {
5197 pcity->original = past;
5198 }
5199
5200 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5201 citystr), FALSE, "%s", secfile_error());
5202 size = (citizens)value; /* set the correct type */
5203 sg_warn_ret_val(value == (int)size, FALSE,
5204 "Invalid city size: %d, set to %d", value, size);
5205 city_size_set(pcity, size);
5206
5207 for (i = 0; i < loading->specialist.size; i++) {
5208 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5209 citystr, i),
5210 FALSE, "%s", secfile_error());
5211 pcity->specialists[specialist_index(loading->specialist.order[i])]
5212 = (citizens)value;
5213 sp_count += value;
5214 }
5215
5216 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5217 for (i = 0; partner != 0; i++) {
5218 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5219 const char *dir;
5220 const char *good_str;
5221
5222 /* Append to routes list immediately, so the pointer can be found for freeing
5223 * even if we abort */
5225
5226 proute->partner = partner;
5227 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5229 "No traderoute direction found for %s", citystr);
5232 "Illegal route direction %s", dir);
5233 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5235 "No good found for %s", citystr);
5237 sg_warn_ret_val(proute->goods != NULL, FALSE,
5238 "Illegal good %s", good_str);
5239
5240 /* Next one */
5242 "%s.traderoute%d", citystr, i + 1);
5243 }
5244
5245 for (; i < routes_max; i++) {
5246 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5247 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5248 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5249 }
5250
5252 "%s.food_stock", citystr),
5253 FALSE, "%s", secfile_error());
5255 "%s.shield_stock", citystr),
5256 FALSE, "%s", secfile_error());
5257 pcity->history =
5258 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5259
5260 pcity->airlift =
5261 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5262 pcity->was_happy =
5263 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5264 citystr);
5265 pcity->had_famine =
5266 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5267 citystr);
5268
5269 pcity->turn_plague =
5270 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5271
5273 "%s.anarchy", citystr),
5274 FALSE, "%s", secfile_error());
5275 pcity->rapture =
5276 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5277 pcity->steal =
5278 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5279
5281 "%s.turn_founded", citystr),
5282 FALSE, "%s", secfile_error());
5284 "%s.acquire_t", citystr),
5285 FALSE, "%s", secfile_error());
5286 pcity->acquire_t = tmp_int;
5287 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5288 citystr), FALSE, "%s", secfile_error());
5289 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5290 citystr), FALSE, "%s", secfile_error());
5291
5293 "%s.turn_last_built", citystr),
5294 FALSE, "%s", secfile_error());
5295
5296 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5297 citystr);
5298 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5299 citystr);
5300 pcity->production = universal_by_rule_name(kind, name);
5302 "%s.currently_building: unknown \"%s\" \"%s\".",
5303 citystr, kind, name);
5304
5305 want = secfile_lookup_int_default(loading->file, 0,
5306 "%s.current_want", citystr);
5307 if (pcity->production.kind == VUT_IMPROVEMENT) {
5308 pcity->server.adv->
5309 building_want[improvement_index(pcity->production.value.building)]
5310 = want;
5311 }
5312
5313 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5314 citystr);
5315 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5316 citystr);
5319 "%s.changed_from: unknown \"%s\" \"%s\".",
5320 citystr, kind, name);
5321
5322 pcity->before_change_shields =
5324 "%s.before_change_shields", citystr);
5325 pcity->caravan_shields =
5327 "%s.caravan_shields", citystr);
5328 pcity->disbanded_shields =
5330 "%s.disbanded_shields", citystr);
5333 "%s.last_turns_shield_surplus",
5334 citystr);
5335
5337 "%s.style", citystr);
5338 if (stylename != NULL) {
5340 } else {
5341 pcity->style = 0;
5342 }
5343 if (pcity->style < 0) {
5344 pcity->style = city_style(pcity);
5345 }
5346
5347 pcity->server.synced = FALSE; /* Must re-sync with clients */
5348
5349 /* Initialise list of city improvements. */
5350 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5351 pcity->built[i].turn = I_NEVER;
5352 }
5353
5354 /* Load city improvements. */
5355 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5357 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5358 "Invalid length of '%s.improvements' ("
5359 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5360 citystr, strlen(str), loading->improvement.size);
5361 for (i = 0; i < loading->improvement.size; i++) {
5362 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5363 "Undefined value '%c' within '%s.improvements'.",
5364 str[i], citystr)
5365
5366 if (str[i] == '1') {
5367 struct impr_type *pimprove
5368 = improvement_by_rule_name(loading->improvement.order[i]);
5369
5370 if (pimprove) {
5371 city_add_improvement(pcity, pimprove);
5372 }
5373 }
5374 }
5375
5376 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5377 "No worked tiles map defined.");
5378
5379 city_freeze_workers(pcity);
5380
5381 /* Load new savegame with variable (squared) city radius and worked
5382 * tiles map */
5383
5384 int radius_sq
5385 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5386 citystr);
5387 city_map_radius_sq_set(pcity, radius_sq);
5388
5390 if (loading->worked_tiles[ptile->index] == pcity->id) {
5391 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5392 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5393 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5394 TILE_XY(pcity->tile), TILE_XY(ptile));
5396 sp_count++;
5397 } else {
5398 tile_set_worked(ptile, pcity);
5399 workers++;
5400 }
5401
5402#ifdef FREECIV_DEBUG
5403 /* Set this tile to unused; a check for not resetted tiles is
5404 * included in game_load_internal() */
5405 loading->worked_tiles[ptile->index] = -1;
5406#endif /* FREECIV_DEBUG */
5407 }
5409
5410 if (tile_worked(city_tile(pcity)) != pcity) {
5411 struct city *pwork = tile_worked(city_tile(pcity));
5412
5413 if (NULL != pwork) {
5414 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5415 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5418
5419 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5420 pwork->specialists[DEFAULT_SPECIALIST]++;
5422 } else {
5423 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5424 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5425 city_size_get(pcity));
5426 }
5427
5428 /* Repair pcity */
5429 tile_set_worked(city_tile(pcity), pcity);
5430 city_repair_size(pcity, -1);
5431 }
5432
5433 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5434 if (0 != repair) {
5435 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5436 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5437 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5438 workers, FREE_WORKED_TILES, sp_count);
5439
5440 /* Repair pcity */
5441 city_repair_size(pcity, repair);
5442 }
5443
5444 /* worklist_init() done in create_city_virtual() */
5445 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5446
5447 /* Load city options. */
5448 BV_CLR_ALL(pcity->city_options);
5449 for (i = 0; i < loading->coptions.size; i++) {
5450 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5451 citystr, i)) {
5452 BV_SET(pcity->city_options, loading->coptions.order[i]);
5453 }
5454 }
5456 "%s.wlcb", citystr),
5457 FALSE, "%s", secfile_error());
5458 pcity->wlcb = tmp_int;
5459
5460 /* Load the city rally point. */
5461 {
5462 int len = secfile_lookup_int_default(loading->file, 0,
5463 "%s.rally_point_length", citystr);
5464 int unconverted;
5465
5466 pcity->rally_point.length = len;
5467 if (len > 0) {
5469
5470 pcity->rally_point.orders
5471 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5472 pcity->rally_point.persistent
5474 "%s.rally_point_persistent", citystr);
5475 pcity->rally_point.vigilant
5477 "%s.rally_point_vigilant", citystr);
5478
5481 "%s.rally_point_orders", citystr);
5484 "%s.rally_point_dirs", citystr);
5487 "%s.rally_point_activities", citystr);
5488
5489 for (i = 0; i < len; i++) {
5490 struct unit_order *order = &pcity->rally_point.orders[i];
5491
5492 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5493 || rally_activities[i] == '\0') {
5494 log_sg("Invalid rally point.");
5495 free(pcity->rally_point.orders);
5496 pcity->rally_point.orders = NULL;
5497 pcity->rally_point.length = 0;
5498 break;
5499 }
5500 order->order = char2order(rally_orders[i]);
5501 order->dir = char2dir(rally_dirs[i]);
5502 order->activity = char2activity(rally_activities[i]);
5503
5505 "%s.rally_point_action_vec,%d",
5506 citystr, i);
5507
5508 if (unconverted >= 0 && unconverted < loading->action.size) {
5509 /* Look up what action id the unconverted number represents. */
5510 order->action = loading->action.order[unconverted];
5511 } else {
5512 if (order->order == ORDER_PERFORM_ACTION) {
5513 log_sg("Invalid action id in order for city rally point %d",
5514 pcity->id);
5515 }
5516
5517 order->action = ACTION_NONE;
5518 }
5519
5520 order->target
5522 "%s.rally_point_tgt_vec,%d",
5523 citystr, i);
5524 order->sub_target
5526 "%s.rally_point_sub_tgt_vec,%d",
5527 citystr, i);
5528 }
5529 } else {
5530 pcity->rally_point.orders = NULL;
5531
5532 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5533 citystr);
5534 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5535 citystr);
5536 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5537 citystr);
5538 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5539 citystr);
5540 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5541 citystr);
5542 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5543 citystr);
5545 "%s.rally_point_tgt_vec", citystr);
5547 "%s.rally_point_sub_tgt_vec", citystr);
5548 }
5549 }
5550
5551 /* Load the city manager parameters. */
5552 {
5553 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5554 "%s.cma_enabled", citystr);
5555 if (enabled) {
5556 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5557
5558 for (i = 0; i < O_LAST; i++) {
5560 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5562 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5563 }
5564
5566 loading->file, FALSE, "%s.max_growth", citystr);
5568 loading->file, FALSE, "%s.require_happy", citystr);
5570 loading->file, FALSE, "%s.allow_disorder", citystr);
5572 loading->file, FALSE, "%s.allow_specialists", citystr);
5574 loading->file, 0, "%s.happy_factor", citystr);
5575 pcity->cm_parameter = param;
5576 } else {
5577 pcity->cm_parameter = NULL;
5578
5579 for (i = 0; i < O_LAST; i++) {
5581 "%s.cma_minimal_surplus,%d", citystr, i);
5583 "%s.cma_factor,%d", citystr, i);
5584 }
5585
5586 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5587 citystr);
5588 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5589 citystr);
5590 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5591 citystr);
5592 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5593 citystr);
5594 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5595 citystr);
5596 }
5597 }
5598
5599 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5600
5601 return TRUE;
5602}
5603
5604/************************************************************************/
5608 struct player *plr,
5609 struct city *pcity,
5610 const char *citystr)
5611{
5613 citizens size;
5614
5615 citizens_init(pcity);
5616 player_slots_iterate(pslot) {
5617 int nationality;
5618
5619 nationality = secfile_lookup_int_default(loading->file, -1,
5620 "%s.citizen%d", citystr,
5621 player_slot_index(pslot));
5622 if (nationality > 0 && !player_slot_is_used(pslot)) {
5623 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5624 city_name_get(pcity), player_slot_index(pslot));
5625 continue;
5626 }
5627
5628 if (nationality != -1 && player_slot_is_used(pslot)) {
5629 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5630 "Invalid value for citizens of player %d in %s: %d.",
5631 player_slot_index(pslot), city_name_get(pcity), nationality);
5632 citizens_nation_set(pcity, pslot, nationality);
5633 }
5635 /* Sanity check. */
5636 size = citizens_count(pcity);
5637 if (size != city_size_get(pcity)) {
5638 if (size != 0) {
5639 /* size == 0 can be result from the fact that ruleset had no
5640 * nationality enabled at saving time, so no citizens at all
5641 * were saved. But something more serious must be going on if
5642 * citizens have been saved partially - if some of them are there. */
5643 log_sg("City size and number of citizens does not match in %s "
5644 "(%d != %d)! Repairing ...", city_name_get(pcity),
5645 city_size_get(pcity), size);
5646 }
5647 citizens_update(pcity, NULL);
5648 }
5649 }
5650}
5651
5652/************************************************************************/
5656 struct player *plr)
5657{
5659 int i = 0;
5660 int plrno = player_number(plr);
5662
5663 /* Check status and return if not OK (sg_success FALSE). */
5664 sg_check_ret();
5665
5667 "player%d.ncities", plrno);
5668
5670 /* Initialise the nation list for the citizens information. */
5671 player_slots_iterate(pslot) {
5674 }
5675
5676 /* First determine length of longest worklist, rally point order, and the
5677 * nationalities we have. */
5678 city_list_iterate(plr->cities, pcity) {
5679 int routes;
5680
5681 /* Check the sanity of the city. */
5682 city_refresh(pcity);
5683 sanity_check_city(pcity);
5684
5685 if (pcity->worklist.length > wlist_max_length) {
5686 wlist_max_length = pcity->worklist.length;
5687 }
5688
5689 if (pcity->rally_point.length > rally_point_max_length) {
5690 rally_point_max_length = pcity->rally_point.length;
5691 }
5692
5693 routes = city_num_trade_routes(pcity);
5694 if (routes > routes_max) {
5695 routes_max = routes;
5696 }
5697
5699 /* Find all nations of the citizens,*/
5700 players_iterate(pplayer) {
5701 if (!nations[player_index(pplayer)]
5702 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5703 nations[player_index(pplayer)] = TRUE;
5704 }
5706 }
5708
5710 "player%d.wl_max_length", plrno);
5712 "player%d.routes_max_length", plrno);
5713
5714 city_list_iterate(plr->cities, pcity) {
5715 struct tile *pcenter = city_tile(pcity);
5716 char impr_buf[B_LAST + 1];
5717 char buf[32];
5718 int j, nat_x, nat_y;
5719
5720 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5721
5722
5724 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5725 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5726
5727 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5728
5729 if (pcity->original != NULL) {
5730 secfile_insert_int(saving->file, player_number(pcity->original),
5731 "%s.original", buf);
5732 } else {
5733 secfile_insert_int(saving->file, -1, "%s.original", buf);
5734 }
5735 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5736
5737 j = 0;
5739 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5740 buf, j++);
5742
5743 j = 0;
5745 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5746 buf, j);
5748 "%s.route_direction%d", buf, j);
5750 "%s.route_good%d", buf, j);
5751 j++;
5753
5754 /* Save dummy values to keep tabular format happy */
5755 for (; j < routes_max; j++) {
5756 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5758 "%s.route_direction%d", buf, j);
5760 "%s.route_good%d", buf, j);
5761 }
5762
5763 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5764 buf);
5765 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5766 buf);
5767 secfile_insert_int(saving->file, pcity->history, "%s.history",
5768 buf);
5769
5770 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5771 buf);
5772 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5773 buf);
5774 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5775 buf);
5776 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5777 buf);
5778
5779 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5780 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5781 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5782 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5783 buf);
5784 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5785 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5786 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5787 secfile_insert_int(saving->file, pcity->turn_last_built,
5788 "%s.turn_last_built", buf);
5789
5790 /* For visual debugging, variable length strings together here */
5791 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5792
5793 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5794 "%s.currently_building_kind", buf);
5795 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5796 "%s.currently_building_name", buf);
5797
5798 if (pcity->production.kind == VUT_IMPROVEMENT) {
5800 pcity->server.adv->
5801 building_want[improvement_index(pcity->production.value.building)],
5802 "%s.current_want", buf);
5803 } else {
5804 secfile_insert_int(saving->file, 0,
5805 "%s.current_want", buf);
5806 }
5807
5808 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5809 "%s.changed_from_kind", buf);
5810 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5811 "%s.changed_from_name", buf);
5812
5813 secfile_insert_int(saving->file, pcity->before_change_shields,
5814 "%s.before_change_shields", buf);
5815 secfile_insert_int(saving->file, pcity->caravan_shields,
5816 "%s.caravan_shields", buf);
5817 secfile_insert_int(saving->file, pcity->disbanded_shields,
5818 "%s.disbanded_shields", buf);
5819 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5820 "%s.last_turns_shield_surplus", buf);
5821
5822 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5823 "%s.style", buf);
5824
5825 /* Save the squared city radius and all tiles within the corresponing
5826 * city map. */
5827 secfile_insert_int(saving->file, pcity->city_radius_sq,
5828 "player%d.c%d.city_radius_sq", plrno, i);
5829 /* The tiles worked by the city are saved using the main map.
5830 * See also sg_save_map_worked(). */
5831
5832 /* Save improvement list as bytevector. Note that improvement order
5833 * is saved in savefile.improvement_order. */
5834 improvement_iterate(pimprove) {
5835 impr_buf[improvement_index(pimprove)]
5836 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5837 : '1';
5839 impr_buf[improvement_count()] = '\0';
5840
5842 "Invalid size of the improvement vector (%s.improvements: "
5843 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5844 strlen(impr_buf), sizeof(impr_buf));
5845 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5846
5847 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5848 buf);
5849
5850 for (j = 0; j < CITYO_LAST; j++) {
5851 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5852 "%s.option%d", buf, j);
5853 }
5854 secfile_insert_int(saving->file, pcity->wlcb,
5855 "%s.wlcb", buf);
5856
5857 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5858
5860 /* Save nationality of the citizens,*/
5861 players_iterate(pplayer) {
5862 if (nations[player_index(pplayer)]) {
5864 citizens_nation_get(pcity, pplayer->slot),
5865 "%s.citizen%d", buf, player_index(pplayer));
5866 }
5868 }
5869
5870 secfile_insert_int(saving->file, pcity->rally_point.length,
5871 "%s.rally_point_length", buf);
5872 if (pcity->rally_point.length) {
5873 int len = pcity->rally_point.length;
5874 char orders[len + 1], dirs[len + 1], activities[len + 1];
5875 int actions[len];
5876 int targets[len];
5877 int sub_targets[len];
5878
5879 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5880 "%s.rally_point_persistent", buf);
5881 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5882 "%s.rally_point_vigilant", buf);
5883
5884 for (j = 0; j < len; j++) {
5885 orders[j] = order2char(pcity->rally_point.orders[j].order);
5886 dirs[j] = '?';
5887 activities[j] = '?';
5888 targets[j] = NO_TARGET;
5889 sub_targets[j] = NO_TARGET;
5890 actions[j] = -1;
5891 switch (pcity->rally_point.orders[j].order) {
5892 case ORDER_MOVE:
5893 case ORDER_ACTION_MOVE:
5894 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5895 break;
5896 case ORDER_ACTIVITY:
5897 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5898 activities[j]
5899 = activity2char(pcity->rally_point.orders[j].activity);
5900 actions[j]
5901 = pcity->rally_point.orders[j].action;
5902 break;
5904 actions[j] = pcity->rally_point.orders[j].action;
5905 targets[j] = pcity->rally_point.orders[j].target;
5906 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5907 break;
5908 case ORDER_FULL_MP:
5909 case ORDER_LAST:
5910 break;
5911 }
5912 }
5913 orders[len] = dirs[len] = activities[len] = '\0';
5914
5915 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5916 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5917 secfile_insert_str(saving->file, activities,
5918 "%s.rally_point_activities", buf);
5919
5921 "%s.rally_point_action_vec", buf);
5922 /* Fill in dummy values for order targets so the registry will save
5923 * the unit table in a tabular format. */
5924 for (j = len; j < rally_point_max_length; j++) {
5925 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5926 buf, j);
5927 }
5928
5929 secfile_insert_int_vec(saving->file, targets, len,
5930 "%s.rally_point_tgt_vec", buf);
5931 /* Fill in dummy values for order targets so the registry will save
5932 * the unit table in a tabular format. */
5933 for (j = len; j < rally_point_max_length; j++) {
5935 "%s.rally_point_tgt_vec,%d", buf, j);
5936 }
5937
5938 secfile_insert_int_vec(saving->file, sub_targets, len,
5939 "%s.rally_point_sub_tgt_vec", buf);
5940 /* Fill in dummy values for order targets so the registry will save
5941 * the unit table in a tabular format. */
5942 for (j = len; j < rally_point_max_length; j++) {
5943 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5944 buf, j);
5945 }
5946 } else {
5947 /* Put all the same fields into the savegame - otherwise the
5948 * registry code can't correctly use a tabular format and the
5949 * savegame will be bigger. */
5950 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5951 buf);
5952 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5953 buf);
5954 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5955 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5956 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5957 buf);
5958
5959 /* Fill in dummy values for order targets so the registry will save
5960 * the unit table in a tabular format. */
5961
5962 /* The start of a vector has no number. */
5963 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5964 buf);
5965 for (j = 1; j < rally_point_max_length; j++) {
5966 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5967 buf, j);
5968 }
5969
5970 /* The start of a vector has no number. */
5971 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5972 buf);
5973 for (j = 1; j < rally_point_max_length; j++) {
5975 "%s.rally_point_tgt_vec,%d", buf, j);
5976 }
5977
5978 /* The start of a vector has no number. */
5979 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5980 buf);
5981 for (j = 1; j < rally_point_max_length; j++) {
5982 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5983 buf, j);
5984 }
5985 }
5986
5987 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5988 "%s.cma_enabled", buf);
5989 if (pcity->cm_parameter) {
5991 pcity->cm_parameter->minimal_surplus, O_LAST,
5992 "%s.cma_minimal_surplus", buf);
5994 pcity->cm_parameter->factor, O_LAST,
5995 "%s.cma_factor", buf);
5996 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
5997 "%s.max_growth", buf);
5998 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
5999 "%s.require_happy", buf);
6000 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6001 "%s.allow_disorder", buf);
6003 pcity->cm_parameter->allow_specialists,
6004 "%s.allow_specialists", buf);
6005 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6006 "%s.happy_factor", buf);
6007 } else {
6008 int zeros[O_LAST];
6009
6010 memset(zeros, 0, sizeof(zeros));
6012 "%s.cma_minimal_surplus", buf);
6014 "%s.cma_factor", buf);
6015 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6016 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6017 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6018 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6019 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6020 }
6021
6022 i++;
6024
6025 i = 0;
6026 city_list_iterate(plr->cities, pcity) {
6027 worker_task_list_iterate(pcity->task_reqs, ptask) {
6028 int nat_x, nat_y;
6029
6031 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6032 plrno, i);
6033 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6034 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6036 "player%d.task%d.activity",
6037 plrno, i);
6038 if (ptask->tgt != NULL) {
6040 "player%d.task%d.target",
6041 plrno, i);
6042 } else {
6043 secfile_insert_str(saving->file, "-",
6044 "player%d.task%d.target",
6045 plrno, i);
6046 }
6047 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6048
6049 i++;
6052}
6053
6054/************************************************************************/
6058 struct player *plr)
6059{
6060 int nunits, i, plrno = player_number(plr);
6061 size_t orders_max_length;
6062
6063 /* Check status and return if not OK (sg_success FALSE). */
6064 sg_check_ret();
6065
6067 "player%d.nunits", plrno),
6068 "%s", secfile_error());
6069 if (!plr->is_alive && nunits > 0) {
6070 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6071 nunits = 0; /* Some old savegames may be buggy. */
6072 }
6073
6075 "player%d.orders_max_length",
6076 plrno);
6077
6078 for (i = 0; i < nunits; i++) {
6079 struct unit *punit;
6080 struct city *pcity;
6081 const char *name;
6082 char buf[32];
6083 struct unit_type *type;
6084 struct tile *ptile;
6085
6086 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6087
6088 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6090 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6091
6092 /* Create a dummy unit. */
6093 punit = unit_virtual_create(plr, NULL, type, 0);
6096 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6097 }
6098
6101
6102 if ((pcity = game_city_by_number(punit->homecity))) {
6104 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6105 log_sg("%s: bad home city %d.", buf, punit->homecity);
6107 }
6108
6109 ptile = unit_tile(punit);
6110
6111 /* allocate the unit's contribution to fog of war */
6114 /* NOTE: There used to be some map_set_known calls here. These were
6115 * unneeded since unfogging the tile when the unit sees it will
6116 * automatically reveal that tile. */
6117
6120 }
6121}
6122
6123/************************************************************************/
6127 struct player *plr, struct unit *punit,
6129 const char *unitstr)
6130{
6131 enum unit_activity activity;
6132 int nat_x, nat_y;
6133 struct extra_type *pextra = NULL;
6134 struct tile *ptile;
6135 int extra_id;
6136 int ei;
6137 const char *facing_str;
6138 int natnbr;
6139 int unconverted;
6140 const char *str;
6141 enum gen_action action;
6142
6144 unitstr), FALSE, "%s", secfile_error());
6146 FALSE, "%s", secfile_error());
6148 FALSE, "%s", secfile_error());
6149
6150 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6151 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6152 unitstr, nat_x, nat_y);
6153 unit_tile_set(punit, ptile);
6154
6157 "%s.facing", unitstr);
6158 if (facing_str[0] != 'x') {
6159 /* We don't touch punit->facing if savegame does not contain that
6160 * information. Initial orientation set by unit_virtual_create()
6161 * is as good as any. */
6162 enum direction8 facing = char2dir(facing_str[0]);
6163
6164 if (direction8_is_valid(facing)) {
6165 punit->facing = facing;
6166 } else {
6167 log_error("Illegal unit orientation '%s'", facing_str);
6168 }
6169 }
6170
6171 /* If savegame has unit nationality, it doesn't hurt to
6172 * internally set it even if nationality rules are disabled. */
6174 player_number(plr),
6175 "%s.nationality", unitstr);
6176
6178 if (punit->nationality == NULL) {
6179 punit->nationality = plr;
6180 }
6181
6183 "%s.homecity", unitstr), FALSE,
6184 "%s", secfile_error());
6186 "%s.moves", unitstr), FALSE,
6187 "%s", secfile_error());
6189 "%s.fuel", unitstr), FALSE,
6190 "%s", secfile_error());
6192 "%s.activity", unitstr), FALSE,
6193 "%s", secfile_error());
6194 activity = unit_activity_by_name(loading->activities.order[ei],
6197 "%s.action", unitstr), FALSE,
6198 "%s", secfile_error());
6199 action = loading->action.order[ei];
6200
6203 "%s.born", unitstr);
6206 "%s.current_form_turn", unitstr);
6207
6209 "%s.activity_tgt", unitstr);
6210
6211 if (extra_id != -2) {
6212 if (extra_id >= 0 && extra_id < loading->extra.size) {
6213 pextra = loading->extra.order[extra_id];
6214 set_unit_activity_targeted(punit, activity, pextra, action);
6215 } else if (activity == ACTIVITY_IRRIGATE) {
6219 punit);
6220 if (tgt != NULL) {
6222 } else {
6224 }
6225 } else if (activity == ACTIVITY_MINE) {
6227 EC_MINE,
6229 punit);
6230 if (tgt != NULL) {
6232 } else {
6234 }
6235 } else {
6236 set_unit_activity(punit, activity, action);
6237 }
6238 } else {
6240 } /* activity_tgt == NULL */
6241
6243 "%s.activity_count", unitstr), FALSE,
6244 "%s", secfile_error());
6245
6248 "%s.changed_from", unitstr);
6249
6251 "%s.changed_from_tgt", unitstr), FALSE,
6252 "%s", secfile_error());
6253
6254 if (extra_id >= 0 && extra_id < loading->extra.size) {
6255 punit->changed_from_target = loading->extra.order[extra_id];
6256 } else {
6258 }
6259
6262 "%s.changed_from_count", unitstr);
6263
6264 /* Special case: for a long time, we accidentally incremented
6265 * activity_count while a unit was sentried, so it could increase
6266 * without bound (bug #20641) and be saved in old savefiles.
6267 * We zero it to prevent potential trouble overflowing the range
6268 * in network packets, etc. */
6269 if (activity == ACTIVITY_SENTRY) {
6270 punit->activity_count = 0;
6271 }
6274 }
6275
6276 punit->veteran
6277 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6278 {
6279 /* Protect against change in veteran system in ruleset */
6280 const int levels = utype_veteran_levels(unit_type_get(punit));
6281
6282 if (punit->veteran >= levels) {
6283 fc_assert(levels >= 1);
6284 punit->veteran = levels - 1;
6285 }
6286 }
6289 "%s.done_moving", unitstr);
6292 "%s.battlegroup", unitstr);
6293
6295 "%s.go", unitstr)) {
6296 int gnat_x, gnat_y;
6297
6299 "%s.goto_x", unitstr), FALSE,
6300 "%s", secfile_error());
6302 "%s.goto_y", unitstr), FALSE,
6303 "%s", secfile_error());
6304
6306 } else {
6307 punit->goto_tile = NULL;
6308
6309 /* These variables are not used but needed for saving the unit table.
6310 * Load them to prevent unused variables errors. */
6311 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6312 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6313 }
6314
6315 /* Load AI data of the unit. */
6316 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6317
6320 "%s.server_side_agent",
6321 unitstr);
6322 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6323 /* Look up what server side agent the unconverted number represents. */
6324 punit->ssa_controller = loading->ssa.order[unconverted];
6325 } else {
6326 log_sg("Invalid server side agent %d for unit %d",
6327 unconverted, punit->id);
6328
6330 }
6331
6333 "%s.hp", unitstr), FALSE,
6334 "%s", secfile_error());
6335
6337 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6339 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6340 punit->moved
6341 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6344 "%s.paradropped", unitstr);
6345 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6346 if (str[0] != '\0') {
6348 }
6349
6350 /* The transport status (punit->transported_by) is loaded in
6351 * sg_player_units_transport(). */
6352
6353 /* Initialize upkeep values: these are hopefully initialized
6354 * elsewhere before use (specifically, in city_support(); but
6355 * fixme: check whether always correctly initialized?).
6356 * Below is mainly for units which don't have homecity --
6357 * otherwise these don't get initialized (and AI calculations
6358 * etc may use junk values). */
6362
6364 "%s.action_decision", unitstr),
6365 FALSE, "%s", secfile_error());
6366
6367 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6368 /* Look up what action decision want the unconverted number
6369 * represents. */
6370 punit->action_decision_want = loading->act_dec.order[unconverted];
6371 } else {
6372 log_sg("Invalid action decision want for unit %d", punit->id);
6373
6375 }
6376
6378 /* Load the tile to act against. */
6379 int adwt_x, adwt_y;
6380
6381 if (secfile_lookup_int(loading->file, &adwt_x,
6382 "%s.action_decision_tile_x", unitstr)
6384 "%s.action_decision_tile_y", unitstr)) {
6386 adwt_x, adwt_y);
6387 } else {
6390 log_sg("Bad action_decision_tile for unit %d", punit->id);
6391 }
6392 } else {
6393 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6394 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6396 }
6397
6399
6400 /* Load the unit orders */
6401 {
6402 int len = secfile_lookup_int_default(loading->file, 0,
6403 "%s.orders_length", unitstr);
6404
6405 if (len > 0) {
6406 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6407 int j;
6408
6409 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6413 "%s.orders_index", unitstr);
6416 "%s.orders_repeat", unitstr);
6419 "%s.orders_vigilant", unitstr);
6420
6423 "%s.orders_list", unitstr);
6426 "%s.dir_list", unitstr);
6429 "%s.activity_list", unitstr);
6430
6432
6433 for (j = 0; j < len; j++) {
6434 struct unit_order *order = &punit->orders.list[j];
6436 int order_sub_tgt;
6437
6438 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6439 || act_unitstr[j] == '\0') {
6440 log_sg("Invalid unit orders.");
6442 break;
6443 }
6444 order->order = char2order(orders_unitstr[j]);
6445 order->dir = char2dir(dir_unitstr[j]);
6446 order->activity = char2activity(act_unitstr[j]);
6447
6449 "%s.action_vec,%d",
6450 unitstr, j);
6451
6452 if (unconverted >= 0 && unconverted < loading->action.size) {
6453 /* Look up what action id the unconverted number represents. */
6454 order->action = loading->action.order[unconverted];
6455 } else {
6456 if (order->order == ORDER_PERFORM_ACTION) {
6457 log_sg("Invalid action id in order for unit %d", punit->id);
6458 }
6459
6460 order->action = ACTION_NONE;
6461 }
6462
6463 if (order->order == ORDER_LAST
6464 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6465 || (order->order == ORDER_ACTION_MOVE
6466 && !direction8_is_valid(order->dir))
6467 || (order->order == ORDER_PERFORM_ACTION
6468 && !action_id_exists(order->action))
6469 || (order->order == ORDER_ACTIVITY
6470 && (order->activity == ACTIVITY_LAST
6471 || !action_id_exists(order->action)))) {
6472 /* An invalid order. Just drop the orders for this unit. */
6474 punit->orders.list = NULL;
6476 break;
6477 }
6478
6480 "%s.tgt_vec,%d",
6481 unitstr, j);
6483 "%s.sub_tgt_vec,%d",
6484 unitstr, j);
6485
6486 if (order->order == ORDER_PERFORM_ACTION) {
6487 /* Validate sub target */
6488 switch (action_id_get_sub_target_kind(order->action)) {
6489 case ASTK_BUILDING:
6490 /* Sub target is a building. */
6492 /* Sub target is invalid. */
6493 log_sg("Cannot find building %d for %s to %s",
6496 order->sub_target = B_LAST;
6497 } else {
6498 order->sub_target = order_sub_tgt;
6499 }
6500 break;
6501 case ASTK_TECH:
6502 /* Sub target is a technology. */
6503 if (order_sub_tgt == A_NONE
6505 && order_sub_tgt != A_FUTURE)) {
6506 /* Target tech is invalid. */
6507 log_sg("Cannot find tech %d for %s to steal",
6509 order->sub_target = A_NONE;
6510 } else {
6511 order->sub_target = order_sub_tgt;
6512 }
6513 break;
6514 case ASTK_EXTRA:
6516 /* These take an extra. */
6518 break;
6519 case ASTK_NONE:
6520 /* None of these can take a sub target. */
6522 "Specified sub target for action %d unsupported.",
6523 order->action);
6524 order->sub_target = NO_TARGET;
6525 break;
6526 case ASTK_COUNT:
6528 "Bad action action %d.",
6529 order->action);
6530 order->sub_target = NO_TARGET;
6531 break;
6532 }
6533 }
6534
6535 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6536 enum unit_activity act;
6537
6539 if (order_sub_tgt != EXTRA_NONE) {
6540 log_sg("Cannot find extra %d for %s to build",
6542 }
6543
6544 order->sub_target = EXTRA_NONE;
6545 } else {
6546 order->sub_target = order_sub_tgt;
6547 }
6548
6549 /* An action or an activity may require an extra target. */
6550 if (action_wants_extra) {
6551 act = action_id_get_activity(order->action);
6552 } else {
6553 act = order->activity;
6554 }
6555
6556 if (unit_activity_is_valid(act)
6558 && order->sub_target == EXTRA_NONE) {
6559 /* Missing required action extra target. */
6561 punit->orders.list = NULL;
6563 break;
6564 }
6565 } else if (order->order != ORDER_PERFORM_ACTION) {
6566 if (order_sub_tgt != -1) {
6567 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6568 order_sub_tgt, -1, order->order);
6569 }
6570 order->sub_target = NO_TARGET;
6571 }
6572 }
6573
6574 for (; j < orders_max_length; j++) {
6576 "%s.action_vec,%d", unitstr, j);
6578 "%s.tgt_vec,%d", unitstr, j);
6580 "%s.sub_tgt_vec,%d", unitstr, j);
6581 }
6582 } else {
6583 int j;
6584
6586 punit->orders.list = NULL;
6587
6588 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6589 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6590 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6591 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6592 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6593 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6594 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6595 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6596 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6597
6598 for (j = 1; j < orders_max_length; j++) {
6600 "%s.action_vec,%d", unitstr, j);
6602 "%s.tgt_vec,%d", unitstr, j);
6604 "%s.sub_tgt_vec,%d", unitstr, j);
6605 }
6606 }
6607 }
6608
6609 return TRUE;
6610}
6611
6612/************************************************************************/
6617 struct player *plr)
6618{
6619 int nunits, i, plrno = player_number(plr);
6620
6621 /* Check status and return if not OK (sg_success FALSE). */
6622 sg_check_ret();
6623
6624 /* Recheck the number of units for the player. This is a copied from
6625 * sg_load_player_units(). */
6627 "player%d.nunits", plrno),
6628 "%s", secfile_error());
6629 if (!plr->is_alive && nunits > 0) {
6630 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6631 nunits = 0; /* Some old savegames may be buggy. */
6632 }
6633
6634 for (i = 0; i < nunits; i++) {
6635 int id_unit, id_trans;
6636 struct unit *punit, *ptrans;
6637
6639 "player%d.u%d.id",
6640 plrno, i);
6642 fc_assert_action(punit != NULL, continue);
6643
6645 "player%d.u%d.transported_by",
6646 plrno, i);
6647 if (id_trans == -1) {
6648 /* Not transported. */
6649 continue;
6650 }
6651
6653 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6654
6655 if (ptrans) {
6656#ifndef FREECIV_NDEBUG
6657 bool load_success =
6658#endif
6660
6661 fc_assert_action(load_success, continue);
6662 }
6663 }
6664}
6665
6666/************************************************************************/
6670 struct player *plr)
6671{
6672 int i = 0;
6673 int longest_order = 0;
6674 int plrno = player_number(plr);
6675
6676 /* Check status and return if not OK (sg_success FALSE). */
6677 sg_check_ret();
6678
6680 "player%d.nunits", plrno);
6681
6682 /* Find the longest unit order so different order length won't break
6683 * storing units in the tabular format. */
6685 if (punit->has_orders) {
6686 if (longest_order < punit->orders.length) {
6688 }
6689 }
6691
6693 "player%d.orders_max_length", plrno);
6694
6696 char buf[32];
6697 char dirbuf[2] = " ";
6698 int nat_x, nat_y;
6699 int last_order, j;
6700
6701 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6702 dirbuf[0] = dir2char(punit->facing);
6703 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6704
6706 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6707 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6708
6709 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6712 "%s.nationality", buf);
6713 }
6714 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6715 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6716 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6718 "%s.type_by_name", buf);
6719
6720 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6722 "%s.activity_count", buf);
6723 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6724 if (punit->activity_target == NULL) {
6725 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6726 } else {
6728 "%s.activity_tgt", buf);
6729 }
6730
6732 "%s.changed_from", buf);
6734 "%s.changed_from_count", buf);
6735 if (punit->changed_from_target == NULL) {
6736 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6737 } else {
6739 "%s.changed_from_tgt", buf);
6740 }
6741
6743 "%s.done_moving", buf);
6744 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6745 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6747 "%s.born", buf);
6749 "%s.current_form_turn", buf);
6751 "%s.battlegroup", buf);
6752
6753 if (punit->goto_tile) {
6755 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6756 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6757 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6758 } else {
6759 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6760 /* Set this values to allow saving it as table. */
6761 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6762 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6763 }
6764
6766 "%s.server_side_agent", buf);
6767
6768 /* Save AI data of the unit. */
6769 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6770
6772 "%s.ord_map", buf);
6774 "%s.ord_city", buf);
6775 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6777 "%s.paradropped", buf);
6779 ? unit_transport_get(punit)->id : -1,
6780 "%s.transported_by", buf);
6781 if (punit->carrying != NULL) {
6783 "%s.carrying", buf);
6784 } else {
6785 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6786 }
6787
6789 "%s.action_decision", buf);
6790
6791 /* Stored as tile rather than direction to make sure the target tile is
6792 * sane. */
6797 "%s.action_decision_tile_x", buf);
6799 "%s.action_decision_tile_y", buf);
6800 } else {
6801 /* Dummy values to get tabular format. */
6802 secfile_insert_int(saving->file, -1,
6803 "%s.action_decision_tile_x", buf);
6804 secfile_insert_int(saving->file, -1,
6805 "%s.action_decision_tile_y", buf);
6806 }
6807
6809 "%s.stay", buf);
6810
6811 if (punit->has_orders) {
6812 int len = punit->orders.length;
6813 char orders_buf[len + 1], dir_buf[len + 1];
6814 char act_buf[len + 1];
6815 int action_buf[len];
6816 int tgt_vec[len];
6817 int sub_tgt_vec[len];
6818
6819 last_order = len;
6820
6821 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6823 "%s.orders_index", buf);
6825 "%s.orders_repeat", buf);
6827 "%s.orders_vigilant", buf);
6828
6829 for (j = 0; j < len; j++) {
6831 dir_buf[j] = '?';
6832 act_buf[j] = '?';
6833 tgt_vec[j] = NO_TARGET;
6834 sub_tgt_vec[j] = -1;
6835 action_buf[j] = -1;
6836 switch (punit->orders.list[j].order) {
6837 case ORDER_MOVE:
6838 case ORDER_ACTION_MOVE:
6839 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6840 break;
6841 case ORDER_ACTIVITY:
6845 break;
6848 tgt_vec[j] = punit->orders.list[j].target;
6850 break;
6851 case ORDER_FULL_MP:
6852 case ORDER_LAST:
6853 break;
6854 }
6855 }
6856 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6857
6858 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6859 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6860 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6861
6863 "%s.action_vec", buf);
6864 /* Fill in dummy values for order targets so the registry will save
6865 * the unit table in a tabular format. */
6866 for (j = last_order; j < longest_order; j++) {
6867 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6868 }
6869
6871 "%s.tgt_vec", buf);
6872 /* Fill in dummy values for order targets so the registry will save
6873 * the unit table in a tabular format. */
6874 for (j = last_order; j < longest_order; j++) {
6875 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6876 }
6877
6879 "%s.sub_tgt_vec", buf);
6880 /* Fill in dummy values for order targets so the registry will save
6881 * the unit table in a tabular format. */
6882 for (j = last_order; j < longest_order; j++) {
6883 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6884 }
6885 } else {
6886
6887 /* Put all the same fields into the savegame - otherwise the
6888 * registry code can't correctly use a tabular format and the
6889 * savegame will be bigger. */
6890 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6891 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6892 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6893 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6894 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6895 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6896 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6897
6898 /* Fill in dummy values for order targets so the registry will save
6899 * the unit table in a tabular format. */
6900
6901 /* The start of a vector has no number. */
6902 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6903 for (j = 1; j < longest_order; j++) {
6904 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6905 }
6906
6907 /* The start of a vector has no number. */
6908 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6909 for (j = 1; j < longest_order; j++) {
6910 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6911 }
6912
6913 /* The start of a vector has no number. */
6914 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6915 for (j = 1; j < longest_order; j++) {
6916 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6917 }
6918 }
6919
6920 i++;
6922}
6923
6924/************************************************************************/
6928 struct player *plr)
6929{
6930 int plrno = player_number(plr);
6931
6932 /* Check status and return if not OK (sg_success FALSE). */
6933 sg_check_ret();
6934
6935 /* Toss any existing attribute_block (should not exist) */
6936 if (plr->attribute_block.data) {
6938 plr->attribute_block.data = NULL;
6939 }
6940
6941 /* This is a big heap of opaque data for the client, check everything! */
6943 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6944
6945 if (0 > plr->attribute_block.length) {
6946 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6947 plr->attribute_block.length);
6948 plr->attribute_block.length = 0;
6949 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6950 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6952 plr->attribute_block.length = 0;
6953 } else if (0 < plr->attribute_block.length) {
6954 int part_nr, parts;
6955 int quoted_length;
6956 char *quoted;
6957#ifndef FREECIV_NDEBUG
6958 size_t actual_length;
6959#endif
6960
6963 "player%d.attribute_v2_block_length_quoted",
6964 plrno), "%s", secfile_error());
6967 "player%d.attribute_v2_block_parts", plrno),
6968 "%s", secfile_error());
6969
6971 quoted[0] = '\0';
6973 for (part_nr = 0; part_nr < parts; part_nr++) {
6974 const char *current =
6976 "player%d.attribute_v2_block_data.part%d",
6977 plrno, part_nr);
6978 if (!current) {
6979 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6980 break;
6981 }
6982 log_debug("attribute_v2_block_length_quoted=%d"
6983 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
6984 quoted_length, strlen(quoted), strlen(current));
6985 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6986 strcat(quoted, current);
6987 }
6989 "attribute_v2_block_length_quoted=%d"
6990 " actual=" SIZE_T_PRINTF,
6992
6993#ifndef FREECIV_NDEBUG
6995#endif
6997 plr->attribute_block.data,
6998 plr->attribute_block.length);
7000 free(quoted);
7001 }
7002}
7003
7004/************************************************************************/
7008 struct player *plr)
7009{
7010 int plrno = player_number(plr);
7011
7012 /* Check status and return if not OK (sg_success FALSE). */
7013 sg_check_ret();
7014
7015 /* This is a big heap of opaque data from the client. Although the binary
7016 * format is not user editable, keep the lines short enough for debugging,
7017 * and hope that data compression will keep the file a reasonable size.
7018 * Note that the "quoted" format is a multiple of 3.
7019 */
7020#define PART_SIZE (3*256)
7021#define PART_ADJUST (3)
7022 if (plr->attribute_block.data) {
7023 char part[PART_SIZE + PART_ADJUST];
7024 int parts;
7025 int current_part_nr;
7027 plr->attribute_block.length);
7028 char *quoted_at = strchr(quoted, ':');
7029 size_t bytes_left = strlen(quoted);
7030 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7032
7034 "player%d.attribute_v2_block_length", plrno);
7036 "player%d.attribute_v2_block_length_quoted", plrno);
7037
7038 /* Try to wring some compression efficiencies out of the "quoted" format.
7039 * The first line has a variable length decimal, mis-aligning triples.
7040 */
7041 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7042 /* first line can be longer */
7043 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7044 } else {
7045 parts = 1;
7046 }
7047
7049 "player%d.attribute_v2_block_parts", plrno);
7050
7051 if (parts > 1) {
7053
7054 /* first line can be longer */
7056 part[size_of_current_part] = '\0';
7058 "player%d.attribute_v2_block_data.part%d",
7059 plrno, 0);
7062 current_part_nr = 1;
7063 } else {
7064 quoted_at = quoted;
7065 current_part_nr = 0;
7066 }
7067
7070
7072 part[size_of_current_part] = '\0';
7074 "player%d.attribute_v2_block_data.part%d",
7075 plrno,
7079 }
7080 fc_assert(bytes_left == 0);
7081 free(quoted);
7082 }
7083#undef PART_ADJUST
7084#undef PART_SIZE
7085}
7086
7087/************************************************************************/
7091 struct player *plr)
7092{
7093 int plrno = player_number(plr);
7094 int total_ncities =
7096 "player%d.dc_total", plrno);
7097 int i;
7098 bool someone_alive = FALSE;
7099
7100 /* Check status and return if not OK (sg_success FALSE). */
7101 sg_check_ret();
7102
7105 if (pteam_member->is_alive) {
7107 break;
7108 }
7110
7111 if (!someone_alive) {
7112 /* Reveal all for completely dead teams. */
7114 }
7115 }
7116
7117 if (-1 == total_ncities
7118 || !game.info.fogofwar
7120 "game.save_private_map")) {
7121 /* We have:
7122 * - a dead player;
7123 * - fogged cities are not saved for any reason;
7124 * - a savegame with fog of war turned off;
7125 * - or game.save_private_map is not set to FALSE in the scenario /
7126 * savegame. The players private knowledge is set to be what they could
7127 * see without fog of war. */
7128 whole_map_iterate(&(wld.map), ptile) {
7129 if (map_is_known(ptile, plr)) {
7130 struct city *pcity = tile_city(ptile);
7131
7132 update_player_tile_last_seen(plr, ptile);
7133 update_player_tile_knowledge(plr, ptile);
7134
7135 if (NULL != pcity) {
7136 update_dumb_city(plr, pcity);
7137 }
7138 }
7140
7141 /* Nothing more to do; */
7142 return;
7143 }
7144
7145 /* Load player map (terrain). */
7146 LOAD_MAP_CHAR(ch, ptile,
7147 map_get_player_tile(ptile, plr)->terrain
7148 = char2terrain(ch), loading->file,
7149 "player%d.map_t%04d", plrno);
7150
7151 /* Load player map (extras). */
7152 halfbyte_iterate_extras(j, loading->extra.size) {
7153 LOAD_MAP_CHAR(ch, ptile,
7155 ch, loading->extra.order + 4 * j),
7156 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7158
7159 whole_map_iterate(&(wld.map), ptile) {
7160 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7161
7163 if (BV_ISSET(plrtile->extras, extra_number(pres))) {
7164 plrtile->resource = pres;
7165 if (!terrain_has_resource(plrtile->terrain, pres)) {
7166 BV_CLR(plrtile->extras, extra_number(pres));
7167 }
7168 }
7171
7173 /* Load player map (border). */
7174 int x, y;
7175
7176 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7177 const char *buffer
7178 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7179 plrno, y);
7180 const char *buffer2
7181 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7182 plrno, y);
7183 const char *ptr = buffer;
7184 const char *ptr2 = buffer2;
7185
7186 sg_failure_ret(NULL != buffer,
7187 "Savegame corrupt - map line %d not found.", y);
7188 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7189 char token[TOKEN_SIZE];
7190 char token2[TOKEN_SIZE];
7191 int number;
7192 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7193
7194 scanin(&ptr, ",", token, sizeof(token));
7195 sg_failure_ret('\0' != token[0],
7196 "Savegame corrupt - map size not correct.");
7197 if (strcmp(token, "-") == 0) {
7198 map_get_player_tile(ptile, plr)->owner = NULL;
7199 } else {
7200 sg_failure_ret(str_to_int(token, &number),
7201 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7202 token, x, y);
7203 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7204 }
7205
7206 scanin(&ptr2, ",", token2, sizeof(token2));
7207 sg_failure_ret('\0' != token2[0],
7208 "Savegame corrupt - map size not correct.");
7209 if (strcmp(token2, "-") == 0) {
7210 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7211 } else {
7213 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7214 token, x, y);
7215 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7216 }
7217 }
7218 }
7219 }
7220
7221 /* Load player map (update time). */
7222 for (i = 0; i < 4; i++) {
7223 /* put 4-bit segments of 16-bit "updated" field */
7224 if (i == 0) {
7225 LOAD_MAP_CHAR(ch, ptile,
7226 map_get_player_tile(ptile, plr)->last_updated
7227 = ascii_hex2bin(ch, i),
7228 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7229 } else {
7230 LOAD_MAP_CHAR(ch, ptile,
7231 map_get_player_tile(ptile, plr)->last_updated
7232 |= ascii_hex2bin(ch, i),
7233 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7234 }
7235 }
7236
7237 /* Load player map known cities. */
7238 for (i = 0; i < total_ncities; i++) {
7239 struct vision_site *pdcity;
7240 char buf[32];
7241 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7242
7246 pdcity);
7248 } else {
7249 /* Error loading the data. */
7250 log_sg("Skipping seen city %d for player %d.", i, plrno);
7251 if (pdcity != NULL) {
7253 }
7254 }
7255 }
7256
7257 /* Repair inconsistent player maps. */
7258 whole_map_iterate(&(wld.map), ptile) {
7259 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7260 struct city *pcity = tile_city(ptile);
7261
7262 update_player_tile_knowledge(plr, ptile);
7263 reality_check_city(plr, ptile);
7264
7265 if (NULL != pcity) {
7266 update_dumb_city(plr, pcity);
7267 }
7268 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7269 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7270 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7271
7272 plrtile->owner = tile_owner(ptile);
7273 }
7275}
7276
7277/************************************************************************/
7281 struct player *plr,
7282 struct vision_site *pdcity,
7283 const char *citystr)
7284{
7285 const char *str;
7286 int i, id, size;
7287 citizens city_size;
7288 int nat_x, nat_y;
7289 const char *stylename;
7290 enum capital_type cap;
7291 const char *vname;
7292
7294 citystr),
7295 FALSE, "%s", secfile_error());
7297 citystr),
7298 FALSE, "%s", secfile_error());
7299 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7300 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7301 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7302
7303 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7304 citystr),
7305 FALSE, "%s", secfile_error());
7306 pdcity->owner = player_by_number(id);
7307 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7308 "%s has invalid owner (%d); skipping.", citystr, id);
7309
7311 "%s.id", citystr),
7312 FALSE, "%s", secfile_error());
7314 "%s has invalid id (%d); skipping.", citystr, id);
7315
7317 "%s.size", citystr),
7318 FALSE, "%s", secfile_error());
7319 city_size = (citizens)size; /* set the correct type */
7320 sg_warn_ret_val(size == (int)city_size, FALSE,
7321 "Invalid city size: %d; set to %d.", size, city_size);
7322 vision_site_size_set(pdcity, city_size);
7323
7324 /* Initialise list of improvements */
7325 BV_CLR_ALL(pdcity->improvements);
7326 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7328 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7329 "Invalid length of '%s.improvements' ("
7330 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7331 citystr, strlen(str), loading->improvement.size);
7332 for (i = 0; i < loading->improvement.size; i++) {
7333 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7334 "Undefined value '%c' within '%s.improvements'.",
7335 str[i], citystr)
7336
7337 if (str[i] == '1') {
7338 struct impr_type *pimprove =
7339 improvement_by_rule_name(loading->improvement.order[i]);
7340 if (pimprove) {
7341 BV_SET(pdcity->improvements, improvement_index(pimprove));
7342 }
7343 }
7344 }
7345
7347 "%s.name", citystr);
7348
7349 if (vname != NULL) {
7350 pdcity->name = fc_strdup(vname);
7351 }
7352
7354 "%s.occupied", citystr);
7356 "%s.walls", citystr);
7358 "%s.happy", citystr);
7360 "%s.unhappy", citystr);
7362 "%s.style", citystr);
7363 if (stylename != NULL) {
7365 } else {
7366 pdcity->style = 0;
7367 }
7368 if (pdcity->style < 0) {
7369 pdcity->style = 0;
7370 }
7371
7372 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7373 "%s.city_image", citystr);
7374
7376 "%s.capital", citystr),
7378
7380 pdcity->capital = cap;
7381 } else {
7382 pdcity->capital = CAPITAL_NOT;
7383 }
7384
7385 return TRUE;
7386}
7387
7388/************************************************************************/
7392 struct player *plr)
7393{
7394 int i, plrno = player_number(plr);
7395
7396 /* Check status and return if not OK (sg_success FALSE). */
7397 sg_check_ret();
7398
7400 /* The player can see all, there's no reason to save the private map. */
7401 return;
7402 }
7403
7404 /* Save the map (terrain). */
7405 SAVE_MAP_CHAR(ptile,
7407 saving->file, "player%d.map_t%04d", plrno);
7408
7410 /* Save the map (borders). */
7411 int x, y;
7412
7413 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7415
7416 line[0] = '\0';
7417 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7418 char token[TOKEN_SIZE];
7419 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7420 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7421
7422 if (plrtile == NULL || plrtile->owner == NULL) {
7423 strcpy(token, "-");
7424 } else {
7425 fc_snprintf(token, sizeof(token), "%d",
7426 player_number(plrtile->owner));
7427 }
7428 strcat(line, token);
7429 if (x < MAP_NATIVE_WIDTH) {
7430 strcat(line, ",");
7431 }
7432 }
7433 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7434 plrno, y);
7435 }
7436
7437 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7439
7440 line[0] = '\0';
7441 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7442 char token[TOKEN_SIZE];
7443 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7444 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7445
7446 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7447 strcpy(token, "-");
7448 } else {
7449 fc_snprintf(token, sizeof(token), "%d",
7450 player_number(plrtile->extras_owner));
7451 }
7452 strcat(line, token);
7453 if (x < MAP_NATIVE_WIDTH) {
7454 strcat(line, ",");
7455 }
7456 }
7457 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7458 plrno, y);
7459 }
7460 }
7461
7462 /* Save the map (extras). */
7464 int mod[4];
7465 int l;
7466
7467 for (l = 0; l < 4; l++) {
7468 if (4 * j + 1 > game.control.num_extra_types) {
7469 mod[l] = -1;
7470 } else {
7471 mod[l] = 4 * j + l;
7472 }
7473 }
7474
7475 SAVE_MAP_CHAR(ptile,
7477 map_get_player_tile(ptile, plr)->resource,
7478 mod),
7479 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7481
7482 /* Save the map (update time). */
7483 for (i = 0; i < 4; i++) {
7484 /* put 4-bit segments of 16-bit "updated" field */
7485 SAVE_MAP_CHAR(ptile,
7487 map_get_player_tile(ptile, plr)->last_updated, i),
7488 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7489 }
7490
7491 /* Save known cities. */
7492 i = 0;
7493 whole_map_iterate(&(wld.map), ptile) {
7494 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7495 char impr_buf[B_LAST + 1];
7496 char buf[32];
7497
7498 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7499
7500 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7501 int nat_x, nat_y;
7502
7504 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7505 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7506
7507 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7509 "%s.owner", buf);
7510
7512 "%s.size", buf);
7513 secfile_insert_bool(saving->file, pdcity->occupied,
7514 "%s.occupied", buf);
7515 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7516 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7517 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7519 "%s.style", buf);
7520 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7522 "%s.capital", buf);
7523
7524 /* Save improvement list as bitvector. Note that improvement order
7525 * is saved in savefile.improvement.order. */
7526 improvement_iterate(pimprove) {
7527 impr_buf[improvement_index(pimprove)]
7528 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7529 ? '1' : '0';
7531 impr_buf[improvement_count()] = '\0';
7533 "Invalid size of the improvement vector (%s.improvements: "
7534 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7535 buf, strlen(impr_buf), sizeof(impr_buf));
7536 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7537 if (pdcity->name != NULL) {
7538 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7539 }
7540
7541 i++;
7542 }
7544
7545 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7546}
7547
7548/* =======================================================================
7549 * Load / save the researches.
7550 * ======================================================================= */
7551
7552/************************************************************************/
7556{
7557 struct research *presearch;
7558 int count;
7559 int number;
7560 const char *str;
7561 int i, j;
7562 int *vlist_research;
7563
7565 /* Check status and return if not OK (sg_success FALSE). */
7566 sg_check_ret();
7567
7568 /* Initialize all researches. */
7572
7573 /* May be unsaved (e.g. scenario case). */
7574 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7575 for (i = 0; i < count; i++) {
7577 "research.r%d.number", i),
7578 "%s", secfile_error());
7579 presearch = research_by_number(number);
7581 "Invalid research number %d in 'research.r%d.number'",
7582 number, i);
7583
7584 presearch->tech_goal = technology_load(loading->file,
7585 "research.r%d.goal", i);
7587 &presearch->techs_researched,
7588 "research.r%d.techs", i),
7589 "%s", secfile_error());
7591 &presearch->future_tech,
7592 "research.r%d.futuretech", i),
7593 "%s", secfile_error());
7595 &presearch->bulbs_researched,
7596 "research.r%d.bulbs", i),
7597 "%s", secfile_error());
7599 &presearch->bulbs_researching_saved,
7600 "research.r%d.bulbs_before", i),
7601 "%s", secfile_error());
7602 presearch->researching_saved = technology_load(loading->file,
7603 "research.r%d.saved", i);
7604 presearch->researching = technology_load(loading->file,
7605 "research.r%d.now", i);
7607 &presearch->free_bulbs,
7608 "research.r%d.free_bulbs", i),
7609 "%s", secfile_error());
7610
7611 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7612 sg_failure_ret(str != NULL, "%s", secfile_error());
7613 sg_failure_ret(strlen(str) == loading->technology.size,
7614 "Invalid length of 'research.r%d.done' ("
7615 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7616 i, strlen(str), loading->technology.size);
7617 for (j = 0; j < loading->technology.size; j++) {
7618 sg_failure_ret(str[j] == '1' || str[j] == '0',
7619 "Undefined value '%c' within 'research.r%d.done'.",
7620 str[j], i);
7621
7622 if (str[j] == '1') {
7623 struct advance *padvance =
7624 advance_by_rule_name(loading->technology.order[j]);
7625
7626 if (padvance) {
7628 TECH_KNOWN);
7629 }
7630 }
7631 }
7632
7634 size_t count_res;
7635 int tn;
7636
7638 "research.r%d.vbs", i);
7639
7640 for (tn = 0; tn < count_res; tn++) {
7641 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7642
7643 if (padvance != NULL) {
7644 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7645 = vlist_research[tn];
7646 }
7647 }
7648 }
7649 }
7650
7651 /* In case of tech_leakage, we can update research only after all the
7652 * researches have been loaded */
7656}
7657
7658/************************************************************************/
7662{
7663 char invs[A_LAST];
7664 int i = 0;
7665 int *vlist_research;
7666
7668 /* Check status and return if not OK (sg_success FALSE). */
7669 sg_check_ret();
7670
7671 if (saving->save_players) {
7674 "research.r%d.number", i);
7675 technology_save(saving->file, "research.r%d.goal",
7676 i, presearch->tech_goal);
7677 secfile_insert_int(saving->file, presearch->techs_researched,
7678 "research.r%d.techs", i);
7679 secfile_insert_int(saving->file, presearch->future_tech,
7680 "research.r%d.futuretech", i);
7681 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7682 "research.r%d.bulbs_before", i);
7686 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7690 "research.r%d.vbs", i);
7691 if (vlist_research) {
7693 }
7694 }
7695 technology_save(saving->file, "research.r%d.saved",
7696 i, presearch->researching_saved);
7697 secfile_insert_int(saving->file, presearch->bulbs_researched,
7698 "research.r%d.bulbs", i);
7699 technology_save(saving->file, "research.r%d.now",
7700 i, presearch->researching);
7701 secfile_insert_int(saving->file, presearch->free_bulbs,
7702 "research.r%d.free_bulbs", i);
7703 /* Save technology lists as bytevector. Note that technology order is
7704 * saved in savefile.technology.order */
7705 advance_index_iterate(A_NONE, tech_id) {
7706 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7708 == TECH_KNOWN ? '1' : '0');
7711 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7712 i++;
7714 secfile_insert_int(saving->file, i, "research.count");
7715 }
7716}
7717
7718/* =======================================================================
7719 * Load / save the event cache. Should be the last thing to do.
7720 * ======================================================================= */
7721
7722/************************************************************************/
7726{
7727 /* Check status and return if not OK (sg_success FALSE). */
7728 sg_check_ret();
7729
7730 event_cache_load(loading->file, "event_cache");
7731}
7732
7733/************************************************************************/
7737{
7738 /* Check status and return if not OK (sg_success FALSE). */
7739 sg_check_ret();
7740
7741 if (saving->scenario) {
7742 /* Do _not_ save events in a scenario. */
7743 return;
7744 }
7745
7746 event_cache_save(saving->file, "event_cache");
7747}
7748
7749/* =======================================================================
7750 * Load / save the open treaties
7751 * ======================================================================= */
7752
7753/************************************************************************/
7757{
7758 int tidx;
7759 const char *plr0;
7760
7761 /* Check status and return if not OK (sg_success FALSE). */
7762 sg_check_ret();
7763
7764 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7765 "treaty%d.plr0", tidx)) != NULL ;
7766 tidx++) {
7767 const char *plr1;
7768 const char *ct;
7769 int cidx;
7770 struct player *p0, *p1;
7771
7772 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7773
7774 p0 = player_by_name(plr0);
7775 p1 = player_by_name(plr1);
7776
7777 if (p0 == NULL || p1 == NULL) {
7778 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7779 } else {
7780 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7781
7784
7785 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7786 "treaty%d.clause%d.type",
7787 tidx, cidx)) != NULL ;
7788 cidx++ ) {
7790 const char *plrx;
7791
7792 if (!clause_type_is_valid(type)) {
7793 log_error("Invalid clause type \"%s\"", ct);
7794 } else {
7795 struct player *pgiver = NULL;
7796
7797 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7798 tidx, cidx);
7799
7800 if (!fc_strcasecmp(plrx, plr0)) {
7801 pgiver = p0;
7802 } else if (!fc_strcasecmp(plrx, plr1)) {
7803 pgiver = p1;
7804 } else {
7805 log_error("Clause giver %s is not participant of the treaty"
7806 "between %s and %s", plrx, plr0, plr1);
7807 }
7808
7809 if (pgiver != NULL) {
7810 int value;
7811
7812 value = secfile_lookup_int_default(loading->file, 0,
7813 "treaty%d.clause%d.value",
7814 tidx, cidx);
7815
7816 add_clause(ptreaty, pgiver, type, value, NULL);
7817 }
7818 }
7819 }
7820
7821 /* These must be after clauses have been added so that acceptance
7822 * does not get cleared by what seems like changes to the treaty. */
7824 "treaty%d.accept0", tidx);
7826 "treaty%d.accept1", tidx);
7827 }
7828 }
7829}
7830
7831typedef struct {
7832 int tidx;
7835
7836/************************************************************************/
7839static void treaty_save(struct Treaty *ptr, void *data_in)
7840{
7841 char tpath[512];
7842 int cidx = 0;
7844
7845 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7846
7847 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7848 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7849 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7850 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7851
7853 char cpath[512];
7854
7855 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7856
7857 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7858 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7859 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7861}
7862
7863/************************************************************************/
7867{
7868 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7869
7871}
7872
7873/* =======================================================================
7874 * Load / save the history report
7875 * ======================================================================= */
7876
7877/************************************************************************/
7881{
7883 int turn;
7884
7885 /* Check status and return if not OK (sg_success FALSE). */
7886 sg_check_ret();
7887
7888 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7889
7890 if (turn != -2) {
7891 hist->turn = turn;
7892 }
7893
7894 if (turn + 1 >= game.info.turn) {
7895 const char *str;
7896
7897 str = secfile_lookup_str(loading->file, "history.title");
7898 sg_failure_ret(str != NULL, "%s", secfile_error());
7899 sz_strlcpy(hist->title, str);
7900 str = secfile_lookup_str(loading->file, "history.body");
7901 sg_failure_ret(str != NULL, "%s", secfile_error());
7902 sz_strlcpy(hist->body, str);
7903 }
7904}
7905
7906/************************************************************************/
7909static void sg_save_history(struct savedata *saving)
7910{
7912
7913 secfile_insert_int(saving->file, hist->turn, "history.turn");
7914
7915 if (hist->turn + 1 >= game.info.turn) {
7916 secfile_insert_str(saving->file, hist->title, "history.title");
7917 secfile_insert_str(saving->file, hist->body, "history.body");
7918 }
7919}
7920
7921/* =======================================================================
7922 * Load / save the mapimg definitions.
7923 * ======================================================================= */
7924
7925/************************************************************************/
7928static void sg_load_mapimg(struct loaddata *loading)
7929{
7930 int mapdef_count, i;
7931
7932 /* Check status and return if not OK (sg_success FALSE). */
7933 sg_check_ret();
7934
7935 /* Clear all defined map images. */
7936 while (mapimg_count() > 0) {
7937 mapimg_delete(0);
7938 }
7939
7941 "mapimg.count");
7942 log_verbose("Saved map image definitions: %d.", mapdef_count);
7943
7944 if (0 >= mapdef_count) {
7945 return;
7946 }
7947
7948 for (i = 0; i < mapdef_count; i++) {
7949 const char *p;
7950
7951 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7952 if (NULL == p) {
7953 log_verbose("[Mapimg %4d] Missing definition.", i);
7954 continue;
7955 }
7956
7957 if (!mapimg_define(p, FALSE)) {
7958 log_error("Invalid map image definition %4d: %s.", i, p);
7959 }
7960
7961 log_verbose("Mapimg %4d loaded.", i);
7962 }
7963}
7964
7965/************************************************************************/
7968static void sg_save_mapimg(struct savedata *saving)
7969{
7970 /* Check status and return if not OK (sg_success FALSE). */
7971 sg_check_ret();
7972
7973 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7974 if (mapimg_count() > 0) {
7975 int i;
7976
7977 for (i = 0; i < mapimg_count(); i++) {
7978 char buf[MAX_LEN_MAPDEF];
7979
7980 mapimg_id2str(i, buf, sizeof(buf));
7981 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7982 }
7983 }
7984}
7985
7986/* =======================================================================
7987 * Sanity checks for loading / saving a game.
7988 * ======================================================================= */
7989
7990/************************************************************************/
7994{
7995 int players;
7996
7997 /* Check status and return if not OK (sg_success FALSE). */
7998 sg_check_ret();
7999
8000 if (game.info.is_new_game) {
8001 /* Nothing to do for new games (or not started scenarios). */
8002 return;
8003 }
8004
8005 /* Old savegames may have maxplayers lower than current player count,
8006 * fix. */
8007 players = normal_player_count();
8008 if (game.server.max_players < players) {
8009 log_verbose("Max players lower than current players, fixing");
8010 game.server.max_players = players;
8011 }
8012
8013 /* Fix ferrying sanity */
8014 players_iterate(pplayer) {
8015 unit_list_iterate_safe(pplayer->units, punit) {
8018 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8024 }
8027
8028 /* Fix stacking issues. We don't rely on the savegame preserving
8029 * alliance invariants (old savegames often did not) so if there are any
8030 * unallied units on the same tile we just bounce them. */
8031 players_iterate(pplayer) {
8033 resolve_unit_stacks(pplayer, aplayer, TRUE);
8036
8037 /* Recalculate the potential buildings for each city. Has caused some
8038 * problems with game random state.
8039 * This also changes the game state if you save the game directly after
8040 * loading it and compare the results. */
8041 players_iterate(pplayer) {
8042 /* Building advisor needs data phase open in order to work */
8043 adv_data_phase_init(pplayer, FALSE);
8044 building_advisor(pplayer);
8045 /* Close data phase again so it can be opened again when game starts. */
8046 adv_data_phase_done(pplayer);
8048
8049 /* Prevent a buggy or intentionally crafted save game from crashing
8050 * Freeciv. See hrm Bug #887748 */
8051 players_iterate(pplayer) {
8052 city_list_iterate(pplayer->cities, pcity) {
8053 worker_task_list_iterate(pcity->task_reqs, ptask) {
8054 if (!worker_task_is_sane(ptask)) {
8055 log_error("[city id: %d] Bad worker task %d.",
8056 pcity->id, ptask->act);
8057 worker_task_list_remove(pcity->task_reqs, ptask);
8058 free(ptask);
8059 ptask = NULL;
8060 }
8064
8065 /* Check worked tiles map */
8066#ifdef FREECIV_DEBUG
8067 if (loading->worked_tiles != NULL) {
8068 /* check the entire map for unused worked tiles */
8069 whole_map_iterate(&(wld.map), ptile) {
8070 if (loading->worked_tiles[ptile->index] != -1) {
8071 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8072 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8073 }
8075 }
8076#endif /* FREECIV_DEBUG */
8077
8078 /* Check researching technologies and goals. */
8080 int techs;
8081
8082 if (presearch->researching != A_UNSET
8083 && !is_future_tech(presearch->researching)
8084 && (valid_advance_by_number(presearch->researching) == NULL
8086 != TECH_PREREQS_KNOWN))) {
8087 log_sg(_("%s had invalid researching technology."),
8089 presearch->researching = A_UNSET;
8090 }
8091 if (presearch->tech_goal != A_UNSET
8092 && !is_future_tech(presearch->tech_goal)
8093 && (valid_advance_by_number(presearch->tech_goal) == NULL
8096 == TECH_KNOWN))) {
8097 log_sg(_("%s had invalid technology goal."),
8099 presearch->tech_goal = A_UNSET;
8100 }
8101
8103
8104 if (presearch->techs_researched != techs) {
8105 sg_regr(3000300,
8106 _("%s had finished researches count wrong."),
8108 presearch->techs_researched = techs;
8109 }
8111
8112 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8113 players_iterate(pplayer) {
8114 int unique_count[U_LAST];
8115
8116 memset(unique_count, 0, sizeof(unique_count));
8117
8118 unit_list_iterate(pplayer->units, punit) {
8121
8124 log_sg(_("%s has multiple units of type %s though it should be possible "
8125 "to have only one."),
8127 }
8130
8131 players_iterate(pplayer) {
8132 unit_list_iterate_safe(pplayer->units, punit) {
8134 punit->orders.list)) {
8135 log_sg("Invalid unit orders for unit %d.", punit->id);
8137 }
8140
8141 /* Check max rates (rules may have changed since saving) */
8142 players_iterate(pplayer) {
8145
8146 if (0 == strlen(server.game_identifier)
8147 || !is_base64url(server.game_identifier)) {
8148 /* This uses fc_rand(), so random state has to be initialized before. */
8149 randomize_base64url_string(server.game_identifier,
8150 sizeof(server.game_identifier));
8151 }
8152
8153 /* Restore game random state, just in case various initialization code
8154 * inexplicably altered the previously existing state. */
8155 if (!game.info.is_new_game) {
8156 fc_rand_set_state(loading->rstate);
8157 }
8158
8159 /* At the end do the default sanity checks. */
8160 sanity_check();
8161}
8162
8163/************************************************************************/
8167{
8168 /* Check status and return if not OK (sg_success FALSE). */
8169 sg_check_ret();
8170}
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:1225
struct action * action_by_rule_name(const char *name)
Definition actions.c:1054
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1214
bool action_id_exists(const action_id act_id)
Definition actions.c:1043
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:411
#define NUM_ACTIONS
Definition actions.h:59
#define action_id_get_activity(act_id)
Definition actions.h:456
#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:262
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:564
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
int ai_type_get_count(void)
Definition ai.c:327
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define ai_type_iterate_end
Definition ai.h:372
#define ai_type_iterate(NAME_ai)
Definition ai.h:365
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:179
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool has_capabilities(const char *us, const char *them)
Definition capability.c: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:1141
const char * city_name_get(const struct city *pcity)
Definition city.c:1133
const char * city_style_rule_name(const int style)
Definition city.c:1761
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3426
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2867
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1176
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3353
void destroy_city_virtual(struct city *pcity)
Definition city.c:3512
int city_style_by_rule_name(const char *s)
Definition city.c:1734
#define cities_iterate_end
Definition city.h:517
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
#define cities_iterate(pcity)
Definition city.h:512
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:86
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define output_type_iterate(output)
Definition city.h:836
#define FREE_WORKED_TILES
Definition city.h:873
#define MAX_CITY_SIZE
Definition city.h:106
#define city_list_iterate_end
Definition city.h:510
#define I_NEVER
Definition city.h:247
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
#define city_tile_iterate_end
Definition city.h:238
#define output_type_iterate_end
Definition city.h:842
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2751
bool send_city_suppression(bool now)
Definition citytools.c:2159
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:2822
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3426
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:365
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:850
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
char * techs
Definition comments.c:30
char * incite_cost
Definition comments.c:74
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
int counter_index(const struct counter *pcount)
Definition counters.c:174
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
int counters_get_city_counters_count(void)
Definition counters.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:108
struct Treaty * ptreaty
Definition diplodlg_g.h:28
void init_treaty(struct Treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
bool add_clause(struct Treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaty_add(struct Treaty *ptreaty)
Definition diptreaty.c:377
#define clause_list_iterate_end
Definition diptreaty.h:71
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:69
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:159
#define NO_TARGET
Definition fc_types.h:358
int Tech_type_id
Definition fc_types.h:381
unsigned char citizens
Definition fc_types.h:392
#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:390
#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:686
struct city * game_city_by_number(int id)
Definition game.c:106
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:595
#define GAME_DEFAULT_SCORETURN
Definition game.h:579
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:594
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:597
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:596
#define GAME_DEFAULT_RULESETDIR
Definition game.h:673
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:599
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:614
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:122
#define governments_iterate_end
Definition government.h:125
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:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_fatal(message,...)
Definition log.h:100
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1678
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:647
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:1895
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1694
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1717
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1790
void main_map_allocate(void)
Definition map.c:525
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:462
int map_startpos_count(void)
Definition map.c:1882
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:449
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1777
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1661
void map_init_topology(void)
Definition map.c:306
#define map_startpos_iterate(NAME_psp)
Definition map.h:125
#define map_startpos_iterate_end
Definition map.h:128
#define whole_map_iterate(_map, _tile)
Definition map.h:531
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:150
#define whole_map_iterate_end
Definition map.h:540
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:1228
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1474
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2212
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:901
bool send_tile_suppression(bool now)
Definition maphand.c:475
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:345
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1203
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1405
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1374
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2225
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1185
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:927
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1166
void map_calculate_borders(void)
Definition maphand.c:2378
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1639
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1389
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:784
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:904
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:539
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:534
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:557
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define player_slots_iterate(_pslot)
Definition player.h:525
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:559
#define players_iterate_alive_end
Definition player.h:549
#define player_slots_iterate_end
Definition player.h:529
#define players_iterate_alive(_pplayer)
Definition player.h:544
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2268
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1894
int normal_player_count(void)
Definition plrhand.c:3211
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2057
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2456
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2406
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3257
void shuffle_players(void)
Definition plrhand.c:2381
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1943
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1618
void assign_player_colors(void)
Definition plrhand.c:1734
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3244
void fit_nationset_to_players(void)
Definition plrhand.c:2662
#define shuffled_players_iterate_end
Definition plrhand.h:108
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
bool fc_rand_is_init(void)
Definition rand.c:200
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c: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,...)
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,...)
struct history_report * history_report_get(void)
Definition report.c:1825
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:9115
#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:7909
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:3018
static void unit_ordering_apply(void)
Definition savegame3.c:1079
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3709
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:3590
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3249
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:3081
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3551
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4164
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:219
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5655
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5607
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5041
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2917
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:6126
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:6057
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:3194
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7555
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3507
#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:6616
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7880
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7866
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3371
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7661
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:4225
static char order2char(enum unit_orders order)
Definition savegame3.c:737
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7756
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:6669
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:7391
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:5160
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1227
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8166
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7928
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6927
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7007
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2064
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2872
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7090
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2957
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:7968
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:7280
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2702
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3107
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:623
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3969
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:2985
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:7736
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3049
static void treaty_save(struct Treaty *ptr, void *data_in)
Definition savegame3.c:7839
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:7993
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7725
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:4715
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:3646
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:4906
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4818
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:1920
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:3496
const char * aifill(int amount)
Definition srv_main.c:2505
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:2310
enum server_states server_state(void)
Definition srv_main.c:338
void server_game_free(void)
Definition srv_main.c:3520
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * plr0
Definition diptreaty.h:80
bool accept0
Definition diptreaty.h:81
bool accept1
Definition diptreaty.h:81
struct clause_list * clauses
Definition diptreaty.h:82
struct player * plr1
Definition diptreaty.h:80
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
int turn
Definition city.h:246
Definition city.h:320
struct worker_task_list * task_reqs
Definition city.h:412
int turn_last_built
Definition city.h:387
enum city_wl_cancel_behavior wlcb
Definition city.h:404
int food_stock
Definition city.h:367
struct built_status built[B_LAST]
Definition city.h:394
struct player * original
Definition city.h:324
int history
Definition city.h:410
int * counter_values
Definition city.h:408
bool did_sell
Definition city.h:380
int id
Definition city.h:326
int last_turns_shield_surplus
Definition city.h:392
int disbanded_shields
Definition city.h:391
int turn_plague
Definition city.h:374
bv_city_options city_options
Definition city.h:403
bool was_happy
Definition city.h:381
enum city_acquire_type acquire_t
Definition city.h:329
int turn_founded
Definition city.h:386
int airlift
Definition city.h:378
int caravan_shields
Definition city.h:390
bool did_buy
Definition city.h:379
struct trade_route_list * routes
Definition city.h:344
int anarchy
Definition city.h:384
struct worklist worklist
Definition city.h:401
struct universal production
Definition city.h:396
struct unit_order * orders
Definition city.h:422
struct city::@16 rally_point
struct adv_city * adv
Definition city.h:452
bool vigilant
Definition city.h:421
int steal
Definition city.h:414
int before_change_shields
Definition city.h:389
int style
Definition city.h:327
bool had_famine
Definition city.h:382
size_t length
Definition city.h:417
bool synced
Definition city.h:448
citizens specialists[SP_MAX]
Definition city.h:336
struct tile * tile
Definition city.h:322
int shield_stock
Definition city.h:368
struct vision * vision
Definition city.h:455
struct city::@17::@19 server
struct cm_parameter * cm_parameter
Definition city.h:425
struct universal changed_from
Definition city.h:399
struct unit_list * units_supported
Definition city.h:406
bool persistent
Definition city.h:419
int rapture
Definition city.h:385
bool multiresearch
Definition game.h:163
bool last_updated_year
Definition game.h:236
int world_peace_start
Definition game.h:238
float turn_change_time
Definition game.h:218
bool vision_reveal_tiles
Definition game.h:200
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:262
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:234
struct civ_game::@31::@35::@37 save_options
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:207
char rulesetdir[MAX_LEN_NAME]
Definition game.h:239
int additional_phase_seconds
Definition game.h:212
struct section_file * luadata
Definition game.h:247
int scoreturn
Definition game.h:225
randseed seed
Definition game.h:227
int dbid
Definition game.h:248
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:203
struct timer * phase_timer
Definition game.h:211
unsigned revealmap
Definition game.h:177
char orig_game_version[MAX_LEN_NAME]
Definition game.h:221
bool save_known
Definition game.h:259
bool foggedborders
Definition game.h:147
struct civ_game::@31::@35 server
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:205
int timeoutinc
Definition game.h:204
int phase_mode_stored
Definition game.h:216
int max_players
Definition game.h:156
bool save_starts
Definition game.h:261
int timeoutintinc
Definition game.h:206
randseed seed
Definition map_types.h:93
bool have_resources
Definition map_types.h:109
struct civ_map::@42::@44 server
bool altitude_info
Definition map_types.h:74
bool have_huts
Definition map_types.h:108
enum map_generator generator
Definition map_types.h:99
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:62
struct section_file * file
Definition savecompat.h:48
int great_wonder_owners[B_LAST]
bool global_advances[A_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char version[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char datafile[MAX_LEN_NAME]
char authors[MAX_LEN_PACKET/3]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:116
struct ai_trait * traits
Definition player.h:126
enum barbarian_type barbarian_type
Definition player.h:122
int science_cost
Definition player.h:119
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:124
int expand
Definition player.h:118
int fuzzy
Definition player.h:117
enum diplstate_type type
Definition player.h:199
int infra_points
Definition player.h:67
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int angry
Definition player.h:89
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:281
int bulbs_last_turn
Definition player.h:351
struct player_ai ai_common
Definition player.h:288
bv_plr_flags flags
Definition player.h:292
bool is_male
Definition player.h:257
int wonders[B_LAST]
Definition player.h:305
bool unassigned_ranked
Definition player.h:255
struct government * target_government
Definition player.h:259
int autoselect_weight
Definition player.h:299
char username[MAX_LEN_NAME]
Definition player.h:252
int revolution_finishes
Definition player.h:273
int nturns_idle
Definition player.h:265
struct government * government
Definition player.h:258
struct team * team
Definition player.h:261
int turns_alive
Definition player.h:266
const struct ai_type * ai
Definition player.h:289
struct unit_list * units
Definition player.h:282
char ranked_username[MAX_LEN_NAME]
Definition player.h:254
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
bv_player real_embassy
Definition player.h:277
struct player_economic economic
Definition player.h:284
struct player_spaceship spaceship
Definition player.h:286
struct attribute_block_s attribute_block
Definition player.h:307
struct player_score score
Definition player.h:283
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:314
struct nation_type * nation
Definition player.h:260
struct nation_style * style
Definition player.h:279
bool border_vision
Definition player.h:327
bool phase_done
Definition player.h:263
struct adv_data * adv
Definition player.h:334
struct player::@70::@72 server
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:7833
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
struct unit::@80 orders
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
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::@81::@84 server
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 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
enum universals_n kind
Definition fc_types.h:880
universals_u value
Definition fc_types.h:879
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:189
#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:190
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:249
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:276
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:277
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:245
void init_tech(struct research *research, bool update)
Definition techtools.c:1093
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:264
void timer_stop(struct timer *t)
Definition timing.c:308
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:384
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
const struct impr_type * building
Definition fc_types.h:691
void free_unit_orders(struct unit *punit)
Definition unit.c:1807
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2428
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1275
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2499
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:866
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1662
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2707
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:1133
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1767
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1285
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1115
#define unit_tile(_pu)
Definition unit.h:397
#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:396
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1402
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5001
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1226
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1063
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2613
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define unit_type_iterate(_p)
Definition unittype.h:859
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:866
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:165
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:155
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h:128
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
#define worker_task_list_iterate_end
Definition workertask.h:35
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
#define MAX_LEN_WORKLIST
Definition worklist.h:24
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT