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 "score.h"
123#include "settings.h"
124#include "spacerace.h"
125#include "srv_main.h"
126#include "stdinhand.h"
127#include "techtools.h"
128#include "unittools.h"
129
130/* server/advisors */
131#include "advdata.h"
132#include "advbuilding.h"
133#include "infracache.h"
134
135/* server/generator */
136#include "mapgen.h"
137#include "mapgen_utils.h"
138
139/* server/scripting */
140#include "script_server.h"
141
142/* server/savegame */
143#include "savecompat.h"
144#include "savemain.h"
145
146/* ai */
147#include "aitraits.h"
148#include "difficulty.h"
149
150#include "savegame3.h"
151
152extern bool sg_success;
153
154#define ACTIVITY_OLD_POLLUTION_SG3 (ACTIVITY_LAST + 1)
155#define ACTIVITY_OLD_FALLOUT_SG3 (ACTIVITY_OLD_POLLUTION_SG3 + 1)
156#define ACTIVITY_LAST_SAVEGAME3 (ACTIVITY_OLD_FALLOUT_SG3 + 1)
157
158#ifdef FREECIV_TESTMATIC
159#define SAVE_DUMMY_TURN_CHANGE_TIME 1
160#endif
161
162/*
163 * This loops over the entire map to save data. It collects all the data of
164 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
165 *
166 * Parameters:
167 * ptile: current tile within the line (used by GET_XY_CHAR)
168 * GET_XY_CHAR: macro returning the map character for each position
169 * secfile: a secfile struct
170 * secpath, ...: path as used for sprintf() with arguments; the last item
171 * will be the y coordinate
172 * Example:
173 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
174 */
175#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
176{ \
177 char _line[MAP_NATIVE_WIDTH + 1]; \
178 int _nat_x, _nat_y; \
179 \
180 for (_nat_y = 0; _nat_y < MAP_NATIVE_HEIGHT; _nat_y++) { \
181 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _nat_x++) { \
182 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
183 fc_assert_action(ptile != NULL, continue); \
184 _line[_nat_x] = (GET_XY_CHAR); \
185 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
186 "Trying to write invalid map data at position " \
187 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
188 secpath, _line[_nat_x], _line[_nat_x]); \
189 } \
190 _line[MAP_NATIVE_WIDTH] = '\0'; \
191 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
192 } \
193}
194
195/*
196 * This loops over the entire map to load data. It inputs a line of data
197 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
198 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
199 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
200 * macro but definable by the caller.
201 *
202 * Parameters:
203 * ch: a variable to hold a char (data for a single position,
204 * used by SET_XY_CHAR)
205 * ptile: current tile within the line (used by SET_XY_CHAR)
206 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
207 * secfile: a secfile struct
208 * secpath, ...: path as used for sprintf() with arguments; the last item
209 * will be the y coordinate
210 * Example:
211 * LOAD_MAP_CHAR(ch, ptile,
212 * map_get_player_tile(ptile, plr)->terrain
213 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
214 *
215 * Note: some (but not all) of the code this is replacing used to skip over
216 * lines that did not exist. This allowed for backward-compatibility.
217 * We could add another parameter that specified whether it was OK to
218 * skip the data, but there's not really much advantage to exiting
219 * early in this case. Instead, we let any map data type to be empty,
220 * and just print an informative warning message about it.
221 */
222#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
223{ \
224 int _nat_x, _nat_y; \
225 bool _printed_warning = FALSE; \
226 for (_nat_y = 0; _nat_y < MAP_NATIVE_HEIGHT; _nat_y++) { \
227 const char *_line = secfile_lookup_str(secfile, secpath, \
228 ## __VA_ARGS__, _nat_y); \
229 if (NULL == _line) { \
230 char buf[64]; \
231 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
232 log_verbose("Line not found='%s'", buf); \
233 _printed_warning = TRUE; \
234 continue; \
235 } else if (strlen(_line) != MAP_NATIVE_WIDTH) { \
236 char buf[64]; \
237 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
238 log_verbose("Line too short (expected %d got " SIZE_T_PRINTF \
239 ")='%s'", MAP_NATIVE_WIDTH, strlen(_line), buf); \
240 _printed_warning = TRUE; \
241 continue; \
242 } \
243 for (_nat_x = 0; _nat_x < MAP_NATIVE_WIDTH; _nat_x++) { \
244 const char ch = _line[_nat_x]; \
245 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
246 (SET_XY_CHAR); \
247 } \
248 } \
249 if (_printed_warning) { \
250 /* TRANS: Minor error message. */ \
251 log_sg(_("Saved game contains incomplete map data. This can" \
252 " happen with old saved games, or it may indicate an" \
253 " invalid saved game file. Proceed at your own risk.")); \
254 } \
255}
256
257/* Iterate on the extras half-bytes */
258#define halfbyte_iterate_extras(e, num_extras_types) \
259{ \
260 int e; \
261 for (e = 0; 4 * e < (num_extras_types); e++) {
262
263#define halfbyte_iterate_extras_end \
264 } \
265}
266
267struct savedata {
270
271 /* set by the caller */
272 const char *save_reason;
274
275 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
277};
278
279#define TOKEN_SIZE 10
280
281static const char savefile_options_default[] =
282 " +version3";
283/* The following savefile option are added if needed:
284 * - nothing at current version
285 * See also calls to sg_save_savefile_options(). */
286
287static void savegame3_save_real(struct section_file *file,
288 const char *save_reason,
289 bool scenario);
290static struct loaddata *loaddata_new(struct section_file *file);
291static void loaddata_destroy(struct loaddata *loading);
292
293static struct savedata *savedata_new(struct section_file *file,
294 const char *save_reason,
295 bool scenario);
296static void savedata_destroy(struct savedata *saving);
297
298static enum unit_orders char2order(char order);
299static char order2char(enum unit_orders order);
300static enum direction8 char2dir(char dir);
301static char dir2char(enum direction8 dir);
302static char activity2char(int activity);
303static enum unit_activity char2activity(char activity);
304static char *quote_block(const void *const data, int length);
305static int unquote_block(const char *const quoted_, void *dest,
306 int dest_length);
307static void worklist_load(struct section_file *file, int wlist_max_length,
308 struct worklist *pwl, const char *path, ...);
309static void worklist_save(struct section_file *file,
310 const struct worklist *pwl,
311 int max_length, const char *path, ...);
312static void unit_ordering_calc(void);
313static void unit_ordering_apply(void);
314static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx);
315static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx);
316static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
317 const int *idx);
318static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
319 const int *idx);
320static struct terrain *char2terrain(char ch);
321static char terrain2char(const struct terrain *pterrain);
322static Tech_type_id technology_load(struct section_file *file,
323 const char *path, int plrno);
324static void technology_save(struct section_file *file,
325 const char *path, int plrno, Tech_type_id tech);
326
327static void sg_load_savefile(struct loaddata *loading);
328static void sg_save_savefile(struct savedata *saving);
329static void sg_save_savefile_options(struct savedata *saving,
330 const char *option);
331
332static void sg_load_game(struct loaddata *loading);
333static void sg_save_game(struct savedata *saving);
334
335static void sg_load_ruledata(struct loaddata *loading);
336static void sg_save_ruledata(struct savedata *saving);
337
338static void sg_load_random(struct loaddata *loading);
339static void sg_save_random(struct savedata *saving);
340
341static void sg_load_script(struct loaddata *loading);
342static void sg_save_script(struct savedata *saving);
343
344static void sg_load_scenario(struct loaddata *loading);
345static void sg_save_scenario(struct savedata *saving);
346
347static void sg_load_settings(struct loaddata *loading);
348static void sg_save_settings(struct savedata *saving);
349
350static void sg_load_counters (struct loaddata * loading);
351static void sg_save_counters (struct savedata * saving);
352
353static void sg_load_map(struct loaddata *loading);
354static void sg_save_map(struct savedata *saving);
355static void sg_load_map_tiles(struct loaddata *loading);
356static void sg_load_map_altitude(struct loaddata *loading);
357static void sg_save_map_tiles(struct savedata *saving);
358static void sg_save_map_altitude(struct savedata *saving);
359static void sg_load_map_tiles_extras(struct loaddata *loading);
360static void sg_save_map_tiles_extras(struct savedata *saving);
361
362static void sg_load_map_startpos(struct loaddata *loading);
363static void sg_save_map_startpos(struct savedata *saving);
364static void sg_load_map_owner(struct loaddata *loading);
365static void sg_save_map_owner(struct savedata *saving);
366static void sg_load_map_worked(struct loaddata *loading);
367static void sg_save_map_worked(struct savedata *saving);
368static void sg_load_map_known(struct loaddata *loading);
369static void sg_save_map_known(struct savedata *saving);
370
371static void sg_load_players_basic(struct loaddata *loading);
372static void sg_load_players(struct loaddata *loading);
373static void sg_load_player_main(struct loaddata *loading,
374 struct player *plr);
375static void sg_load_player_cities(struct loaddata *loading,
376 struct player *plr);
377static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
378 struct city *pcity, const char *citystr,
381 struct player *plr,
382 struct city *pcity,
383 const char *citystr);
384static void sg_load_player_units(struct loaddata *loading,
385 struct player *plr);
386static bool sg_load_player_unit(struct loaddata *loading,
387 struct player *plr, struct unit *punit,
389 const char *unitstr);
391 struct player *plr);
392static void sg_load_player_attributes(struct loaddata *loading,
393 struct player *plr);
394static void sg_load_player_vision(struct loaddata *loading,
395 struct player *plr);
397 struct player *plr,
398 struct vision_site *pdcity,
399 const char *citystr);
400static void sg_save_players(struct savedata *saving);
401static void sg_save_player_main(struct savedata *saving,
402 struct player *plr);
403static void sg_save_player_cities(struct savedata *saving,
404 struct player *plr);
405static void sg_save_player_units(struct savedata *saving,
406 struct player *plr);
407static void sg_save_player_attributes(struct savedata *saving,
408 struct player *plr);
409static void sg_save_player_vision(struct savedata *saving,
410 struct player *plr);
411
412static void sg_load_researches(struct loaddata *loading);
413static void sg_save_researches(struct savedata *saving);
414
415static void sg_load_event_cache(struct loaddata *loading);
416static void sg_save_event_cache(struct savedata *saving);
417
418static void sg_load_treaties(struct loaddata *loading);
419static void sg_save_treaties(struct savedata *saving);
420
421static void sg_load_history(struct loaddata *loading);
422static void sg_save_history(struct savedata *saving);
423
424static void sg_load_mapimg(struct loaddata *loading);
425static void sg_save_mapimg(struct savedata *saving);
426
427static void sg_load_sanitycheck(struct loaddata *loading);
428static void sg_save_sanitycheck(struct savedata *saving);
429
430
431/************************************************************************/
434void savegame3_save(struct section_file *sfile, const char *save_reason,
435 bool scenario)
436{
437 fc_assert_ret(sfile != NULL);
438
439#ifdef DEBUG_TIMERS
440 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
442#endif
443
444 log_verbose("saving game in new format ...");
445 savegame3_save_real(sfile, save_reason, scenario);
446
447#ifdef DEBUG_TIMERS
449 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
451#endif /* DEBUG_TIMERS */
452}
453
454/* =======================================================================
455 * Basic load / save functions.
456 * ======================================================================= */
457
458/************************************************************************/
461void savegame3_load(struct section_file *file)
462{
463 struct loaddata *loading;
465
466 /* initialise loading */
471
472 /* Load the savegame data. */
473 /* [compat] */
475 /* [scenario] */
477 /* [savefile] */
479 /* [game] */
481 /* [random] */
483 /* [settings] */
485 /* [ruledata] */
487 /* [players] (basic data) */
489 /* [map]; needs width and height loaded by [settings] */
491 /* [research] */
493 /* [player<i>] */
495 /* [counters] */
497 /* [event_cache] */
499 /* [treaties] */
501 /* [history] */
503 /* [mapimg] */
505 /* [script] -- must come last as may reference game objects */
507 /* [post_load_compat]; needs the game loaded by [savefile] */
509
510 /* Sanity checks for the loaded game. */
512
513 /* deinitialise loading */
517
518 if (!sg_success) {
519 log_error("Failure loading savegame!");
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 if (pwl->length > MAX_LEN_WORKLIST) {
985 log_sg("worklist length %d, while MAX_LEN_WORKLIST %d.",
986 pwl->length, MAX_LEN_WORKLIST);
987 pwl->length = MAX_LEN_WORKLIST;
988 } else if (pwl->length > wlist_max_length) {
989 log_sg("worklist length %d, while player's max worklist length %d.",
990 pwl->length, wlist_max_length);
991 }
992
993 for (i = 0; i < pwl->length; i++) {
994 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
995
996 /* We lookup the production value by name. An invalid entry isn't a
997 * fatal error; we just truncate the worklist. */
998 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
999 path_str, i);
1000 pwl->entries[i] = universal_by_rule_name(kind, name);
1001 if (pwl->entries[i].kind == universals_n_invalid()) {
1002 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
1003 name);
1004 pwl->length = i;
1005 break;
1006 }
1007 }
1008
1009 /* Padding entries */
1010 for (; i < wlist_max_length; i++) {
1011 secfile_entry_ignore(file, "%s.wl_kind%d", path_str, i);
1012 secfile_entry_ignore(file, "%s.wl_value%d", path_str, i);
1013 }
1014}
1015
1016/************************************************************************/
1020static void worklist_save(struct section_file *file,
1021 const struct worklist *pwl,
1022 int max_length, const char *path, ...)
1023{
1024 char path_str[1024];
1025 int i;
1026 va_list ap;
1027
1028 /* The first part of the registry path is taken from the varargs to the
1029 * function. */
1030 va_start(ap, path);
1031 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1032 va_end(ap);
1033
1034 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1035
1036 for (i = 0; i < pwl->length; i++) {
1037 const struct universal *entry = pwl->entries + i;
1039 "%s.wl_kind%d", path_str, i);
1041 "%s.wl_value%d", path_str, i);
1042 }
1043
1045
1046 /* We want to keep savegame in tabular format, so each line has to be
1047 * of equal length. Fill table up to maximum worklist size. */
1048 for (i = pwl->length ; i < max_length; i++) {
1049 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1050 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1051 }
1052}
1053
1054/************************************************************************/
1058static void unit_ordering_calc(void)
1059{
1060 int j;
1061
1062 players_iterate(pplayer) {
1063 /* to avoid junk values for unsupported units: */
1064 unit_list_iterate(pplayer->units, punit) {
1065 punit->server.ord_city = 0;
1067 city_list_iterate(pplayer->cities, pcity) {
1068 j = 0;
1069 unit_list_iterate(pcity->units_supported, punit) {
1070 punit->server.ord_city = j++;
1074
1075 whole_map_iterate(&(wld.map), ptile) {
1076 j = 0;
1077 unit_list_iterate(ptile->units, punit) {
1078 punit->server.ord_map = j++;
1081}
1082
1083/************************************************************************/
1087static void unit_ordering_apply(void)
1088{
1089 players_iterate(pplayer) {
1090 city_list_iterate(pplayer->cities, pcity) {
1091 unit_list_sort_ord_city(pcity->units_supported);
1092 }
1095
1096 whole_map_iterate(&(wld.map), ptile) {
1097 unit_list_sort_ord_map(ptile->units);
1099}
1100
1101/************************************************************************/
1108static void sg_extras_set_dbv(struct dbv *extras, char ch,
1109 struct extra_type **idx)
1110{
1111 int i, bin;
1112 const char *pch = strchr(hex_chars, ch);
1113
1114 if (!pch || ch == '\0') {
1115 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1116 bin = 0;
1117 } else {
1118 bin = pch - hex_chars;
1119 }
1120
1121 for (i = 0; i < 4; i++) {
1122 struct extra_type *pextra = idx[i];
1123
1124 if (pextra == NULL) {
1125 continue;
1126 }
1127 if ((bin & (1 << i))
1128 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1129 dbv_set(extras, extra_index(pextra));
1130 }
1131 }
1132}
1133
1134/************************************************************************/
1142 struct extra_type **idx)
1143{
1144 int i, bin;
1145 const char *pch = strchr(hex_chars, ch);
1146
1147 if (!pch || ch == '\0') {
1148 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1149 bin = 0;
1150 } else {
1151 bin = pch - hex_chars;
1152 }
1153
1154 for (i = 0; i < 4; i++) {
1155 struct extra_type *pextra = idx[i];
1156
1157 if (pextra == NULL) {
1158 continue;
1159 }
1160 if ((bin & (1 << i))
1161 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1162 BV_SET(*extras, extra_index(pextra));
1163 }
1164 }
1165}
1166
1167/************************************************************************/
1173static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1174 const int *idx)
1175{
1176 int i, bin = 0;
1177 int max = dbv_bits(extras);
1178
1179 for (i = 0; i < 4; i++) {
1180 int extra = idx[i];
1181
1182 if (extra < 0) {
1183 break;
1184 }
1185
1186 if (extra < max
1187 && (dbv_isset(extras, extra)
1188 /* An invalid resource, a resource that can't exist at the tile's
1189 * current terrain, isn't in the bit extra vector. Save it so it
1190 * can return if the tile's terrain changes to something it can
1191 * exist on. */
1192 || extra_by_number(extra) == presource)) {
1193 bin |= (1 << i);
1194 }
1195 }
1196
1197 return hex_chars[bin];
1198}
1199
1200/************************************************************************/
1206static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1207 const int *idx)
1208{
1209 int i, bin = 0;
1210
1211 for (i = 0; i < 4; i++) {
1212 int extra = idx[i];
1213
1214 if (extra < 0) {
1215 break;
1216 }
1217
1218 if (BV_ISSET(extras, extra)
1219 /* An invalid resource, a resource that can't exist at the tile's
1220 * current terrain, isn't in the bit extra vector. Save it so it
1221 * can return if the tile's terrain changes to something it can
1222 * exist on. */
1223 || extra_by_number(extra) == presource) {
1224 bin |= (1 << i);
1225 }
1226 }
1227
1228 return hex_chars[bin];
1229}
1230
1231/************************************************************************/
1235static struct terrain *char2terrain(char ch)
1236{
1237 /* terrain_by_identifier plus fatal error */
1239 return T_UNKNOWN;
1240 }
1241 terrain_type_iterate(pterrain) {
1242 if (pterrain->identifier_load == ch) {
1243 return pterrain;
1244 }
1246
1247 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1248
1250
1252}
1253
1254/************************************************************************/
1258static char terrain2char(const struct terrain *pterrain)
1259{
1260 if (pterrain == T_UNKNOWN) {
1262 } else {
1263 return pterrain->identifier;
1264 }
1265}
1266
1267/************************************************************************/
1271 const char *path, int plrno)
1272{
1273 char path_with_name[128];
1274 const char *name;
1275 struct advance *padvance;
1276
1278 "%s_name", path);
1279
1281
1282 if (!name || name[0] == '\0') {
1283 /* Used by researching_saved */
1284 return A_UNKNOWN;
1285 }
1286 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1287 return A_FUTURE;
1288 }
1289 if (fc_strcasecmp(name, "A_NONE") == 0) {
1290 return A_NONE;
1291 }
1292 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1293 return A_UNSET;
1294 }
1295
1298 "%s: unknown technology \"%s\".", path_with_name, name);
1299
1300 return advance_number(padvance);
1301}
1302
1303/************************************************************************/
1306static void technology_save(struct section_file *file,
1307 const char *path, int plrno, Tech_type_id tech)
1308{
1309 char path_with_name[128];
1310 const char *name;
1311
1313 "%s_name", path);
1314
1315 switch (tech) {
1316 case A_UNKNOWN: /* Used by researching_saved */
1317 name = "";
1318 break;
1319 case A_NONE:
1320 name = "A_NONE";
1321 break;
1322 case A_UNSET:
1323 name = "A_UNSET";
1324 break;
1325 case A_FUTURE:
1326 name = "A_FUTURE";
1327 break;
1328 default:
1330 break;
1331 }
1332
1334}
1335
1336/* =======================================================================
1337 * Load / save savefile data.
1338 * ======================================================================= */
1339
1340/************************************************************************/
1344{
1345 int i;
1346 const char *terr_name;
1347 bool ruleset_datafile;
1349 const char *str;
1350
1351 /* Check status and return if not OK (sg_success FALSE). */
1352 sg_check_ret();
1353
1354 /* Load savefile options. */
1355 loading->secfile_options
1356 = secfile_lookup_str(loading->file, "savefile.options");
1357
1358 /* We don't need these entries, but read them anyway to avoid
1359 * warnings about unread secfile entries. */
1360 secfile_entry_ignore_by_path(loading->file, "savefile.reason");
1361 secfile_entry_ignore_by_path(loading->file, "savefile.revision");
1362
1363 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1365
1366 if (game.scenario.datafile[0] != '\0') {
1368 } else {
1370 }
1371
1374 const char *req_caps;
1375
1378 /* Failed to load correct ruleset */
1379 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1381 }
1382
1383 req_caps = secfile_lookup_str_default(loading->file, "",
1384 "scenario.ruleset_caps");
1385 strncpy(game.scenario.req_caps, req_caps,
1386 sizeof(game.scenario.req_caps) - 1);
1387 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1388
1389 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1390 /* Current ruleset lacks required capabilities. */
1391 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1392 log_normal(_("Ruleset has capabilities: %s"),
1394 /* TRANS: ... ruleset dir ... scenario name ... */
1395 log_error(_("Current ruleset %s not compatible with the scenario %s."
1396 " Trying to switch to the ruleset specified by the"
1397 " scenario."),
1399
1401 }
1402 }
1403
1406 const char *ruleset, *alt_dir;
1407
1410 "savefile.rulesetdir");
1411
1412 /* Load ruleset. */
1414 if (!strcmp("default", game.server.rulesetdir)) {
1415 /* Here 'default' really means current default.
1416 * Saving happens with real ruleset name, so savegames containing this
1417 * are special scenarios. */
1419 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1421 }
1422
1423 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1424 "savefile.ruleset_alt_dir");
1425
1426 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1427 if (alt_dir) {
1429 _("Failed to load either of rulesets '%s' or '%s' "
1430 "needed for savegame."),
1431 ruleset, alt_dir);
1432 } else {
1434 _("Failed to load ruleset '%s' needed for savegame."),
1435 ruleset);
1436 }
1437 }
1438
1440 /* TRANS: ruleset dir */
1441 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1442 }
1443 }
1444
1445 /* Remove all aifill players. Correct number of them get created later
1446 * with correct skill level etc. */
1447 (void) aifill(0);
1448
1449 /* Time to load scenario specific luadata */
1450 if (game.scenario.datafile[0] != '\0') {
1451 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1453 } else {
1454 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1455 const struct strvec **path;
1456 const char *found = NULL;
1457 char testfile[MAX_LEN_PATH];
1458 struct section_file *secfile;
1459
1460 for (path = paths; found == NULL && *path != NULL; path++) {
1461 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1462
1463 found = fileinfoname(*path, testfile);
1464 }
1465
1466 if (found == NULL) {
1467 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1468 sg_success = FALSE;
1469 return;
1470 }
1471
1472 secfile = secfile_load(found, FALSE);
1473 if (secfile == NULL) {
1474 log_error(_("Failed to load scenario luadata file %s.luadata"),
1476 sg_success = FALSE;
1477 return;
1478 }
1479
1480 game.server.luadata = secfile;
1481 }
1482 }
1483
1485 "savefile.dbid");
1486
1487 /* This is in the savegame only if the game has been started before savegame3.c time,
1488 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1490 "savefile.last_updated_as_year");
1491
1492 /* Load improvements. */
1493 loading->improvement.size
1495 "savefile.improvement_size");
1496 if (loading->improvement.size) {
1497 loading->improvement.order
1498 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1499 "savefile.improvement_vector");
1500 sg_failure_ret(loading->improvement.size != 0,
1501 "Failed to load improvement order: %s",
1502 secfile_error());
1503 }
1504
1505 /* Load technologies. */
1506 loading->technology.size
1508 "savefile.technology_size");
1509 if (loading->technology.size) {
1510 loading->technology.order
1511 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1512 "savefile.technology_vector");
1513 sg_failure_ret(loading->technology.size != 0,
1514 "Failed to load technology order: %s",
1515 secfile_error());
1516 }
1517
1518 /* Load Activities. */
1519 loading->activities.size
1521 "savefile.activities_size");
1522 if (loading->activities.size) {
1523 loading->activities.order
1524 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1525 "savefile.activities_vector");
1526 sg_failure_ret(loading->activities.size != 0,
1527 "Failed to load activity order: %s",
1528 secfile_error());
1529 }
1530
1531 /* Load traits. */
1532 loading->trait.size
1534 "savefile.trait_size");
1535 if (loading->trait.size) {
1536 loading->trait.order
1537 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1538 "savefile.trait_vector");
1539 sg_failure_ret(loading->trait.size != 0,
1540 "Failed to load trait order: %s",
1541 secfile_error());
1542 }
1543
1544 /* Load extras. */
1545 loading->extra.size
1547 "savefile.extras_size");
1548 if (loading->extra.size) {
1549 const char **modname;
1550 size_t nmod;
1551 int j;
1552
1553 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1554 "savefile.extras_vector");
1555 sg_failure_ret(loading->extra.size != 0,
1556 "Failed to load extras order: %s",
1557 secfile_error());
1559 "Number of extras defined by the ruleset (= %d) are "
1560 "lower than the number in the savefile (= %d).",
1561 game.control.num_extra_types, (int)loading->extra.size);
1562 /* make sure that the size of the array is divisible by 4 */
1563 nmod = 4 * ((loading->extra.size + 3) / 4);
1564 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1565 for (j = 0; j < loading->extra.size; j++) {
1566 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1567 }
1568 free(modname);
1569 for (; j < nmod; j++) {
1570 loading->extra.order[j] = NULL;
1571 }
1572 }
1573
1574 /* Load multipliers. */
1575 loading->multiplier.size
1577 "savefile.multipliers_size");
1578 if (loading->multiplier.size) {
1579 const char **modname;
1580 int j;
1581
1582 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1583 "savefile.multipliers_vector");
1584 sg_failure_ret(loading->multiplier.size != 0,
1585 "Failed to load multipliers order: %s",
1586 secfile_error());
1587 /* It's OK for the set of multipliers in the savefile to differ
1588 * from those in the ruleset. */
1589 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1590 sizeof(*loading->multiplier.order));
1591 for (j = 0; j < loading->multiplier.size; j++) {
1592 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1593 if (!loading->multiplier.order[j]) {
1594 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1595 "discarding", modname[j]);
1596 }
1597 }
1598 free(modname);
1599 }
1600
1601 /* Load specialists. */
1602 loading->specialist.size
1604 "savefile.specialists_size");
1605 if (loading->specialist.size) {
1606 const char **modname;
1607 size_t nmod;
1608 int j;
1609
1610 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1611 "savefile.specialists_vector");
1612 sg_failure_ret(loading->specialist.size != 0,
1613 "Failed to load specialists order: %s",
1614 secfile_error());
1616 "Number of specialists defined by the ruleset (= %d) are "
1617 "lower than the number in the savefile (= %d).",
1618 game.control.num_specialist_types, (int)loading->specialist.size);
1619 /* make sure that the size of the array is divisible by 4 */
1620 /* That's not really needed with specialists at the moment, but done this way
1621 * for consistency with other types, and to be prepared for the time it needs
1622 * to be this way. */
1623 nmod = 4 * ((loading->specialist.size + 3) / 4);
1624 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1625 for (j = 0; j < loading->specialist.size; j++) {
1626 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1627 }
1628 free(modname);
1629 for (; j < nmod; j++) {
1630 loading->specialist.order[j] = NULL;
1631 }
1632 }
1633
1634 /* Load action order. */
1635 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1636 "savefile.action_size");
1637
1638 sg_failure_ret(loading->action.size > 0,
1639 "Failed to load action order: %s",
1640 secfile_error());
1641
1642 if (loading->action.size) {
1643 const char **modname;
1644 int j;
1645
1646 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1647 "savefile.action_vector");
1648
1649 loading->action.order = fc_calloc(loading->action.size,
1650 sizeof(*loading->action.order));
1651
1652 for (j = 0; j < loading->action.size; j++) {
1654
1655 if (real_action) {
1656 loading->action.order[j] = real_action->id;
1657 } else {
1658 log_sg("Unknown action \'%s\'", modname[j]);
1659 loading->action.order[j] = ACTION_NONE;
1660 }
1661 }
1662
1663 free(modname);
1664 }
1665
1666 /* Load action decision order. */
1667 loading->act_dec.size
1669 "savefile.action_decision_size");
1670
1671 sg_failure_ret(loading->act_dec.size > 0,
1672 "Failed to load action decision order: %s",
1673 secfile_error());
1674
1675 if (loading->act_dec.size) {
1676 const char **modname;
1677 int j;
1678
1679 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1680 "savefile.action_decision_vector");
1681
1682 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1683 sizeof(*loading->act_dec.order));
1684
1685 for (j = 0; j < loading->act_dec.size; j++) {
1686 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1688 }
1689
1690 free(modname);
1691 }
1692
1693 /* Load server side agent order. */
1694 loading->ssa.size
1696 "savefile.server_side_agent_size");
1697
1698 sg_failure_ret(loading->ssa.size > 0,
1699 "Failed to load server side agent order: %s",
1700 secfile_error());
1701
1702 if (loading->ssa.size) {
1703 const char **modname;
1704 int j;
1705
1706 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1707 "savefile.server_side_agent_list");
1708
1709 loading->ssa.order = fc_calloc(loading->ssa.size,
1710 sizeof(*loading->ssa.order));
1711
1712 for (j = 0; j < loading->ssa.size; j++) {
1713 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1715 }
1716
1717 free(modname);
1718 }
1719
1720 /* Load city options order. */
1721 loading->coptions.size
1723 "savefile.city_options_size");
1724
1725 sg_failure_ret(loading->coptions.size > 0,
1726 "Failed to load city options order: %s",
1727 secfile_error());
1728
1729 if (loading->coptions.size) {
1730 const char **modname;
1731 int j;
1732
1733 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1734 "savefile.city_options_vector");
1735
1736 loading->coptions.order = fc_calloc(loading->coptions.size,
1737 sizeof(*loading->coptions.order));
1738
1739 for (j = 0; j < loading->coptions.size; j++) {
1740 loading->coptions.order[j] = city_options_by_name(modname[j],
1742 }
1743
1744 free(modname);
1745 }
1746
1747 /* Terrain identifiers */
1749 pterr->identifier_load = '\0';
1751
1752 i = 0;
1754 "savefile.terrident%d.name", i)) != NULL) {
1756
1757 if (pterr != NULL) {
1758 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1759 "savefile.terrident%d.identifier", i);
1760
1761 pterr->identifier_load = *iptr;
1762 } else {
1763 log_error("Identifier for unknown terrain type %s.", terr_name);
1764 }
1765 i++;
1766 }
1767
1770 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1771 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1772 "%s and %s share a saved identifier",
1774 }
1777}
1778
1779/************************************************************************/
1783{
1784 int i;
1785
1786 /* Check status and return if not OK (sg_success FALSE). */
1787 sg_check_ret();
1788
1789 /* Save savefile options. */
1791
1792 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1793
1794 /* Save reason of the savefile generation. */
1795 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1796
1797 /* Save as accurate freeciv revision information as possible */
1798 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1799
1800 /* Freeciv version used in the very first launch of this game -
1801 * or even saving in pregame. */
1803 "savefile.orig_version");
1804
1805 /* Save rulesetdir at this point as this ruleset is required by this
1806 * savefile. */
1807 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1808
1809 if (game.control.version[0] != '\0') {
1810 /* Current ruleset has version information, save it.
1811 * This is never loaded, but exist in savegame file only for debugging purposes. */
1812 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1813 }
1814
1815 if (game.control.alt_dir[0] != '\0') {
1816 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1817 }
1818
1820 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1821 }
1822
1823 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1824
1825 /* Save improvement order in savegame, so we are not dependent on ruleset
1826 * order. If the game isn't started improvements aren't loaded so we can
1827 * not save the order. */
1829 "savefile.improvement_size");
1830 if (improvement_count() > 0) {
1831 const char *buf[improvement_count()];
1832
1833 improvement_iterate(pimprove) {
1834 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1836
1838 "savefile.improvement_vector");
1839 }
1840
1841 /* Save technology order in savegame, so we are not dependent on ruleset
1842 * order. If the game isn't started advances aren't loaded so we can not
1843 * save the order. */
1845 "savefile.technology_size");
1846 if (game.control.num_tech_types > 0) {
1847 const char *buf[game.control.num_tech_types];
1848
1849 buf[A_NONE] = "A_NONE";
1850 advance_iterate(a) {
1854 "savefile.technology_vector");
1855 }
1856
1857 /* Save activities order in the savegame. */
1859 "savefile.activities_size");
1860 if (ACTIVITY_LAST > 0) {
1861 const char **modname;
1862 int j;
1863
1864 i = 0;
1865
1867
1868 for (j = 0; j < ACTIVITY_LAST; j++) {
1870 }
1871
1874 "savefile.activities_vector");
1875 free(modname);
1876 }
1877
1878 /* Save specialists order in the savegame. */
1880 "savefile.specialists_size");
1881 {
1882 const char **modname;
1883
1884 i = 0;
1886
1890
1892 "savefile.specialists_vector");
1893
1894 free(modname);
1895 }
1896
1897 /* Save trait order in savegame. */
1899 "savefile.trait_size");
1900 {
1901 const char **modname;
1902 enum trait tr;
1903 int j;
1904
1905 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1906
1907 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1908 modname[j] = trait_name(tr);
1909 }
1910
1912 "savefile.trait_vector");
1913 free(modname);
1914 }
1915
1916 /* Save extras order in the savegame. */
1918 "savefile.extras_size");
1919 if (game.control.num_extra_types > 0) {
1920 const char **modname;
1921
1922 i = 0;
1924
1925 extra_type_iterate(pextra) {
1926 modname[i++] = extra_rule_name(pextra);
1928
1931 "savefile.extras_vector");
1932 free(modname);
1933 }
1934
1935 /* Save multipliers order in the savegame. */
1937 "savefile.multipliers_size");
1938 if (multiplier_count() > 0) {
1939 const char **modname;
1940
1942
1943 multipliers_iterate(pmul) {
1946
1949 "savefile.multipliers_vector");
1950 free(modname);
1951 }
1952
1953 /* Save city_option order in the savegame. */
1955 "savefile.city_options_size");
1956 if (CITYO_LAST > 0) {
1957 const char **modname;
1958 int j;
1959
1960 i = 0;
1961 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1962
1963 for (j = 0; j < CITYO_LAST; j++) {
1964 modname[i++] = city_options_name(j);
1965 }
1966
1968 CITYO_LAST,
1969 "savefile.city_options_vector");
1970 free(modname);
1971 }
1972
1973 /* Save action order in the savegame. */
1975 "savefile.action_size");
1976 if (NUM_ACTIONS > 0) {
1977 const char **modname;
1978 int j;
1979
1980 i = 0;
1981 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1982
1983 for (j = 0; j < NUM_ACTIONS; j++) {
1985 }
1986
1989 "savefile.action_vector");
1990 free(modname);
1991 }
1992
1993 /* Save action decision order in the savegame. */
1995 "savefile.action_decision_size");
1996 if (ACT_DEC_COUNT > 0) {
1997 const char **modname;
1998 int j;
1999
2000 i = 0;
2002
2003 for (j = 0; j < ACT_DEC_COUNT; j++) {
2005 }
2006
2009 "savefile.action_decision_vector");
2010 free(modname);
2011 }
2012
2013 /* Save server side agent order in the savegame. */
2015 "savefile.server_side_agent_size");
2016 if (SSA_COUNT > 0) {
2017 const char **modname;
2018 int j;
2019
2020 i = 0;
2021 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2022
2023 for (j = 0; j < SSA_COUNT; j++) {
2025 }
2026
2028 SSA_COUNT,
2029 "savefile.server_side_agent_list");
2030 free(modname);
2031 }
2032
2033 /* Save terrain character mapping in the savegame. */
2034 i = 0;
2036 char buf[2];
2037
2038 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2040 buf[1] = '\0';
2041 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2043}
2044
2045/************************************************************************/
2049 const char *option)
2050{
2051 /* Check status and return if not OK (sg_success FALSE). */
2052 sg_check_ret();
2053
2054 if (option == NULL) {
2055 /* no additional option */
2056 return;
2057 }
2058
2059 sz_strlcat(saving->secfile_options, option);
2060 secfile_replace_str(saving->file, saving->secfile_options,
2061 "savefile.options");
2062}
2063
2064/* =======================================================================
2065 * Load / save game status.
2066 * ======================================================================= */
2067
2068/************************************************************************/
2072{
2073 int i;
2074 const char *name;
2075
2076 /* Check status and return if not OK (sg_success FALSE). */
2077 sg_check_ret();
2078
2079 for (i = 0;
2081 "ruledata.government%d.name", i));
2082 i++) {
2084
2085 if (gov != NULL) {
2087 "ruledata.government%d.changes", i);
2088 }
2089 }
2090}
2091
2092/************************************************************************/
2095static void sg_load_game(struct loaddata *loading)
2096{
2097 const char *str;
2098 int i;
2099
2100 /* Check status and return if not OK (sg_success FALSE). */
2101 sg_check_ret();
2102
2103 /* Load server state. */
2104 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2105 "game.server_state");
2106 loading->server_state = server_states_by_name(str, strcmp);
2107 if (!server_states_is_valid(loading->server_state)) {
2108 /* Don't take any risk! */
2109 loading->server_state = S_S_INITIAL;
2110 }
2111
2113 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2114
2117 "game.meta_patches");
2119
2121 /* Do not overwrite this if the user requested a specific metaserver
2122 * from the command line (option --Metaserver). */
2126 "game.meta_server"));
2127 }
2128
2129 if ('\0' == srvarg.serverid[0]) {
2130 /* Do not overwrite this if the user requested a specific metaserver
2131 * from the command line (option --serverid). */
2134 "game.serverid"));
2135 }
2136 sz_strlcpy(server.game_identifier,
2137 secfile_lookup_str_default(loading->file, "", "game.id"));
2138 /* We are not checking game_identifier legality just yet.
2139 * That's done when we are sure that rand seed has been initialized,
2140 * so that we can generate new game_identifier, if needed.
2141 * See sq_load_sanitycheck(). */
2142
2144 "game.phase_mode");
2145 if (str != NULL) {
2148 log_error("Illegal phase mode \"%s\"", str);
2150 }
2151 } else {
2152 log_error("Phase mode missing");
2153 }
2154
2156 "game.phase_mode_stored");
2157 if (str != NULL) {
2160 log_error("Illegal stored phase mode \"%s\"", str);
2162 }
2163 } else {
2164 log_error("Stored phase mode missing");
2165 }
2168 "game.phase");
2172 "game.scoreturn");
2173
2176 "game.timeoutint");
2179 "game.timeoutintinc");
2182 "game.timeoutinc");
2185 "game.timeoutincmult");
2188 "game.timeoutcounter");
2189
2190 game.info.turn
2191 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2193 "game.year"), "%s", secfile_error());
2195 "game.world_peace_start"), "%s", secfile_error());
2197 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2198
2200 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2202 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2204 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2205
2207 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2209 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2211 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2212
2213 /* Savegame may have stored random_seed for documentation purposes only,
2214 * but we want to keep it for resaving. */
2215 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2216
2217 /* Global advances. */
2219 "game.global_advances");
2220 if (str != NULL) {
2221 sg_failure_ret(strlen(str) == loading->technology.size,
2222 "Invalid length of 'game.global_advances' ("
2223 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2224 strlen(str), loading->technology.size);
2225 for (i = 0; i < loading->technology.size; i++) {
2226 sg_failure_ret(str[i] == '1' || str[i] == '0',
2227 "Undefined value '%c' within 'game.global_advances'.",
2228 str[i]);
2229 if (str[i] == '1') {
2230 struct advance *padvance
2231 = advance_by_rule_name(loading->technology.order[i]);
2232
2233 if (padvance != NULL) {
2235 }
2236 }
2237 }
2238 }
2239
2241 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2242
2244 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2245}
2246
2247/************************************************************************/
2251{
2252 int set_count = 0;
2253
2255 char path[256];
2256
2257 fc_snprintf(path, sizeof(path),
2258 "ruledata.government%d", set_count++);
2259
2261 "%s.name", path);
2262 secfile_insert_int(saving->file, pgov->changed_to_times,
2263 "%s.changes", path);
2265}
2266
2267/************************************************************************/
2270static void sg_save_game(struct savedata *saving)
2271{
2273 char global_advances[game.control.num_tech_types + 1];
2274 int i;
2275
2276 /* Check status and return if not OK (sg_success FALSE). */
2277 sg_check_ret();
2278
2279 /* Game state: once the game is no longer a new game (ie, has been
2280 * started the first time), it should always be considered a running
2281 * game for savegame purposes. */
2282 if (saving->scenario && !game.scenario.players) {
2284 } else {
2286 }
2288 "game.server_state");
2289
2290 if (game.server.phase_timer != NULL) {
2294 "game.phase_seconds");
2295 }
2296
2298 "game.meta_patches");
2299 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2300
2301 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2302 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2303
2306 "game.phase_mode");
2309 "game.phase_mode_stored");
2311 "game.phase");
2313 "game.scoreturn");
2314
2316 "game.timeoutint");
2318 "game.timeoutintinc");
2320 "game.timeoutinc");
2322 "game.timeoutincmult");
2324 "game.timeoutcounter");
2325
2326 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2327 secfile_insert_int(saving->file, game.info.year, "game.year");
2328 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2330 "game.year_0_hack");
2331
2333 "game.globalwarming");
2335 "game.heating");
2337 "game.warminglevel");
2338
2340 "game.nuclearwinter");
2342 "game.cooling");
2344 "game.coolinglevel");
2345 /* For debugging purposes only.
2346 * Do not save it if it's 0 (not known);
2347 * this confuses people reading this 'document' less than
2348 * saving 0. */
2349 if (game.server.seed != 0) {
2351 "game.random_seed");
2352 }
2353
2354 /* Global advances. */
2355 for (i = 0; i < game.control.num_tech_types; i++) {
2356 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2357 }
2358 global_advances[i] = '\0';
2359 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2360
2361 if (!game_was_started()) {
2362 saving->save_players = FALSE;
2363 } else {
2364 if (saving->scenario) {
2365 saving->save_players = game.scenario.players;
2366 } else {
2367 saving->save_players = TRUE;
2368 }
2369#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2371 "game.last_turn_change_time");
2372#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2374 "game.last_turn_change_time");
2375#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2376 }
2377 secfile_insert_bool(saving->file, saving->save_players,
2378 "game.save_players");
2379
2380 if (srv_state != S_S_INITIAL) {
2381 const char *ainames[ai_type_get_count()];
2382
2383 i = 0;
2384 ai_type_iterate(ait) {
2385 ainames[i] = ait->name;
2386 i++;
2388
2390 "game.ai_types");
2391 }
2392}
2393
2394/* =======================================================================
2395 * Load / save random status.
2396 * ======================================================================= */
2397
2398/************************************************************************/
2401static void sg_load_random(struct loaddata *loading)
2402{
2403 /* Check status and return if not OK (sg_success FALSE). */
2404 sg_check_ret();
2405
2406 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2407 const char *str;
2408 int i;
2409
2411 "random.index_J"), "%s", secfile_error());
2413 "random.index_K"), "%s", secfile_error());
2415 "random.index_X"), "%s", secfile_error());
2416
2417 for (i = 0; i < 8; i++) {
2418 str = secfile_lookup_str(loading->file, "random.table%d",i);
2419 sg_failure_ret(NULL != str, "%s", secfile_error());
2420 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2421 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2422 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2423 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2424 }
2425 loading->rstate.is_init = TRUE;
2426 fc_rand_set_state(loading->rstate);
2427 } else {
2428 /* No random values - mark the setting. */
2429 secfile_entry_ignore_by_path(loading->file, "random.saved");
2430
2431 /* We're loading a game without a seed (which is okay, if it's a scenario).
2432 * We need to generate the game seed now because it will be needed later
2433 * during the load. */
2435 loading->rstate = fc_rand_state();
2436 }
2437}
2438
2439/************************************************************************/
2442static void sg_save_random(struct savedata *saving)
2443{
2444 /* Check status and return if not OK (sg_success FALSE). */
2445 sg_check_ret();
2446
2447 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2448 int i;
2449 RANDOM_STATE rstate = fc_rand_state();
2450
2451 secfile_insert_bool(saving->file, TRUE, "random.saved");
2452 fc_assert(rstate.is_init);
2453
2454 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2455 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2456 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2457
2458 for (i = 0; i < 8; i++) {
2459 char vec[100];
2460
2461 fc_snprintf(vec, sizeof(vec),
2462 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2463 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2464 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2465 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2466 secfile_insert_str(saving->file, vec, "random.table%d", i);
2467 }
2468 } else {
2469 secfile_insert_bool(saving->file, FALSE, "random.saved");
2470 }
2471}
2472
2473/* =======================================================================
2474 * Load / save lua script data.
2475 * ======================================================================= */
2476
2477/************************************************************************/
2480static void sg_load_script(struct loaddata *loading)
2481{
2482 /* Check status and return if not OK (sg_success FALSE). */
2483 sg_check_ret();
2484
2486}
2487
2488/************************************************************************/
2491static void sg_save_script(struct savedata *saving)
2492{
2493 /* Check status and return if not OK (sg_success FALSE). */
2494 sg_check_ret();
2495
2497}
2498
2499/* =======================================================================
2500 * Load / save scenario data.
2501 * ======================================================================= */
2502
2503/************************************************************************/
2507{
2508 const char *buf;
2509 int game_version;
2510
2511 /* Check status and return if not OK (sg_success FALSE). */
2512 sg_check_ret();
2513
2514 /* Load version. */
2516 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2517 /* We require at least version 2.90.99 - and at that time we saved version
2518 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2519 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2520 "version 2.90.99 required.");
2521
2522 loading->full_version = game_version;
2523
2524 game.scenario.datafile[0] = '\0';
2525
2527 "scenario.is_scenario"), "%s", secfile_error());
2528 if (!game.scenario.is_scenario) {
2529 return;
2530 }
2531
2532 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2533 if (buf[0] != '\0') {
2535 }
2536
2538 "scenario.authors");
2539 if (buf[0] != '\0') {
2541 } else {
2542 game.scenario.authors[0] = '\0';
2543 }
2544
2546 "scenario.description");
2547 if (buf[0] != '\0') {
2549 } else {
2550 game.scenario_desc.description[0] = '\0';
2551 }
2553 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2555 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2558 "scenario.startpos_nations");
2561 "scenario.prevent_new_cities");
2564 "scenario.lake_flooding");
2567 "scenario.handmade");
2570 "scenario.allow_ai_type_fallback");
2571
2574 "scenario.ruleset_locked");
2575
2577 "scenario.datafile");
2578 if (buf[0] != '\0') {
2580 }
2581
2582 sg_failure_ret(loading->server_state == S_S_INITIAL
2583 || (loading->server_state == S_S_RUNNING
2584 && game.scenario.players),
2585 "Invalid scenario definition (server state '%s' and "
2586 "players are %s).",
2587 server_states_name(loading->server_state),
2588 game.scenario.players ? "saved" : "not saved");
2589}
2590
2591/************************************************************************/
2595{
2596 struct entry *mod_entry;
2597 int game_version;
2598
2599 /* Check status and return if not OK (sg_success FALSE). */
2600 sg_check_ret();
2601
2602 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2603#ifdef EMERGENCY_VERSION
2605#endif /* EMERGENCY_VERSION */
2606 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2607
2608 if (!saving->scenario || !game.scenario.is_scenario) {
2609 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2610 return;
2611 }
2612
2613 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2614
2615 /* Name is mandatory to the level that is saved even if empty. */
2616 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2618
2619 /* Authors list is saved only if it exist */
2620 if (game.scenario.authors[0] != '\0') {
2622 "scenario.authors");
2624 }
2625
2626 /* Description is saved only if it exist */
2627 if (game.scenario_desc.description[0] != '\0') {
2629 "scenario.description");
2631 }
2632
2633 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2634 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2636 "scenario.startpos_nations");
2639 "scenario.prevent_new_cities");
2640 }
2642 "scenario.lake_flooding");
2643 if (game.scenario.handmade) {
2645 "scenario.handmade");
2646 }
2649 "scenario.allow_ai_type_fallback");
2650 }
2651
2652 if (game.scenario.datafile[0] != '\0') {
2654 "scenario.datafile");
2655 }
2657 "scenario.ruleset_locked");
2658 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2660 "scenario.ruleset_caps");
2661 }
2662}
2663
2664/* =======================================================================
2665 * Load / save game settings.
2666 * ======================================================================= */
2667
2668/************************************************************************/
2672{
2673 /* Check status and return if not OK (sg_success FALSE). */
2674 sg_check_ret();
2675
2676 settings_game_load(loading->file, "settings");
2677
2678 /* Save current status of fogofwar. */
2680
2681 /* Add all compatibility settings here. */
2682}
2683
2684/************************************************************************/
2688{
2690
2691 /* Check status and return if not OK (sg_success FALSE). */
2692 sg_check_ret();
2693
2694 if (saving->scenario) {
2695 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2696 }
2697
2698 settings_game_save(saving->file, "settings");
2699 /* Restore real map generator. */
2701
2702 /* Add all compatibility settings here. */
2703}
2704
2705
2706/************************************************************************/
2710{
2711 struct city *pcity;
2712 int i, j;
2713 size_t length, length2;
2714 int *city_count;
2716 "savefile.city_counters_order_size");
2717
2718 if (0==length) {
2719
2720 return;
2721 }
2722
2723 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2724
2725 sg_failure_ret(loading->counter.order != 0,
2726 "Failed to load counter's ruleset order: %s",
2727 secfile_error());
2728 sg_failure_ret(loading->counter.size = length,
2729 "Counter vector in savegame have bad size: %s",
2730 secfile_error());
2731
2732 int corder[length];
2733
2734 for (i = 0; i < length; i++) {
2735
2736 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2738 }
2739
2740 i = 0;
2741 while (NULL != (city_count =
2743 "counters.c%d", i))) {
2744
2745 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);
2746
2748
2749 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2750
2751 for (j = 0; j < length; j++) {
2752
2753 pcity->counter_values[corder[j]] = city_count[j+1];
2754 }
2755 i++;
2756 }
2757}
2758
2759/************************************************************************/
2763{
2764 /* Check status and return if not OK (sg_success FALSE). */
2765 sg_check_ret();
2766
2767 const char **countnames;
2768 int *countvalues;
2769 int i, j, count;
2770
2772
2773 secfile_insert_int(saving->file, count,
2774 "savefile.city_counters_order_size");
2775
2776 if (0 == count) {
2777
2778 return;
2779 }
2780
2781 countnames = fc_calloc(count, sizeof(*countnames));
2782 for (j = 0; j < count; j++) {
2784 }
2785
2787 "savefile.city_counters_order_vector");
2788
2790
2791 // Saving city's counters
2792
2793 j = 0;
2794 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2795
2797
2798 city_list_iterate(_pplayer->cities, pcity) {
2799
2800 countvalues[0] = pcity->id;
2801 for (i = 0; i < count; ++i) {
2802
2803 countvalues[i+1] = pcity->counter_values[i];
2804 }
2805
2806 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2807 ++j;
2810
2812}
2813
2814/* =======================================================================
2815 * Load / save the main map.
2816 * ======================================================================= */
2817
2818/************************************************************************/
2821static void sg_load_map(struct loaddata *loading)
2822{
2823 /* Check status and return if not OK (sg_success FALSE). */
2824 sg_check_ret();
2825
2826 /* This defaults to TRUE even if map has not been generated.
2827 * We rely on that
2828 * 1) scenario maps have it explicitly right.
2829 * 2) when map is actually generated, it re-initialize this to FALSE. */
2831 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2832
2834 = secfile_lookup_bool_default(loading->file, TRUE, "map.altitude");
2835
2837 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2838
2840
2841 /* Savegame may have stored random_seed for documentation purposes only,
2842 * but we want to keep it for resaving. */
2844 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2845
2846 if (S_S_INITIAL == loading->server_state
2848 /* Generator MAPGEN_SCENARIO is used;
2849 * this map was done with the map editor. */
2850
2851 /* Load tiles. */
2855
2856 /* Nothing more needed for a scenario. */
2857 secfile_entry_ignore(loading->file, "game.save_known");
2858
2859 return;
2860 }
2861
2862 if (S_S_INITIAL == loading->server_state) {
2863 /* Nothing more to do if it is not a scenario but in initial state. */
2864 return;
2865 }
2866
2868 if (wld.map.altitude_info) {
2870 }
2876}
2877
2878/************************************************************************/
2881static void sg_save_map(struct savedata *saving)
2882{
2883 /* Check status and return if not OK (sg_success FALSE). */
2884 sg_check_ret();
2885
2886 if (map_is_empty()) {
2887 /* No map. */
2888 return;
2889 }
2890
2891 if (saving->scenario) {
2893 "map.have_huts");
2895 "map.have_resources");
2896 } else {
2897 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2898 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2899 }
2900
2901 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2902
2903 /* For debugging purposes only.
2904 * Do not save it if it's 0 (not known);
2905 * this confuses people reading this 'document' less than
2906 * saving 0. */
2907 if (wld.map.server.seed != 0) {
2909 "map.random_seed");
2910 }
2911
2913 if (wld.map.altitude_info) {
2915 }
2921}
2922
2923/************************************************************************/
2927{
2928 /* Check status and return if not OK (sg_success FALSE). */
2929 sg_check_ret();
2930
2931 /* Initialize the map for the current topology. 'map.xsize' and
2932 * 'map.ysize' must be set. */
2934
2935 /* Allocate map. */
2937
2938 /* get the terrain type */
2939 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2940 "map.t%04d");
2942
2943 /* Check for special tile sprites. */
2944 whole_map_iterate(&(wld.map), ptile) {
2945 const char *spec_sprite;
2946 const char *label;
2947 int nat_x, nat_y;
2948
2950 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2951 nat_x, nat_y);
2952 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2953 nat_x, nat_y);
2954 if (NULL != ptile->spec_sprite) {
2955 ptile->spec_sprite = fc_strdup(spec_sprite);
2956 }
2957 if (label != NULL) {
2958 tile_set_label(ptile, label);
2959 }
2961}
2962
2963/************************************************************************/
2967{
2968 /* Check status and return if not OK (sg_success FALSE). */
2969 sg_check_ret();
2970
2971 /* Save the terrain type. */
2972 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2973 "map.t%04d");
2974
2975 /* Save special tile sprites. */
2976 whole_map_iterate(&(wld.map), ptile) {
2977 int nat_x, nat_y;
2978
2980 if (ptile->spec_sprite) {
2981 secfile_insert_str(saving->file, ptile->spec_sprite,
2982 "map.spec_sprite_%d_%d", nat_x, nat_y);
2983 }
2984 if (ptile->label != NULL) {
2985 secfile_insert_str(saving->file, ptile->label,
2986 "map.label_%d_%d", nat_x, nat_y);
2987 }
2989}
2990
2991/************************************************************************/
2995{
2996 int y;
2997
2998 /* Check status and return if not OK (sg_success FALSE). */
2999 sg_check_ret();
3000
3001 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3002 const char *buffer = secfile_lookup_str(loading->file,
3003 "map.alt%04d", y);
3004 const char *ptr = buffer;
3005 int x;
3006
3007 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3008
3009 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3010 char token[TOKEN_SIZE];
3011 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3012 int number;
3013
3014 scanin(&ptr, ",", token, sizeof(token));
3015 sg_failure_ret(token[0] != '\0',
3016 "Map size not correct (map.alt%d).", y);
3017 sg_failure_ret(str_to_int(token, &number),
3018 "Got map alt %s in (%d, %d).", token, x, y);
3019 ptile->altitude = number;
3020 }
3021 }
3022}
3023
3024/************************************************************************/
3028{
3029 int y;
3030
3031 /* Check status and return if not OK (sg_success FALSE). */
3032 sg_check_ret();
3033
3034 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3036 int x;
3037
3038 line[0] = '\0';
3039 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3040 char token[TOKEN_SIZE];
3041 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3042
3043 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3044
3045 strcat(line, token);
3046 if (x + 1 < MAP_NATIVE_WIDTH) {
3047 strcat(line, ",");
3048 }
3049 }
3050
3051 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3052 }
3053}
3054
3055/************************************************************************/
3059{
3060 /* Check status and return if not OK (sg_success FALSE). */
3061 sg_check_ret();
3062
3063 /* Load extras. */
3064 halfbyte_iterate_extras(j, loading->extra.size) {
3065 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3066 loading->extra.order + 4 * j),
3067 loading->file, "map.e%02d_%04d", j);
3069
3070 if (S_S_INITIAL != loading->server_state
3073 whole_map_iterate(&(wld.map), ptile) {
3075 if (tile_has_extra(ptile, pres)) {
3076 tile_set_resource(ptile, pres);
3077
3078 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3079 BV_CLR(ptile->extras, extra_index(pres));
3080 }
3081 }
3084 }
3085}
3086
3087/************************************************************************/
3091{
3092 /* Check status and return if not OK (sg_success FALSE). */
3093 sg_check_ret();
3094
3095 /* Save extras. */
3097 int mod[4];
3098 int l;
3099
3100 for (l = 0; l < 4; l++) {
3101 if (4 * j + 1 > game.control.num_extra_types) {
3102 mod[l] = -1;
3103 } else {
3104 mod[l] = 4 * j + l;
3105 }
3106 }
3107 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3108 saving->file, "map.e%02d_%04d", j);
3110}
3111
3112/************************************************************************/
3117{
3118 struct nation_type *pnation;
3119 struct startpos *psp;
3120 struct tile *ptile;
3121 const char SEPARATOR = '#';
3122 const char *nation_names;
3123 int nat_x, nat_y;
3124 bool exclude;
3125 int i, startpos_count;
3126
3127 /* Check status and return if not OK (sg_success FALSE). */
3128 sg_check_ret();
3129
3131 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3132
3133 if (0 == startpos_count) {
3134 /* Nothing to do. */
3135 return;
3136 }
3137
3138 for (i = 0; i < startpos_count; i++) {
3139 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3140 || !secfile_lookup_int(loading->file, &nat_y,
3141 "map.startpos%d.y", i)) {
3142 log_sg("Warning: Undefined coordinates for startpos %d", i);
3143 continue;
3144 }
3145
3146 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3147 if (NULL == ptile) {
3148 log_error("Start position native coordinates (%d, %d) do not exist "
3149 "in this map. Skipping...", nat_x, nat_y);
3150 continue;
3151 }
3152
3153 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3154 "map.startpos%d.exclude", i);
3155
3156 psp = map_startpos_new(ptile);
3157
3159 "map.startpos%d.nations", i);
3160 if (NULL != nation_names && '\0' != nation_names[0]) {
3161 const size_t size = strlen(nation_names) + 1;
3162 char buf[size], *start, *end;
3163
3165 for (start = buf - 1; NULL != start; start = end) {
3166 start++;
3167 if ((end = strchr(start, SEPARATOR))) {
3168 *end = '\0';
3169 }
3170
3171 pnation = nation_by_rule_name(start);
3172 if (NO_NATION_SELECTED != pnation) {
3173 if (exclude) {
3174 startpos_disallow(psp, pnation);
3175 } else {
3176 startpos_allow(psp, pnation);
3177 }
3178 } else {
3179 log_verbose("Missing nation \"%s\".", start);
3180 }
3181 }
3182 }
3183 }
3184
3185 if (0 < map_startpos_count()
3186 && loading->server_state == S_S_INITIAL
3188 log_verbose("Number of starts (%d) are lower than rules.max_players "
3189 "(%d), lowering rules.max_players.",
3192 }
3193
3194 /* Re-initialize nation availability in light of start positions.
3195 * This has to be after loading [scenario] and [map].startpos and
3196 * before we seek nations for players. */
3198}
3199
3200/************************************************************************/
3204{
3205 struct tile *ptile;
3206 const char SEPARATOR = '#';
3207 int i = 0;
3208
3209 /* Check status and return if not OK (sg_success FALSE). */
3210 sg_check_ret();
3211
3213 return;
3214 }
3215
3217 "map.startpos_count");
3218
3220 int nat_x, nat_y;
3221
3222 ptile = startpos_tile(psp);
3223
3225 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3226 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3227
3229 "map.startpos%d.exclude", i);
3230 if (startpos_allows_all(psp)) {
3231 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3232 } else {
3233 const struct nation_hash *nations = startpos_raw_nations(psp);
3235
3236 nation_names[0] = '\0';
3237 nation_hash_iterate(nations, pnation) {
3238 if ('\0' == nation_names[0]) {
3240 sizeof(nation_names));
3241 } else {
3243 "%c%s", SEPARATOR, nation_rule_name(pnation));
3244 }
3247 "map.startpos%d.nations", i);
3248 }
3249 i++;
3251
3253}
3254
3255/************************************************************************/
3259{
3260 int y;
3261 struct tile *claimer = NULL;
3262 struct extra_type *placing = NULL;
3263
3264 /* Check status and return if not OK (sg_success FALSE). */
3265 sg_check_ret();
3266
3267 if (game.info.is_new_game) {
3268 /* No owner/source information for a new game / scenario. */
3269 return;
3270 }
3271
3272 /* Owner, ownership source, and infra turns are stored as plain numbers */
3273 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3274 const char *buffer1 = secfile_lookup_str(loading->file,
3275 "map.owner%04d", y);
3276 const char *buffer2 = secfile_lookup_str(loading->file,
3277 "map.source%04d", y);
3278 const char *buffer3 = secfile_lookup_str(loading->file,
3279 "map.eowner%04d", y);
3281 NULL,
3282 "map.placing%04d", y);
3284 NULL,
3285 "map.infra_turns%04d", y);
3286 const char *ptr1 = buffer1;
3287 const char *ptr2 = buffer2;
3288 const char *ptr3 = buffer3;
3289 const char *ptr_placing = buffer_placing;
3290 const char *ptr_turns = buffer_turns;
3291 int x;
3292
3296
3297 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3298 char token1[TOKEN_SIZE];
3299 char token2[TOKEN_SIZE];
3300 char token3[TOKEN_SIZE];
3302 char token_turns[TOKEN_SIZE];
3303 struct player *owner = NULL;
3304 struct player *eowner = NULL;
3305 int turns;
3306 int number;
3307 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3308
3309 scanin(&ptr1, ",", token1, sizeof(token1));
3310 sg_failure_ret(token1[0] != '\0',
3311 "Map size not correct (map.owner%d).", y);
3312 if (strcmp(token1, "-") == 0) {
3313 owner = NULL;
3314 } else {
3316 "Got map owner %s in (%d, %d).", token1, x, y);
3317 owner = player_by_number(number);
3318 }
3319
3320 scanin(&ptr2, ",", token2, sizeof(token2));
3321 sg_failure_ret(token2[0] != '\0',
3322 "Map size not correct (map.source%d).", y);
3323 if (strcmp(token2, "-") == 0) {
3324 claimer = NULL;
3325 } else {
3327 "Got map source %s in (%d, %d).", token2, x, y);
3328 claimer = index_to_tile(&(wld.map), number);
3329 }
3330
3331 scanin(&ptr3, ",", token3, sizeof(token3));
3332 sg_failure_ret(token3[0] != '\0',
3333 "Map size not correct (map.eowner%d).", y);
3334 if (strcmp(token3, "-") == 0) {
3335 eowner = NULL;
3336 } else {
3338 "Got base owner %s in (%d, %d).", token3, x, y);
3339 eowner = player_by_number(number);
3340 }
3341
3342 if (ptr_placing != NULL) {
3344 sg_failure_ret(token_placing[0] != '\0',
3345 "Map size not correct (map.placing%d).", y);
3346 if (strcmp(token_placing, "-") == 0) {
3347 placing = NULL;
3348 } else {
3350 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3351 placing = extra_by_number(number);
3352 }
3353 } else {
3354 placing = NULL;
3355 }
3356
3357 if (ptr_turns != NULL) {
3358 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3359 sg_failure_ret(token_turns[0] != '\0',
3360 "Map size not correct (map.infra_turns%d).", y);
3362 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3363 turns = number;
3364 } else {
3365 turns = 1;
3366 }
3367
3369 tile_claim_bases(ptile, eowner);
3370 ptile->placing = placing;
3371 ptile->infra_turns = turns;
3372 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3373 }
3374 }
3375}
3376
3377/************************************************************************/
3381{
3382 int y;
3383
3384 /* Check status and return if not OK (sg_success FALSE). */
3385 sg_check_ret();
3386
3387 if (saving->scenario && !saving->save_players) {
3388 /* Nothing to do for a scenario without saved players. */
3389 return;
3390 }
3391
3392 /* Store owner and ownership source as plain numbers. */
3393 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3395 int x;
3396
3397 line[0] = '\0';
3398 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3399 char token[TOKEN_SIZE];
3400 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3401
3402 if (!saving->save_players || tile_owner(ptile) == NULL) {
3403 strcpy(token, "-");
3404 } else {
3405 fc_snprintf(token, sizeof(token), "%d",
3406 player_number(tile_owner(ptile)));
3407 }
3408 strcat(line, token);
3409 if (x + 1 < MAP_NATIVE_WIDTH) {
3410 strcat(line, ",");
3411 }
3412 }
3413
3414 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3415 }
3416
3417 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3419 int x;
3420
3421 line[0] = '\0';
3422 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3423 char token[TOKEN_SIZE];
3424 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3425
3426 if (ptile->claimer == NULL) {
3427 strcpy(token, "-");
3428 } else {
3429 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3430 }
3431 strcat(line, token);
3432 if (x + 1 < MAP_NATIVE_WIDTH) {
3433 strcat(line, ",");
3434 }
3435 }
3436
3437 secfile_insert_str(saving->file, line, "map.source%04d", y);
3438 }
3439
3440 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3442 int x;
3443
3444 line[0] = '\0';
3445 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3446 char token[TOKEN_SIZE];
3447 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3448
3449 if (!saving->save_players || extra_owner(ptile) == NULL) {
3450 strcpy(token, "-");
3451 } else {
3452 fc_snprintf(token, sizeof(token), "%d",
3453 player_number(extra_owner(ptile)));
3454 }
3455 strcat(line, token);
3456 if (x + 1 < MAP_NATIVE_WIDTH) {
3457 strcat(line, ",");
3458 }
3459 }
3460
3461 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3462 }
3463
3464 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3466 int x;
3467
3468 line[0] = '\0';
3469 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3470 char token[TOKEN_SIZE];
3471 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3472
3473 if (ptile->placing == NULL) {
3474 strcpy(token, "-");
3475 } else {
3476 fc_snprintf(token, sizeof(token), "%d",
3477 extra_number(ptile->placing));
3478 }
3479 strcat(line, token);
3480 if (x + 1 < MAP_NATIVE_WIDTH) {
3481 strcat(line, ",");
3482 }
3483 }
3484
3485 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3486 }
3487
3488 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3490 int x;
3491
3492 line[0] = '\0';
3493 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3494 char token[TOKEN_SIZE];
3495 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3496
3497 if (ptile->placing != NULL) {
3498 fc_snprintf(token, sizeof(token), "%d",
3499 ptile->infra_turns);
3500 } else {
3501 fc_snprintf(token, sizeof(token), "0");
3502 }
3503 strcat(line, token);
3504 if (x + 1 < MAP_NATIVE_WIDTH) {
3505 strcat(line, ",");
3506 }
3507 }
3508
3509 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3510 }
3511}
3512
3513/************************************************************************/
3517{
3518 int x, y;
3519
3520 /* Check status and return if not OK (sg_success FALSE). */
3521 sg_check_ret();
3522
3523 sg_failure_ret(loading->worked_tiles == NULL,
3524 "City worked map not loaded!");
3525
3526 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3527 sizeof(*loading->worked_tiles));
3528
3529 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3530 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3531 y);
3532 const char *ptr = buffer;
3533
3534 sg_failure_ret(NULL != buffer,
3535 "Savegame corrupt - map line %d not found.", y);
3536 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3537 char token[TOKEN_SIZE];
3538 int number;
3539 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3540
3541 scanin(&ptr, ",", token, sizeof(token));
3542 sg_failure_ret('\0' != token[0],
3543 "Savegame corrupt - map size not correct.");
3544 if (strcmp(token, "-") == 0) {
3545 number = -1;
3546 } else {
3547 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3548 "Savegame corrupt - got tile worked by city "
3549 "id=%s in (%d, %d).", token, x, y);
3550 }
3551
3552 loading->worked_tiles[ptile->index] = number;
3553 }
3554 }
3555}
3556
3557/************************************************************************/
3561{
3562 int x, y;
3563
3564 /* Check status and return if not OK (sg_success FALSE). */
3565 sg_check_ret();
3566
3567 if (saving->scenario && !saving->save_players) {
3568 /* Nothing to do for a scenario without saved players. */
3569 return;
3570 }
3571
3572 /* Additionally save the tiles worked by the cities */
3573 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3575
3576 line[0] = '\0';
3577 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3578 char token[TOKEN_SIZE];
3579 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3580 struct city *pcity = tile_worked(ptile);
3581
3582 if (pcity == NULL) {
3583 strcpy(token, "-");
3584 } else {
3585 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3586 }
3587 strcat(line, token);
3588 if (x < MAP_NATIVE_WIDTH) {
3589 strcat(line, ",");
3590 }
3591 }
3592 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3593 }
3594}
3595
3596/************************************************************************/
3600{
3601 /* Check status and return if not OK (sg_success FALSE). */
3602 sg_check_ret();
3603
3604 players_iterate(pplayer) {
3605 /* Allocate player private map here; it is needed in different modules
3606 * besides this one ((i.e. sg_load_player_*()). */
3607 player_map_init(pplayer);
3609
3611 "game.save_known")) {
3612 int lines = player_slot_max_used_number() / 32 + 1;
3613 int j, p, l, i;
3614 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3615
3616 for (l = 0; l < lines; l++) {
3617 for (j = 0; j < 8; j++) {
3618 for (i = 0; i < 4; i++) {
3619 /* Only bother trying to load the map for this halfbyte if at least
3620 * one of the corresponding player slots is in use. */
3621 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3622 LOAD_MAP_CHAR(ch, ptile,
3623 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3624 |= ascii_hex2bin(ch, j),
3625 loading->file, "map.k%02d_%04d", l * 8 + j);
3626 break;
3627 }
3628 }
3629 }
3630 }
3631
3632 players_iterate(pplayer) {
3633 dbv_clr_all(&pplayer->tile_known);
3635
3636 /* HACK: we read the known data from hex into 32-bit integers, and
3637 * now we convert it to the known tile data of each player. */
3638 whole_map_iterate(&(wld.map), ptile) {
3639 players_iterate(pplayer) {
3640 p = player_index(pplayer);
3641 l = player_index(pplayer) / 32;
3642
3643 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3644 map_set_known(ptile, pplayer);
3645 }
3648
3649 FC_FREE(known);
3650 }
3651}
3652
3653/************************************************************************/
3657{
3658 /* Check status and return if not OK (sg_success FALSE). */
3659 sg_check_ret();
3660
3661 if (!saving->save_players) {
3662 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3663 return;
3664 } else {
3665 int lines = player_slot_max_used_number() / 32 + 1;
3666
3668 "game.save_known");
3670 int j, p, l, i;
3671 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3672
3673 /* HACK: we convert the data into a 32-bit integer, and then save it as
3674 * hex. */
3675
3676 whole_map_iterate(&(wld.map), ptile) {
3677 players_iterate(pplayer) {
3678 if (map_is_known(ptile, pplayer)) {
3679 p = player_index(pplayer);
3680 l = p / 32;
3681 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3682 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3683 }
3686
3687 for (l = 0; l < lines; l++) {
3688 for (j = 0; j < 8; j++) {
3689 for (i = 0; i < 4; i++) {
3690 /* Only bother saving the map for this halfbyte if at least one
3691 * of the corresponding player slots is in use */
3692 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3693 /* put 4-bit segments of the 32-bit "known" field */
3695 + tile_index(ptile)], j),
3696 saving->file, "map.k%02d_%04d", l * 8 + j);
3697 break;
3698 }
3699 }
3700 }
3701 }
3702
3703 FC_FREE(known);
3704 }
3705 }
3706}
3707
3708/* =======================================================================
3709 * Load / save player data.
3710 *
3711 * This is split into two parts as some data can only be loaded if the
3712 * number of players is known and the corresponding player slots are
3713 * defined.
3714 * ======================================================================= */
3715
3716/************************************************************************/
3720{
3721 int i, k, nplayers;
3722 const char *str;
3723 bool shuffle_loaded = TRUE;
3724
3725 /* Check status and return if not OK (sg_success FALSE). */
3726 sg_check_ret();
3727
3728 if (S_S_INITIAL == loading->server_state
3729 || game.info.is_new_game) {
3730 /* Nothing more to do. */
3731 return;
3732 }
3733
3734 /* Load destroyed wonders: */
3736 "players.destroyed_wonders");
3737 sg_failure_ret(str != NULL, "%s", secfile_error());
3738 sg_failure_ret(strlen(str) == loading->improvement.size,
3739 "Invalid length for 'players.destroyed_wonders' ("
3740 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3741 strlen(str), loading->improvement.size);
3742 for (k = 0; k < loading->improvement.size; k++) {
3743 sg_failure_ret(str[k] == '1' || str[k] == '0',
3744 "Undefined value '%c' within "
3745 "'players.destroyed_wonders'.", str[k]);
3746
3747 if (str[k] == '1') {
3748 struct impr_type *pimprove
3749 = improvement_by_rule_name(loading->improvement.order[k]);
3750
3751 if (pimprove != NULL) {
3754 }
3755 }
3756 }
3757
3758 server.identity_number
3759 = secfile_lookup_int_default(loading->file, server.identity_number,
3760 "players.identity_number_used");
3761
3762 /* First remove all defined players. */
3763 players_iterate(pplayer) {
3764 server_remove_player(pplayer);
3766
3767 /* Now, load the players from the savefile. */
3768 player_slots_iterate(pslot) {
3769 struct player *pplayer;
3770 struct rgbcolor *prgbcolor = NULL;
3771 int pslot_id = player_slot_index(pslot);
3772
3773 if (NULL == secfile_section_lookup(loading->file, "player%d",
3774 pslot_id)) {
3775 continue;
3776 }
3777
3778 /* Get player AI type. */
3779 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3780 player_slot_index(pslot));
3781 sg_failure_ret(str != NULL, "%s", secfile_error());
3782
3783 /* Get player color */
3784 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3785 pslot_id)) {
3786 if (game_was_started()) {
3787 log_sg("Game has started, yet player %d has no color defined.",
3788 pslot_id);
3789 /* This will be fixed up later */
3790 } else {
3791 log_verbose("No color defined for player %d.", pslot_id);
3792 /* Colors will be assigned on game start, or at end of savefile
3793 * loading if game has already started */
3794 }
3795 }
3796
3797 /* Create player. */
3798 pplayer = server_create_player(player_slot_index(pslot), str,
3799 prgbcolor,
3802 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3803
3804 server_player_init(pplayer, FALSE, FALSE);
3805
3806 /* Free the color definition. */
3808
3809 /* Multipliers (policies) */
3810
3811 /* First initialise player values with ruleset defaults; this will
3812 * cover any in the ruleset not known when the savefile was created. */
3813 multipliers_iterate(pmul) {
3814 pplayer->multipliers[multiplier_index(pmul)].value
3815 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3817
3818 /* Now override with any values from the savefile. */
3819 for (k = 0; k < loading->multiplier.size; k++) {
3820 const struct multiplier *pmul = loading->multiplier.order[k];
3821
3822 if (pmul) {
3824 int val =
3826 "player%d.multiplier%d.val",
3827 player_slot_index(pslot), k);
3828 int rval = (((CLIP(pmul->start, val, pmul->stop)
3829 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3830
3831 if (rval != val) {
3832 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3833 "was %d, clamped to %d", pslot_id,
3834 multiplier_rule_name(pmul), val, rval);
3835 }
3836 pplayer->multipliers[idx].value = rval;
3837
3838 val =
3840 pplayer->multipliers[idx].value,
3841 "player%d.multiplier%d.target",
3842 player_slot_index(pslot), k);
3843 rval = (((CLIP(pmul->start, val, pmul->stop)
3844 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3845
3846 if (rval != val) {
3847 log_verbose("Player %d had illegal value for multiplier_target "
3848 " \"%s\": was %d, clamped to %d", pslot_id,
3849 multiplier_rule_name(pmul), val, rval);
3850 }
3851 pplayer->multipliers[idx].target = rval;
3852
3853 pplayer->multipliers[idx].changed
3855 "player%d.multiplier%d.changed",
3856 player_slot_index(pslot), k);
3857 } /* else silently discard multiplier not in current ruleset */
3858 }
3859
3860 /* Must be loaded before tile owner is set. */
3861 pplayer->server.border_vision =
3863 "player%d.border_vision",
3864 player_slot_index(pslot));
3865
3867 "player%d.autoselect_weight",
3868 pslot_id);
3870
3871 /* check number of players */
3872 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3873 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3874 "(%d) from the loaded game does not match the number of "
3875 "players present (%d).", nplayers, player_count());
3876
3877 /* Load team information. */
3878 players_iterate(pplayer) {
3879 int team;
3880 struct team_slot *tslot = NULL;
3881
3883 "player%d.team_no",
3884 player_number(pplayer))
3886 "Invalid team definition for player %s (nb %d).",
3887 player_name(pplayer), player_number(pplayer));
3888 /* Should never fail when slot given is not nullptr */
3889 team_add_player(pplayer, team_new(tslot));
3891
3892 /* Loading the shuffle list is quite complex. At the time of saving the
3893 * shuffle data is saved as
3894 * shuffled_player_<number> = player_slot_id
3895 * where number is an increasing number and player_slot_id is a number
3896 * between 0 and the maximum number of player slots. Now we have to create
3897 * a list
3898 * shuffler_players[number] = player_slot_id
3899 * where all player slot IDs are used exactly one time. The code below
3900 * handles this ... */
3901 if (secfile_lookup_int_default(loading->file, -1,
3902 "players.shuffled_player_%d", 0) >= 0) {
3903 int slots = player_slot_count();
3904 int plrcount = player_count();
3907
3908 for (i = 0; i < slots; i++) {
3909 /* Array to save used numbers. */
3911 /* List of all player IDs (needed for set_shuffled_players()). It is
3912 * initialised with the value -1 to indicate that no value is set. */
3913 shuffled_players[i] = -1;
3914 }
3915
3916 /* Load shuffled player list. */
3917 for (i = 0; i < plrcount; i++) {
3918 int shuffle
3920 "players.shuffled_player_%d", i);
3921
3922 if (shuffle == -1) {
3923 log_sg("Missing player shuffle information (index %d) "
3924 "- reshuffle player list!", i);
3926 break;
3927 } else if (shuffled_player_set[shuffle]) {
3928 log_sg("Player shuffle %d used two times "
3929 "- reshuffle player list!", shuffle);
3931 break;
3932 }
3933 /* Set this ID as used. */
3935
3936 /* Save the player ID in the shuffle list. */
3938 }
3939
3940 if (shuffle_loaded) {
3941 /* Insert missing numbers. */
3942 int shuffle_index = plrcount;
3943
3944 for (i = 0; i < slots; i++) {
3945 if (!shuffled_player_set[i]) {
3947 }
3948
3949 /* shuffle_index must not grow higher than size of shuffled_players. */
3951 "Invalid player shuffle data!");
3952 }
3953
3954#ifdef FREECIV_DEBUG
3955 log_debug("[load shuffle] player_count() = %d", player_count());
3956 player_slots_iterate(pslot) {
3957 int plrid = player_slot_index(pslot);
3958
3959 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3961 shuffled_player_set[plrid] ? "is used" : "-");
3963#endif /* FREECIV_DEBUG */
3964
3965 /* Set shuffle list from savegame. */
3967 }
3968 }
3969
3970 if (!shuffle_loaded) {
3971 /* No shuffled players included or error loading them, so shuffle them
3972 * (this may include scenarios). */
3974 }
3975}
3976
3977/************************************************************************/
3981{
3982 /* Check status and return if not OK (sg_success FALSE). */
3983 sg_check_ret();
3984
3985 if (game.info.is_new_game) {
3986 /* Nothing to do. */
3987 return;
3988 }
3989
3990 players_iterate(pplayer) {
3991 sg_load_player_main(loading, pplayer);
3993 sg_load_player_units(loading, pplayer);
3995
3996 /* Check the success of the functions above. */
3997 sg_check_ret();
3998
3999 /* Print out some information */
4000 if (is_ai(pplayer)) {
4001 log_normal(_("%s has been added as %s level AI-controlled player "
4002 "(%s)."), player_name(pplayer),
4003 ai_level_translated_name(pplayer->ai_common.skill_level),
4004 ai_name(pplayer->ai));
4005 } else {
4006 log_normal(_("%s has been added as human player."),
4007 player_name(pplayer));
4008 }
4010
4011 /* Also load the transport status of the units here. It must be a special
4012 * case as all units must be known (unit on an allied transporter). */
4013 players_iterate(pplayer) {
4014 /* Load unit transport status. */
4017
4018 /* Savegame may contain nation assignments that are incompatible with the
4019 * current nationset. Ensure they are compatible, one way or another. */
4021
4022 /* Some players may have invalid nations in the ruleset. Once all players
4023 * are loaded, pick one of the remaining nations for them. */
4024 players_iterate(pplayer) {
4025 if (pplayer->nation == NO_NATION_SELECTED) {
4028 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4029 log_sg(_("%s had invalid nation; changing to %s."),
4030 player_name(pplayer), nation_plural_for_player(pplayer));
4031
4032 ai_traits_init(pplayer);
4033 }
4035
4036 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4039 if (pplayers_allied(plr, aplayer)) {
4041 DS_ALLIANCE);
4042
4045 log_sg("Illegal alliance structure detected: "
4046 "%s alliance to %s reduced to peace treaty.",
4051 }
4052 }
4055
4056 /* Update cached city illness. This can depend on trade routes,
4057 * so can't be calculated until all players have been loaded. */
4058 if (game.info.illness_on) {
4060 pcity->server.illness
4062 &(pcity->illness_trade), NULL);
4064 }
4065
4066 /* Update all city information. This must come after all cities are
4067 * loaded (in player_load) but before player (dumb) cities are loaded
4068 * in player_load_vision(). */
4069 players_iterate(plr) {
4070 city_list_iterate(plr->cities, pcity) {
4073 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4076
4077 /* Since the cities must be placed on the map to put them on the
4078 player map we do this afterwards */
4079 players_iterate(pplayer) {
4081 /* Check the success of the function above. */
4082 sg_check_ret();
4084
4085 /* Check shared vision and tiles. */
4086 players_iterate(pplayer) {
4087 BV_CLR_ALL(pplayer->gives_shared_vision);
4088 BV_CLR_ALL(pplayer->gives_shared_tiles);
4089 BV_CLR_ALL(pplayer->server.really_gives_vision);
4091
4092 /* Set up shared vision... */
4093 players_iterate(pplayer) {
4094 int plr1 = player_index(pplayer);
4095
4097 int plr2 = player_index(pplayer2);
4098
4100 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4101 give_shared_vision(pplayer, pplayer2);
4102 }
4104 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4105 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4106 }
4109
4110 /* ...and check it */
4113 /* TODO: Is there a good reason player is not marked as
4114 * giving shared vision to themselves -> really_gives_vision()
4115 * returning FALSE when pplayer1 == pplayer2 */
4116 if (pplayer1 != pplayer2
4119 sg_regr(3000900,
4120 _("%s did not give shared vision to team member %s."),
4123 }
4125 sg_regr(3000900,
4126 _("%s did not give shared vision to team member %s."),
4129 }
4130 }
4133
4136
4137 /* All vision is ready; this calls city_thaw_workers_queue(). */
4139
4140 /* Make sure everything is consistent. */
4141 players_iterate(pplayer) {
4142 unit_list_iterate(pplayer->units, punit) {
4144 struct tile *ptile = unit_tile(punit);
4145
4146 log_sg("%s doing illegal activity in savegame!",
4148 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4152 : "missing",
4153 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4155 }
4158
4161 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4163
4164 /* Player colors are always needed once game has started. Pre-2.4 savegames
4165 * lack them. This cannot be in compatibility conversion layer as we need
4166 * all the player data available to be able to assign best colors. */
4167 if (game_was_started()) {
4169 }
4170}
4171
4172/************************************************************************/
4175static void sg_save_players(struct savedata *saving)
4176{
4177 /* Check status and return if not OK (sg_success FALSE). */
4178 sg_check_ret();
4179
4180 if ((saving->scenario && !saving->save_players)
4181 || !game_was_started()) {
4182 /* Nothing to do for a scenario without saved players or a game in
4183 * INITIAL state. */
4184 return;
4185 }
4186
4187 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4188
4189 /* Save destroyed wonders as bitvector. Note that improvement order
4190 * is saved in 'savefile.improvement.order'. */
4191 {
4192 char destroyed[B_LAST+1];
4193
4194 improvement_iterate(pimprove) {
4195 if (is_great_wonder(pimprove)
4196 && great_wonder_is_destroyed(pimprove)) {
4197 destroyed[improvement_index(pimprove)] = '1';
4198 } else {
4199 destroyed[improvement_index(pimprove)] = '0';
4200 }
4202 destroyed[improvement_count()] = '\0';
4204 "players.destroyed_wonders");
4205 }
4206
4207 secfile_insert_int(saving->file, server.identity_number,
4208 "players.identity_number_used");
4209
4210 /* Save player order. */
4211 {
4212 int i = 0;
4213 shuffled_players_iterate(pplayer) {
4214 secfile_insert_int(saving->file, player_number(pplayer),
4215 "players.shuffled_player_%d", i);
4216 i++;
4218 }
4219
4220 /* Sort units. */
4222
4223 /* Save players. */
4224 players_iterate(pplayer) {
4225 sg_save_player_main(saving, pplayer);
4226 sg_save_player_cities(saving, pplayer);
4227 sg_save_player_units(saving, pplayer);
4229 sg_save_player_vision(saving, pplayer);
4231}
4232
4233/************************************************************************/
4237 struct player *plr)
4238{
4239 const char **slist;
4240 int i, plrno = player_number(plr);
4241 const char *str;
4242 struct government *gov;
4243 const char *level;
4244 const char *barb_str;
4245 size_t nval;
4246 const char *kind;
4247
4248 /* Check status and return if not OK (sg_success FALSE). */
4249 sg_check_ret();
4250
4251 /* Basic player data. */
4252 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4253 sg_failure_ret(str != NULL, "%s", secfile_error());
4255 sz_strlcpy(plr->username,
4257 "player%d.username", plrno));
4259 "player%d.unassigned_user", plrno),
4260 "%s", secfile_error());
4263 "player%d.orig_username", plrno));
4266 "player%d.ranked_username",
4267 plrno));
4269 "player%d.unassigned_ranked", plrno),
4270 "%s", secfile_error());
4272 "player%d.delegation_username",
4273 plrno);
4274 /* Defaults to no delegation. */
4275 if (strlen(str)) {
4277 }
4278
4279 /* Player flags */
4280 BV_CLR_ALL(plr->flags);
4281 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4282 for (i = 0; i < nval; i++) {
4283 const char *sval = slist[i];
4285
4286 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4287
4288 BV_SET(plr->flags, fid);
4289 }
4290 free(slist);
4291
4292 /* Nation */
4293 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4295 if (plr->nation != NULL) {
4296 ai_traits_init(plr);
4297 }
4298
4299 /* Government */
4300 str = secfile_lookup_str(loading->file, "player%d.government_name",
4301 plrno);
4303 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4304 plrno, str);
4305 plr->government = gov;
4306
4307 /* Target government */
4309 "player%d.target_government_name", plrno);
4310 if (str != NULL) {
4312 } else {
4313 plr->target_government = NULL;
4314 }
4317 "player%d.revolution_finishes", plrno);
4318
4319 /* Load diplomatic data (diplstate + embassy + vision).
4320 * Shared vision is loaded in sg_load_players(). */
4322 players_iterate(pplayer) {
4323 char buf[32];
4324 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4325 i = player_index(pplayer);
4326
4327 /* Load diplomatic status */
4328 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4329
4330 ds->type =
4332 diplstate_type, "%s.current", buf);
4333 ds->max_state =
4335 diplstate_type, "%s.closest", buf);
4336
4337 /* FIXME: If either party is barbarian, we cannot enforce below check */
4338#if 0
4339 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4340 sg_regr(3020000,
4341 "Player%d: War with player %d who has never been met. "
4342 "Reverted to No Contact state.", plrno, i);
4343 ds->type = DS_NO_CONTACT;
4344 }
4345#endif
4346
4347 if (valid_dst_closest(ds) != ds->max_state) {
4348 sg_regr(3020000,
4349 "Player%d: closest diplstate to player %d less than current. "
4350 "Updated.", plrno, i);
4351 ds->max_state = ds->type;
4352 }
4353
4354 ds->first_contact_turn =
4356 "%s.first_contact_turn", buf);
4357 ds->turns_left =
4358 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4359 ds->has_reason_to_cancel =
4361 "%s.has_reason_to_cancel", buf);
4362 ds->contact_turns_left =
4364 "%s.contact_turns_left", buf);
4365
4366 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4367 buf)) {
4368 BV_SET(plr->real_embassy, i);
4369 }
4370 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4371 * must be known. */
4373
4374 /* load ai data */
4376 char buf[32];
4377
4378 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4380
4382 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4383 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4385
4387 "player%d.adv.wonder_city",
4388 plrno);
4389
4390 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4391
4392 /* Some sane defaults */
4393 plr->ai_common.fuzzy = 0;
4394 plr->ai_common.expand = 100;
4395 plr->ai_common.science_cost = 100;
4396
4397
4399 "player%d.ai.level", plrno);
4400 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4401 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4403 } else {
4405 }
4406
4408 log_sg("Player%d: Invalid AI level \"%s\". "
4409 "Changed to \"%s\".", plrno, level,
4412 }
4413
4415 "player%d.ai.barb_type", plrno);
4417
4419 log_sg("Player%d: Invalid barbarian type \"%s\". "
4420 "Changed to \"None\".", plrno, barb_str);
4422 }
4423
4424 if (is_barbarian(plr)) {
4425 server.nbarbarians++;
4426 }
4427
4428 if (is_ai(plr)) {
4430 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4431 }
4432
4433 /* Load nation style. */
4434 {
4435 struct nation_style *style;
4436
4437 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4438
4439 sg_failure_ret(str != NULL, "%s", secfile_error());
4440 style = style_by_rule_name(str);
4441 if (style == NULL) {
4442 style = style_by_number(0);
4443 log_sg("Player%d: unsupported city_style_name \"%s\". "
4444 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4445 }
4446 plr->style = style;
4447 }
4448
4450 "player%d.idle_turns", plrno),
4451 "%s", secfile_error());
4452 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4453 if (sex_by_name(kind) == SEX_MALE) {
4454 plr->is_male = TRUE;
4455 } else {
4456 plr->is_male = FALSE;
4457 }
4459 "player%d.is_alive", plrno),
4460 "%s", secfile_error());
4462 "player%d.turns_alive", plrno),
4463 "%s", secfile_error());
4465 "player%d.last_war", plrno),
4466 "%s", secfile_error());
4468 "player%d.phase_done", plrno);
4470 "player%d.gold", plrno),
4471 "%s", secfile_error());
4473 "player%d.rates.tax", plrno),
4474 "%s", secfile_error());
4476 "player%d.rates.science", plrno),
4477 "%s", secfile_error());
4479 "player%d.rates.luxury", plrno),
4480 "%s", secfile_error());
4482 "player%d.infrapts",
4483 plrno);
4484 plr->server.bulbs_last_turn =
4486 "player%d.research.bulbs_last_turn", plrno);
4487
4488 /* Traits */
4489 if (plr->nation) {
4490 for (i = 0; i < loading->trait.size; i++) {
4491 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4492
4493 if (trait_is_valid(tr)) {
4494 int val;
4495
4496 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4497 plrno, i),
4498 "%s", secfile_error());
4499 plr->ai_common.traits[tr].val = val;
4500
4502 "player%d.trait%d.mod", plrno, i),
4503 "%s", secfile_error());
4504 plr->ai_common.traits[tr].mod = val;
4505 }
4506 }
4507 }
4508
4509 /* Achievements */
4510 {
4511 int count;
4512
4513 count = secfile_lookup_int_default(loading->file, -1,
4514 "player%d.achievement_count", plrno);
4515
4516 if (count > 0) {
4517 for (i = 0; i < count; i++) {
4518 const char *name;
4519 struct achievement *pach;
4520 bool first;
4521
4523 "player%d.achievement%d.name", plrno, i);
4525
4527 "Unknown achievement \"%s\".", name);
4528
4530 "player%d.achievement%d.first",
4531 plrno, i),
4532 "achievement error: %s", secfile_error());
4533
4534 sg_failure_ret(pach->first == NULL || !first,
4535 "Multiple players listed as first to get achievement \"%s\".",
4536 name);
4537
4538 BV_SET(pach->achievers, player_index(plr));
4539
4540 if (first) {
4541 pach->first = plr;
4542 }
4543 }
4544 }
4545 }
4546
4547 /* Player score. */
4548 plr->score.happy =
4550 "score%d.happy", plrno);
4551 plr->score.content =
4553 "score%d.content", plrno);
4554 plr->score.unhappy =
4556 "score%d.unhappy", plrno);
4557 plr->score.angry =
4559 "score%d.angry", plrno);
4560
4561 /* Make sure that the score about specialists in current ruleset that
4562 * were not present at saving time are set to zero. */
4564 plr->score.specialists[sp] = 0;
4566
4567 for (i = 0; i < loading->specialist.size; i++) {
4568 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4570 "score%d.specialists%d", plrno, i);
4571 }
4572
4573 plr->score.wonders =
4575 "score%d.wonders", plrno);
4576 plr->score.techs =
4578 "score%d.techs", plrno);
4579 plr->score.techout =
4581 "score%d.techout", plrno);
4582 plr->score.landarea =
4584 "score%d.landarea", plrno);
4585 plr->score.settledarea =
4587 "score%d.settledarea", plrno);
4588 plr->score.population =
4590 "score%d.population", plrno);
4591 plr->score.cities =
4593 "score%d.cities", plrno);
4594 plr->score.units =
4596 "score%d.units", plrno);
4597 plr->score.pollution =
4599 "score%d.pollution", plrno);
4600 plr->score.literacy =
4602 "score%d.literacy", plrno);
4603 plr->score.bnp =
4605 "score%d.bnp", plrno);
4606 plr->score.mfg =
4608 "score%d.mfg", plrno);
4609 plr->score.spaceship =
4611 "score%d.spaceship", plrno);
4612 plr->score.units_built =
4614 "score%d.units_built", plrno);
4615 plr->score.units_killed =
4617 "score%d.units_killed", plrno);
4618 plr->score.units_lost =
4620 "score%d.units_lost", plrno);
4621 plr->score.units_used =
4623 "score%d.units_used", plrno);
4624 plr->score.culture =
4626 "score%d.culture", plrno);
4627 plr->score.game =
4629 "score%d.total", plrno);
4630
4631 /* Load space ship data. */
4632 {
4633 struct player_spaceship *ship = &plr->spaceship;
4634 char prefix[32];
4635 const char *st;
4636 int ei;
4637
4638 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4641 &ei,
4642 "%s.state", prefix),
4643 "%s", secfile_error());
4644 ship->state = ei;
4645
4646 if (ship->state != SSHIP_NONE) {
4647 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4648 "%s.structurals", prefix),
4649 "%s", secfile_error());
4650 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4651 "%s.components", prefix),
4652 "%s", secfile_error());
4654 "%s.modules", prefix),
4655 "%s", secfile_error());
4657 "%s.fuel", prefix),
4658 "%s", secfile_error());
4659 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4660 "%s.propulsion", prefix),
4661 "%s", secfile_error());
4662 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4663 "%s.habitation", prefix),
4664 "%s", secfile_error());
4665 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4666 "%s.life_support", prefix),
4667 "%s", secfile_error());
4668 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4669 "%s.solar_panels", prefix),
4670 "%s", secfile_error());
4671
4672 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4673 sg_failure_ret(st != NULL, "%s", secfile_error())
4674 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4675 sg_failure_ret(st[i] == '1' || st[i] == '0',
4676 "Undefined value '%c' within '%s.structure'.", st[i],
4677 prefix)
4678
4679 if (!(st[i] == '0')) {
4680 BV_SET(ship->structure, i);
4681 }
4682 }
4683 if (ship->state >= SSHIP_LAUNCHED) {
4684 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4685 "%s.launch_year", prefix),
4686 "%s", secfile_error());
4687 }
4689 }
4690 }
4691
4692 /* Load lost wonder data. */
4693 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4694 /* If not present, probably an old savegame; nothing to be done */
4695 if (str != NULL) {
4696 int k;
4697
4698 sg_failure_ret(strlen(str) == loading->improvement.size,
4699 "Invalid length for 'player%d.lost_wonders' ("
4700 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4701 plrno, strlen(str), loading->improvement.size);
4702 for (k = 0; k < loading->improvement.size; k++) {
4703 sg_failure_ret(str[k] == '1' || str[k] == '0',
4704 "Undefined value '%c' within "
4705 "'player%d.lost_wonders'.", plrno, str[k]);
4706
4707 if (str[k] == '1') {
4708 struct impr_type *pimprove =
4709 improvement_by_rule_name(loading->improvement.order[k]);
4710 if (pimprove) {
4711 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4712 }
4713 }
4714 }
4715 }
4716
4717 plr->history =
4718 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4719 plr->server.huts =
4720 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4721}
4722
4723/************************************************************************/
4727 struct player *plr)
4728{
4729 int i, k, plrno = player_number(plr);
4730 struct player_spaceship *ship = &plr->spaceship;
4731 const char *flag_names[PLRF_COUNT];
4732 int set_count;
4733
4734 /* Check status and return if not OK (sg_success FALSE). */
4735 sg_check_ret();
4736
4737 set_count = 0;
4738 for (i = 0; i < PLRF_COUNT; i++) {
4739 if (player_has_flag(plr, i)) {
4741 }
4742 }
4743
4745 "player%d.flags", plrno);
4746
4747 secfile_insert_str(saving->file, ai_name(plr->ai),
4748 "player%d.ai_type", plrno);
4750 "player%d.name", plrno);
4752 "player%d.username", plrno);
4754 "player%d.unassigned_user", plrno);
4755 if (plr->rgb != NULL) {
4756 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4757 } else {
4758 /* Colorless players are ok in pregame */
4759 if (game_was_started()) {
4760 log_sg("Game has started, yet player %d has no color defined.", plrno);
4761 }
4762 }
4764 "player%d.ranked_username", plrno);
4766 "player%d.unassigned_ranked", plrno);
4768 "player%d.orig_username", plrno);
4771 : "",
4772 "player%d.delegation_username", plrno);
4774 "player%d.nation", plrno);
4775 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4776 "player%d.team_no", plrno);
4777
4780 "player%d.government_name", plrno);
4781
4782 if (plr->target_government) {
4785 "player%d.target_government_name", plrno);
4786 }
4787
4789 "player%d.style_by_name", plrno);
4790
4792 "player%d.idle_turns", plrno);
4793 if (plr->is_male) {
4795 "player%d.kind", plrno);
4796 } else {
4798 "player%d.kind", plrno);
4799 }
4801 "player%d.is_alive", plrno);
4803 "player%d.turns_alive", plrno);
4805 "player%d.last_war", plrno);
4807 "player%d.phase_done", plrno);
4808
4809 players_iterate(pplayer) {
4810 char buf[32];
4811 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4812
4813 i = player_index(pplayer);
4814
4815 /* save diplomatic state */
4816 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4817
4818 secfile_insert_enum(saving->file, ds->type,
4819 diplstate_type, "%s.current", buf);
4820 secfile_insert_enum(saving->file, ds->max_state,
4821 diplstate_type, "%s.closest", buf);
4822 secfile_insert_int(saving->file, ds->first_contact_turn,
4823 "%s.first_contact_turn", buf);
4824 secfile_insert_int(saving->file, ds->turns_left,
4825 "%s.turns_left", buf);
4826 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4827 "%s.has_reason_to_cancel", buf);
4828 secfile_insert_int(saving->file, ds->contact_turns_left,
4829 "%s.contact_turns_left", buf);
4831 "%s.embassy", buf);
4832 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4833 "%s.gives_shared_vision", buf);
4834 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4835 "%s.gives_shared_tiles", buf);
4837
4840 /* save ai data */
4842 "player%d.ai%d.love", plrno, i);
4843 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4845
4847 "player%d.adv.wonder_city", plrno);
4848
4849 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4850
4851 /* Multipliers (policies) */
4852 i = multiplier_count();
4853
4854 for (k = 0; k < i; k++) {
4856 "player%d.multiplier%d.val", plrno, k);
4858 "player%d.multiplier%d.target", plrno, k);
4860 "player%d.multiplier%d.changed", plrno, k);
4861 }
4862
4864 "player%d.ai.level", plrno);
4866 "player%d.ai.barb_type", plrno);
4868 "player%d.gold", plrno);
4870 "player%d.rates.tax", plrno);
4872 "player%d.rates.science", plrno);
4874 "player%d.rates.luxury", plrno);
4876 "player%d.infrapts", plrno);
4878 "player%d.research.bulbs_last_turn", plrno);
4879
4880 /* Save traits */
4881 {
4882 enum trait tr;
4883 int j;
4884
4885 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4887 "player%d.trait%d.val", plrno, j);
4889 "player%d.trait%d.mod", plrno, j);
4890 }
4891 }
4892
4893 /* Save achievements */
4894 {
4895 int j = 0;
4896
4898 if (achievement_player_has(pach, plr)) {
4900 "player%d.achievement%d.name", plrno, j);
4901 if (pach->first == plr) {
4903 "player%d.achievement%d.first", plrno, j);
4904 } else {
4906 "player%d.achievement%d.first", plrno, j);
4907 }
4908
4909 j++;
4910 }
4912
4913 secfile_insert_int(saving->file, j,
4914 "player%d.achievement_count", plrno);
4915 }
4916
4918 "player%d.revolution_finishes", plrno);
4919
4920 /* Player score */
4922 "score%d.happy", plrno);
4924 "score%d.content", plrno);
4926 "score%d.unhappy", plrno);
4928 "score%d.angry", plrno);
4931 "score%d.specialists%d", plrno, sp);
4934 "score%d.wonders", plrno);
4936 "score%d.techs", plrno);
4938 "score%d.techout", plrno);
4940 "score%d.landarea", plrno);
4942 "score%d.settledarea", plrno);
4944 "score%d.population", plrno);
4946 "score%d.cities", plrno);
4948 "score%d.units", plrno);
4950 "score%d.pollution", plrno);
4952 "score%d.literacy", plrno);
4953 secfile_insert_int(saving->file, plr->score.bnp,
4954 "score%d.bnp", plrno);
4955 secfile_insert_int(saving->file, plr->score.mfg,
4956 "score%d.mfg", plrno);
4958 "score%d.spaceship", plrno);
4960 "score%d.units_built", plrno);
4962 "score%d.units_killed", plrno);
4964 "score%d.units_lost", plrno);
4966 "score%d.units_used", plrno);
4968 "score%d.culture", plrno);
4969 secfile_insert_int(saving->file, plr->score.game,
4970 "score%d.total", plrno);
4971
4972 /* Save space ship status. */
4973 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4974 plrno);
4975 if (ship->state != SSHIP_NONE) {
4976 char buf[32];
4977 char st[NUM_SS_STRUCTURALS+1];
4978 int ssi;
4979
4980 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4981
4982 secfile_insert_int(saving->file, ship->structurals,
4983 "%s.structurals", buf);
4984 secfile_insert_int(saving->file, ship->components,
4985 "%s.components", buf);
4986 secfile_insert_int(saving->file, ship->modules,
4987 "%s.modules", buf);
4988 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4989 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4990 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4991 secfile_insert_int(saving->file, ship->life_support,
4992 "%s.life_support", buf);
4993 secfile_insert_int(saving->file, ship->solar_panels,
4994 "%s.solar_panels", buf);
4995
4996 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4997 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4998 }
4999 st[ssi] = '\0';
5000 secfile_insert_str(saving->file, st, "%s.structure", buf);
5001 if (ship->state >= SSHIP_LAUNCHED) {
5002 secfile_insert_int(saving->file, ship->launch_year,
5003 "%s.launch_year", buf);
5004 }
5005 }
5006
5007 /* Save lost wonders info. */
5008 {
5009 char lost[B_LAST+1];
5010
5011 improvement_iterate(pimprove) {
5012 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5013 lost[improvement_index(pimprove)] = '1';
5014 } else {
5015 lost[improvement_index(pimprove)] = '0';
5016 }
5018 lost[improvement_count()] = '\0';
5020 "player%d.lost_wonders", plrno);
5021 }
5022
5023 secfile_insert_int(saving->file, plr->history,
5024 "player%d.history", plrno);
5026 "player%d.hut_count", plrno);
5027
5029 "player%d.border_vision", plrno);
5030
5031 if (saving->scenario) {
5032 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5033 int def = 1; /* We want users to get a player in a scenario */
5034
5036 /* This isn't usable player */
5037 def = 0;
5038 }
5039
5040 secfile_insert_int(saving->file, def,
5041 "player%d.autoselect_weight", plrno);
5042 } else {
5044 "player%d.autoselect_weight", plrno);
5045 }
5046 }
5047}
5048
5049/************************************************************************/
5053 struct player *plr)
5054{
5055 int ncities, i, plrno = player_number(plr);
5056 bool tasks_handled;
5058
5059 /* Check status and return if not OK (sg_success FALSE). */
5060 sg_check_ret();
5061
5063 "player%d.ncities", plrno),
5064 "%s", secfile_error());
5065
5066 if (!plr->is_alive && ncities > 0) {
5067 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5068 ncities = 0;
5069 }
5070
5072 "player%d.wl_max_length",
5073 plrno);
5075 log_sg("wlist_max_length %d over MAX_LEN_WORKLIST (%d)",
5077 }
5078
5080 "player%d.routes_max_length", plrno);
5081
5082 /* Load all cities of the player. */
5083 for (i = 0; i < ncities; i++) {
5084 char buf[32];
5085 struct city *pcity;
5086
5087 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5088
5089 /* Create a dummy city. */
5096 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5097 }
5098
5101
5102 /* Load the information about the nationality of citizens. This is done
5103 * here because the city sanity check called by citizens_update() requires
5104 * that the city is registered. */
5106
5107 /* After everything is loaded, but before vision. */
5109
5110 /* adding the city contribution to fog-of-war */
5114
5116 }
5117
5119 for (i = 0; !tasks_handled; i++) {
5120 int city_id;
5121 struct city *pcity = NULL;
5122
5123 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5124 plrno, i);
5125
5126 if (city_id != -1) {
5127 pcity = player_city_by_number(plr, city_id);
5128 }
5129
5130 if (pcity != NULL) {
5131 const char *str;
5132 int nat_x, nat_y;
5133 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5134
5135 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5136 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5137
5138 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5139
5140 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5142
5144 "Unknown workertask activity %s", str);
5145
5146 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5147
5148 if (strcmp("-", str)) {
5150
5151 sg_failure_ret(ptask->tgt != NULL,
5152 "Unknown workertask target %s", str);
5153 } else {
5154 ptask->tgt = NULL;
5155
5156 if (ptask->act == ACTIVITY_IRRIGATE) {
5158 } else if (ptask->act == ACTIVITY_MINE) {
5159 ptask->act = ACTIVITY_MINE;
5160 }
5161 }
5162
5163 ptask->want = secfile_lookup_int_default(loading->file, 1,
5164 "player%d.task%d.want", plrno, i);
5165
5166 worker_task_list_append(pcity->task_reqs, ptask);
5167 } else {
5169 }
5170 }
5171}
5172
5173/************************************************************************/
5176static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5177 struct city *pcity, const char *citystr,
5179{
5180 struct player *past;
5181 const char *kind, *name, *str;
5182 int id, i, repair, sp_count = 0, workers = 0, value;
5183 int nat_x, nat_y;
5184 citizens size;
5185 const char *stylename;
5186 int partner;
5187 int want;
5188 int tmp_int;
5189 const struct civ_map *nmap = &(wld.map);
5190 enum capital_type cap;
5191
5193 FALSE, "%s", secfile_error());
5195 FALSE, "%s", secfile_error());
5198 "%s has invalid center tile (%d, %d)",
5199 citystr, nat_x, nat_y);
5201 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5202
5203 /* Instead of dying, use 'citystr' string for damaged name. */
5205 "%s.name", citystr));
5206
5208 citystr), FALSE, "%s", secfile_error());
5209
5211 "%s.original", citystr);
5212 past = player_by_number(id);
5213 if (NULL != past) {
5214 pcity->original = past;
5215 }
5216
5217 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5218 citystr), FALSE, "%s", secfile_error());
5219 size = (citizens)value; /* Set the correct type */
5220 sg_warn_ret_val(value == (int)size, FALSE,
5221 "Invalid city size: %d, set to %d", value, size);
5223
5225 "%s.capital", citystr),
5227
5229 pcity->capital = cap;
5230 if (cap == CAPITAL_PRIMARY) {
5231 plr->primary_capital_id = pcity->id;
5232 }
5233 } else {
5234 pcity->capital = CAPITAL_NOT;
5235 }
5236
5237 for (i = 0; i < loading->specialist.size; i++) {
5238 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5239 citystr, i),
5240 FALSE, "%s", secfile_error());
5241 pcity->specialists[specialist_index(loading->specialist.order[i])]
5242 = (citizens)value;
5243 sp_count += value;
5244 }
5245
5246 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5247 for (i = 0; partner != 0; i++) {
5248 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5249 const char *dir;
5250 const char *good_str;
5251
5252 /* Append to routes list immediately, so the pointer can be found for freeing
5253 * even if we abort */
5255
5256 proute->partner = partner;
5257 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5259 "No traderoute direction found for %s", citystr);
5262 "Illegal route direction %s", dir);
5263 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5265 "No good found for %s", citystr);
5267 sg_warn_ret_val(proute->goods != NULL, FALSE,
5268 "Illegal good %s", good_str);
5269
5270 /* Next one */
5272 "%s.traderoute%d", citystr, i + 1);
5273 }
5274
5275 for (; i < routes_max; i++) {
5276 secfile_entry_ignore(loading->file, "%s.traderoute%d", citystr, i);
5277 secfile_entry_ignore(loading->file, "%s.route_direction%d", citystr, i);
5278 secfile_entry_ignore(loading->file, "%s.route_good%d", citystr, i);
5279 }
5280
5281 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5282 "%s.food_stock", citystr),
5283 FALSE, "%s", secfile_error());
5284 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5285 "%s.shield_stock", citystr),
5286 FALSE, "%s", secfile_error());
5287 pcity->history =
5288 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5289
5290 pcity->airlift =
5291 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5292 pcity->was_happy =
5293 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5294 citystr);
5295 pcity->had_famine =
5296 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5297 citystr);
5298
5299 pcity->turn_plague =
5300 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5301
5303 "%s.anarchy", citystr),
5304 FALSE, "%s", secfile_error());
5305 pcity->rapture =
5306 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5307 pcity->steal =
5308 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5309
5310 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5311 "%s.turn_founded", citystr),
5312 FALSE, "%s", secfile_error());
5314 "%s.acquire_t", citystr),
5315 FALSE, "%s", secfile_error());
5316 pcity->acquire_t = tmp_int;
5317 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5318 citystr), FALSE, "%s", secfile_error());
5319 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5320 citystr), FALSE, "%s", secfile_error());
5321
5322 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5323 "%s.turn_last_built", citystr),
5324 FALSE, "%s", secfile_error());
5325
5326 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5327 citystr);
5328 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5329 citystr);
5330 pcity->production = universal_by_rule_name(kind, name);
5331 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5332 "%s.currently_building: unknown \"%s\" \"%s\".",
5333 citystr, kind, name);
5334
5335 want = secfile_lookup_int_default(loading->file, 0,
5336 "%s.current_want", citystr);
5337 if (pcity->production.kind == VUT_IMPROVEMENT) {
5338 pcity->server.adv->
5339 building_want[improvement_index(pcity->production.value.building)]
5340 = want;
5341 }
5342
5343 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5344 citystr);
5345 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5346 citystr);
5349 "%s.changed_from: unknown \"%s\" \"%s\".",
5350 citystr, kind, name);
5351
5352 pcity->before_change_shields =
5353 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5354 "%s.before_change_shields", citystr);
5355 pcity->caravan_shields =
5357 "%s.caravan_shields", citystr);
5358 pcity->disbanded_shields =
5360 "%s.disbanded_shields", citystr);
5361 pcity->last_turns_shield_surplus =
5363 "%s.last_turns_shield_surplus",
5364 citystr);
5365
5367 "%s.style", citystr);
5368 if (stylename != NULL) {
5370 } else {
5371 pcity->style = 0;
5372 }
5373 if (pcity->style < 0) {
5374 pcity->style = city_style(pcity);
5375 }
5376
5377 pcity->server.synced = FALSE; /* Must re-sync with clients */
5378
5379 /* Initialise list of city improvements. */
5380 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5381 pcity->built[i].turn = I_NEVER;
5382 }
5383
5384 /* Load city improvements. */
5385 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5387 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5388 "Invalid length of '%s.improvements' ("
5389 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5390 citystr, strlen(str), loading->improvement.size);
5391 for (i = 0; i < loading->improvement.size; i++) {
5392 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5393 "Undefined value '%c' within '%s.improvements'.",
5394 str[i], citystr)
5395
5396 if (str[i] == '1') {
5397 struct impr_type *pimprove
5398 = improvement_by_rule_name(loading->improvement.order[i]);
5399
5400 if (pimprove) {
5401 city_add_improvement(pcity, pimprove);
5402 }
5403 }
5404 }
5405
5406 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5407 "No worked tiles map defined.");
5408
5410
5411 /* Load new savegame with variable (squared) city radius and worked
5412 * tiles map */
5413
5414 int radius_sq
5415 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5416 citystr);
5417 city_map_radius_sq_set(pcity, radius_sq);
5418
5420 if (loading->worked_tiles[ptile->index] == pcity->id) {
5421 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5422 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5423 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5424 TILE_XY(pcity->tile), TILE_XY(ptile));
5425 pcity->specialists[DEFAULT_SPECIALIST]++;
5426 sp_count++;
5427 } else {
5428 tile_set_worked(ptile, pcity);
5429 workers++;
5430 }
5431
5432#ifdef FREECIV_DEBUG
5433 /* Set this tile to unused; a check for not reset tiles is
5434 * included in game_load_internal() */
5435 loading->worked_tiles[ptile->index] = -1;
5436#endif /* FREECIV_DEBUG */
5437 }
5439
5440 if (tile_worked(city_tile(pcity)) != pcity) {
5441 struct city *pwork = tile_worked(city_tile(pcity));
5442
5443 if (NULL != pwork) {
5444 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5445 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5448
5449 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5450 pwork->specialists[DEFAULT_SPECIALIST]++;
5452 } else {
5453 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5456 }
5457
5458 /* Repair pcity */
5461 }
5462
5464 if (0 != repair) {
5465 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5466 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5468 workers, FREE_WORKED_TILES, sp_count);
5469
5470 /* Repair pcity */
5472 }
5473
5474 /* worklist_init() done in create_city_virtual() */
5475 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5476
5477 /* Load city options. */
5478 BV_CLR_ALL(pcity->city_options);
5479 for (i = 0; i < loading->coptions.size; i++) {
5480 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5481 citystr, i)) {
5482 BV_SET(pcity->city_options, loading->coptions.order[i]);
5483 }
5484 }
5486 "%s.wlcb", citystr),
5487 FALSE, "%s", secfile_error());
5488 pcity->wlcb = tmp_int;
5489
5490 /* Load the city rally point. */
5491 {
5492 int len = secfile_lookup_int_default(loading->file, 0,
5493 "%s.rally_point_length", citystr);
5494 int unconverted;
5495
5496 pcity->rally_point.length = len;
5497 if (len > 0) {
5499
5500 pcity->rally_point.orders
5501 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5502 pcity->rally_point.persistent
5504 "%s.rally_point_persistent", citystr);
5505 pcity->rally_point.vigilant
5507 "%s.rally_point_vigilant", citystr);
5508
5511 "%s.rally_point_orders", citystr);
5514 "%s.rally_point_dirs", citystr);
5517 "%s.rally_point_activities", citystr);
5518
5519 for (i = 0; i < len; i++) {
5520 struct unit_order *order = &pcity->rally_point.orders[i];
5521
5522 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5523 || rally_activities[i] == '\0') {
5524 log_sg("Invalid rally point.");
5525 free(pcity->rally_point.orders);
5526 pcity->rally_point.orders = NULL;
5527 pcity->rally_point.length = 0;
5528 break;
5529 }
5530 order->order = char2order(rally_orders[i]);
5531 order->dir = char2dir(rally_dirs[i]);
5532 order->activity = char2activity(rally_activities[i]);
5533
5535 "%s.rally_point_action_vec,%d",
5536 citystr, i);
5537
5538 if (unconverted == -1) {
5539 order->action = ACTION_NONE;
5540 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5541 /* Look up what action id the unconverted number represents. */
5542 order->action = loading->action.order[unconverted];
5543 } else {
5544 if (order->order == ORDER_PERFORM_ACTION) {
5545 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5546 pcity->id);
5547 }
5548
5549 order->action = ACTION_NONE;
5550 }
5551
5552 order->target
5554 "%s.rally_point_tgt_vec,%d",
5555 citystr, i);
5556 order->sub_target
5558 "%s.rally_point_sub_tgt_vec,%d",
5559 citystr, i);
5560 }
5561 } else {
5562 pcity->rally_point.orders = NULL;
5563
5564 secfile_entry_ignore(loading->file, "%s.rally_point_persistent",
5565 citystr);
5566 secfile_entry_ignore(loading->file, "%s.rally_point_vigilant",
5567 citystr);
5568 secfile_entry_ignore(loading->file, "%s.rally_point_orders",
5569 citystr);
5570 secfile_entry_ignore(loading->file, "%s.rally_point_dirs",
5571 citystr);
5572 secfile_entry_ignore(loading->file, "%s.rally_point_activities",
5573 citystr);
5574 secfile_entry_ignore(loading->file, "%s.rally_point_action_vec",
5575 citystr);
5577 "%s.rally_point_tgt_vec", citystr);
5579 "%s.rally_point_sub_tgt_vec", citystr);
5580 }
5581 }
5582
5583 /* Load the city manager parameters. */
5584 {
5585 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5586 "%s.cma_enabled", citystr);
5587 if (enabled) {
5588 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5589
5590 for (i = 0; i < O_LAST; i++) {
5592 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5594 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5595 }
5596
5598 loading->file, FALSE, "%s.max_growth", citystr);
5600 loading->file, FALSE, "%s.require_happy", citystr);
5602 loading->file, FALSE, "%s.allow_disorder", citystr);
5604 loading->file, FALSE, "%s.allow_specialists", citystr);
5606 loading->file, 0, "%s.happy_factor", citystr);
5607 pcity->cm_parameter = param;
5608 } else {
5609 pcity->cm_parameter = NULL;
5610
5611 for (i = 0; i < O_LAST; i++) {
5613 "%s.cma_minimal_surplus,%d", citystr, i);
5615 "%s.cma_factor,%d", citystr, i);
5616 }
5617
5618 secfile_entry_ignore(loading->file, "%s.max_growth",
5619 citystr);
5620 secfile_entry_ignore(loading->file, "%s.require_happy",
5621 citystr);
5622 secfile_entry_ignore(loading->file, "%s.allow_disorder",
5623 citystr);
5624 secfile_entry_ignore(loading->file, "%s.allow_specialists",
5625 citystr);
5626 secfile_entry_ignore(loading->file, "%s.happy_factor",
5627 citystr);
5628 }
5629 }
5630
5631 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5632
5633 return TRUE;
5634}
5635
5636/************************************************************************/
5640 struct player *plr,
5641 struct city *pcity,
5642 const char *citystr)
5643{
5645 citizens size;
5646
5648 player_slots_iterate(pslot) {
5649 int nationality;
5650
5651 nationality = secfile_lookup_int_default(loading->file, -1,
5652 "%s.citizen%d", citystr,
5653 player_slot_index(pslot));
5654 if (nationality > 0 && !player_slot_is_used(pslot)) {
5655 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5657 continue;
5658 }
5659
5660 if (nationality != -1 && player_slot_is_used(pslot)) {
5661 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5662 "Invalid value for citizens of player %d in %s: %d.",
5663 player_slot_index(pslot), city_name_get(pcity), nationality);
5664 citizens_nation_set(pcity, pslot, nationality);
5665 }
5667 /* Sanity check. */
5669 if (size != city_size_get(pcity)) {
5670 if (size != 0) {
5671 /* size == 0 can be result from the fact that ruleset had no
5672 * nationality enabled at saving time, so no citizens at all
5673 * were saved. But something more serious must be going on if
5674 * citizens have been saved partially - if some of them are there. */
5675 log_sg("City size and number of citizens does not match in %s "
5676 "(%d != %d)! Repairing ...", city_name_get(pcity),
5678 }
5680 }
5681 }
5682}
5683
5684/************************************************************************/
5688 struct player *plr)
5689{
5691 int i = 0;
5692 int plrno = player_number(plr);
5694
5695 /* Check status and return if not OK (sg_success FALSE). */
5696 sg_check_ret();
5697
5699 "player%d.ncities", plrno);
5700
5702 /* Initialise the nation list for the citizens information. */
5703 player_slots_iterate(pslot) {
5706 }
5707
5708 /* First determine length of longest worklist, rally point order, and the
5709 * nationalities we have. */
5711 int routes;
5712
5713 /* Check the sanity of the city. */
5716
5717 if (pcity->worklist.length > wlist_max_length) {
5718 wlist_max_length = pcity->worklist.length;
5719 }
5720
5721 if (pcity->rally_point.length > rally_point_max_length) {
5722 rally_point_max_length = pcity->rally_point.length;
5723 }
5724
5725 routes = city_num_trade_routes(pcity);
5726 if (routes > routes_max) {
5727 routes_max = routes;
5728 }
5729
5731 /* Find all nations of the citizens,*/
5732 players_iterate(pplayer) {
5733 if (!nations[player_index(pplayer)]
5734 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5735 nations[player_index(pplayer)] = TRUE;
5736 }
5738 }
5740
5742 "player%d.wl_max_length", plrno);
5744 "player%d.routes_max_length", plrno);
5745
5747 struct tile *pcenter = city_tile(pcity);
5748 char impr_buf[B_LAST + 1];
5749 char buf[32];
5750 int j, nat_x, nat_y;
5751
5752 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5753
5754
5756 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5757 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5758
5759 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5760
5761 if (pcity->original != NULL) {
5762 secfile_insert_int(saving->file, player_number(pcity->original),
5763 "%s.original", buf);
5764 } else {
5765 secfile_insert_int(saving->file, -1, "%s.original", buf);
5766 }
5767 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5768
5770 "%s.capital", buf);
5771
5772 j = 0;
5774 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5775 buf, j++);
5777
5778 j = 0;
5780 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5781 buf, j);
5783 "%s.route_direction%d", buf, j);
5785 "%s.route_good%d", buf, j);
5786 j++;
5788
5789 /* Save dummy values to keep tabular format happy */
5790 for (; j < routes_max; j++) {
5791 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5793 "%s.route_direction%d", buf, j);
5795 "%s.route_good%d", buf, j);
5796 }
5797
5798 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5799 buf);
5800 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5801 buf);
5802 secfile_insert_int(saving->file, pcity->history, "%s.history",
5803 buf);
5804
5805 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5806 buf);
5807 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5808 buf);
5809 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5810 buf);
5811 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5812 buf);
5813
5814 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5815 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5816 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5817 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5818 buf);
5819 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5820 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5821 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5822 secfile_insert_int(saving->file, pcity->turn_last_built,
5823 "%s.turn_last_built", buf);
5824
5825 /* For visual debugging, variable length strings together here */
5826 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5827
5829 "%s.currently_building_kind", buf);
5831 "%s.currently_building_name", buf);
5832
5833 if (pcity->production.kind == VUT_IMPROVEMENT) {
5835 pcity->server.adv->
5836 building_want[improvement_index(pcity->production.value.building)],
5837 "%s.current_want", buf);
5838 } else {
5839 secfile_insert_int(saving->file, 0,
5840 "%s.current_want", buf);
5841 }
5842
5844 "%s.changed_from_kind", buf);
5846 "%s.changed_from_name", buf);
5847
5848 secfile_insert_int(saving->file, pcity->before_change_shields,
5849 "%s.before_change_shields", buf);
5850 secfile_insert_int(saving->file, pcity->caravan_shields,
5851 "%s.caravan_shields", buf);
5852 secfile_insert_int(saving->file, pcity->disbanded_shields,
5853 "%s.disbanded_shields", buf);
5854 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5855 "%s.last_turns_shield_surplus", buf);
5856
5858 "%s.style", buf);
5859
5860 /* Save the squared city radius and all tiles within the corresponding
5861 * city map. */
5862 secfile_insert_int(saving->file, pcity->city_radius_sq,
5863 "player%d.c%d.city_radius_sq", plrno, i);
5864 /* The tiles worked by the city are saved using the main map.
5865 * See also sg_save_map_worked(). */
5866
5867 /* Save improvement list as bytevector. Note that improvement order
5868 * is saved in savefile.improvement_order. */
5869 improvement_iterate(pimprove) {
5870 impr_buf[improvement_index(pimprove)]
5871 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5872 : '1';
5874 impr_buf[improvement_count()] = '\0';
5875
5877 "Invalid size of the improvement vector (%s.improvements: "
5878 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5879 strlen(impr_buf), sizeof(impr_buf));
5880 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5881
5882 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5883 buf);
5884
5885 for (j = 0; j < CITYO_LAST; j++) {
5886 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5887 "%s.option%d", buf, j);
5888 }
5889 secfile_insert_int(saving->file, pcity->wlcb,
5890 "%s.wlcb", buf);
5891
5892 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5893
5895 /* Save nationality of the citizens,*/
5896 players_iterate(pplayer) {
5897 if (nations[player_index(pplayer)]) {
5899 citizens_nation_get(pcity, pplayer->slot),
5900 "%s.citizen%d", buf, player_index(pplayer));
5901 }
5903 }
5904
5905 secfile_insert_int(saving->file, pcity->rally_point.length,
5906 "%s.rally_point_length", buf);
5907 if (pcity->rally_point.length) {
5908 int len = pcity->rally_point.length;
5909 char orders[len + 1], dirs[len + 1], activities[len + 1];
5910 int actions[len];
5911 int targets[len];
5912 int sub_targets[len];
5913
5914 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5915 "%s.rally_point_persistent", buf);
5916 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5917 "%s.rally_point_vigilant", buf);
5918
5919 for (j = 0; j < len; j++) {
5920 orders[j] = order2char(pcity->rally_point.orders[j].order);
5921 dirs[j] = '?';
5922 activities[j] = '?';
5923 targets[j] = NO_TARGET;
5924 sub_targets[j] = NO_TARGET;
5925 actions[j] = -1;
5926 switch (pcity->rally_point.orders[j].order) {
5927 case ORDER_MOVE:
5928 case ORDER_ACTION_MOVE:
5929 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5930 break;
5931 case ORDER_ACTIVITY:
5932 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5933 activities[j]
5934 = activity2char(pcity->rally_point.orders[j].activity);
5935 actions[j]
5936 = pcity->rally_point.orders[j].action;
5937 break;
5939 actions[j] = pcity->rally_point.orders[j].action;
5940 targets[j] = pcity->rally_point.orders[j].target;
5941 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5942 break;
5943 case ORDER_FULL_MP:
5944 case ORDER_LAST:
5945 break;
5946 }
5947
5948 if (actions[j] == ACTION_NONE) {
5949 actions[j] = -1;
5950 }
5951 }
5952 orders[len] = dirs[len] = activities[len] = '\0';
5953
5954 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5955 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5956 secfile_insert_str(saving->file, activities,
5957 "%s.rally_point_activities", buf);
5958
5960 "%s.rally_point_action_vec", buf);
5961 /* Fill in dummy values for order targets so the registry will save
5962 * the unit table in a tabular format. */
5963 for (j = len; j < rally_point_max_length; j++) {
5964 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5965 buf, j);
5966 }
5967
5968 secfile_insert_int_vec(saving->file, targets, len,
5969 "%s.rally_point_tgt_vec", buf);
5970 /* Fill in dummy values for order targets so the registry will save
5971 * the unit table in a tabular format. */
5972 for (j = len; j < rally_point_max_length; j++) {
5974 "%s.rally_point_tgt_vec,%d", buf, j);
5975 }
5976
5977 secfile_insert_int_vec(saving->file, sub_targets, len,
5978 "%s.rally_point_sub_tgt_vec", buf);
5979 /* Fill in dummy values for order targets so the registry will save
5980 * the unit table in a tabular format. */
5981 for (j = len; 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 } else {
5986 /* Put all the same fields into the savegame - otherwise the
5987 * registry code can't correctly use a tabular format and the
5988 * savegame will be bigger. */
5989 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5990 buf);
5991 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5992 buf);
5993 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5994 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5995 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5996 buf);
5997
5998 /* Fill in dummy values for order targets so the registry will save
5999 * the unit table in a tabular format. */
6000
6001 /* The start of a vector has no number. */
6002 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
6003 buf);
6004 for (j = 1; j < rally_point_max_length; j++) {
6005 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
6006 buf, j);
6007 }
6008
6009 /* The start of a vector has no number. */
6010 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
6011 buf);
6012 for (j = 1; j < rally_point_max_length; j++) {
6014 "%s.rally_point_tgt_vec,%d", buf, j);
6015 }
6016
6017 /* The start of a vector has no number. */
6018 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
6019 buf);
6020 for (j = 1; j < rally_point_max_length; j++) {
6021 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
6022 buf, j);
6023 }
6024 }
6025
6026 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
6027 "%s.cma_enabled", buf);
6028 if (pcity->cm_parameter) {
6030 pcity->cm_parameter->minimal_surplus, O_LAST,
6031 "%s.cma_minimal_surplus", buf);
6033 pcity->cm_parameter->factor, O_LAST,
6034 "%s.cma_factor", buf);
6035 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6036 "%s.max_growth", buf);
6037 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6038 "%s.require_happy", buf);
6039 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6040 "%s.allow_disorder", buf);
6042 pcity->cm_parameter->allow_specialists,
6043 "%s.allow_specialists", buf);
6044 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6045 "%s.happy_factor", buf);
6046 } else {
6047 int zeros[O_LAST];
6048
6049 memset(zeros, 0, sizeof(zeros));
6051 "%s.cma_minimal_surplus", buf);
6053 "%s.cma_factor", buf);
6054 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6055 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6056 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6057 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6058 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6059 }
6060
6061 i++;
6063
6064 i = 0;
6066 worker_task_list_iterate(pcity->task_reqs, ptask) {
6067 int nat_x, nat_y;
6068
6070 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6071 plrno, i);
6072 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6073 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6075 "player%d.task%d.activity",
6076 plrno, i);
6077 if (ptask->tgt != NULL) {
6079 "player%d.task%d.target",
6080 plrno, i);
6081 } else {
6082 secfile_insert_str(saving->file, "-",
6083 "player%d.task%d.target",
6084 plrno, i);
6085 }
6086 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6087
6088 i++;
6091}
6092
6093/************************************************************************/
6097 struct player *plr)
6098{
6099 int nunits, i, plrno = player_number(plr);
6100 size_t orders_max_length;
6101
6102 /* Check status and return if not OK (sg_success FALSE). */
6103 sg_check_ret();
6104
6106 "player%d.nunits", plrno),
6107 "%s", secfile_error());
6108 if (!plr->is_alive && nunits > 0) {
6109 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6110 nunits = 0; /* Some old savegames may be buggy. */
6111 }
6112
6114 "player%d.orders_max_length",
6115 plrno);
6116
6117 for (i = 0; i < nunits; i++) {
6118 struct unit *punit;
6119 struct city *pcity;
6120 const char *name;
6121 char buf[32];
6122 struct unit_type *type;
6123 struct tile *ptile;
6124
6125 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6126
6127 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6129 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6130
6131 /* Create a dummy unit. */
6132 punit = unit_virtual_create(plr, NULL, type, 0);
6135 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6136 }
6137
6140
6142 unit_list_prepend(pcity->units_supported, punit);
6143 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6144 log_sg("%s: bad home city %d.", buf, punit->homecity);
6146 }
6147
6148 ptile = unit_tile(punit);
6149
6150 /* allocate the unit's contribution to fog of war */
6153 /* NOTE: There used to be some map_set_known calls here. These were
6154 * unneeded since unfogging the tile when the unit sees it will
6155 * automatically reveal that tile. */
6156
6159 }
6160}
6161
6162/************************************************************************/
6166 struct player *plr, struct unit *punit,
6168 const char *unitstr)
6169{
6170 enum unit_activity activity;
6171 int nat_x, nat_y;
6172 struct extra_type *pextra = NULL;
6173 struct tile *ptile;
6174 int extra_id;
6175 int ei;
6176 const char *facing_str;
6177 int natnbr;
6178 int unconverted;
6179 const char *str;
6180 enum gen_action action;
6181
6183 unitstr), FALSE, "%s", secfile_error());
6185 FALSE, "%s", secfile_error());
6187 FALSE, "%s", secfile_error());
6188
6189 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6190 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6191 unitstr, nat_x, nat_y);
6192 unit_tile_set(punit, ptile);
6193
6196 "%s.facing", unitstr);
6197 if (facing_str[0] != 'x') {
6198 /* We don't touch punit->facing if savegame does not contain that
6199 * information. Initial orientation set by unit_virtual_create()
6200 * is as good as any. */
6201 enum direction8 facing = char2dir(facing_str[0]);
6202
6203 if (direction8_is_valid(facing)) {
6204 punit->facing = facing;
6205 } else {
6206 log_error("Illegal unit orientation '%s'", facing_str);
6207 }
6208 }
6209
6210 /* If savegame has unit nationality, it doesn't hurt to
6211 * internally set it even if nationality rules are disabled. */
6213 player_number(plr),
6214 "%s.nationality", unitstr);
6215
6217 if (punit->nationality == NULL) {
6218 punit->nationality = plr;
6219 }
6220
6222 "%s.homecity", unitstr), FALSE,
6223 "%s", secfile_error());
6225 "%s.moves", unitstr), FALSE,
6226 "%s", secfile_error());
6228 "%s.fuel", unitstr), FALSE,
6229 "%s", secfile_error());
6230
6232 "%s.activity", unitstr), FALSE,
6233 "%s", secfile_error());
6234 if (ei >= 0 && ei < loading->activities.size) {
6235 activity = unit_activity_by_name(loading->activities.order[ei],
6237 } else {
6238 log_sg("Invalid activity id for unit %d", punit->id);
6239 activity = ACTIVITY_IDLE;
6240 }
6241
6243 "%s.action", unitstr), FALSE,
6244 "%s", secfile_error());
6245 if (ei == -1) {
6247 } else if (ei >= 0 && ei < loading->action.size) {
6248 action = loading->action.order[ei];
6249 } else {
6250 log_sg("Invalid action id for unit %d", punit->id);
6252 }
6253
6256 "%s.born", unitstr);
6259 "%s.current_form_turn", unitstr);
6260
6262 "%s.activity_tgt", unitstr);
6263
6264 if (extra_id != -2) {
6265 if (extra_id >= 0 && extra_id < loading->extra.size) {
6266 pextra = loading->extra.order[extra_id];
6267 set_unit_activity_targeted(punit, activity, pextra, action);
6268 } else if (activity == ACTIVITY_IRRIGATE) {
6272 punit);
6273 if (tgt != NULL) {
6275 } else {
6277 }
6278 } else if (activity == ACTIVITY_MINE) {
6280 EC_MINE,
6282 punit);
6283 if (tgt != NULL) {
6285 } else {
6287 }
6288 } else {
6289 set_unit_activity(punit, activity, action);
6290 }
6291 } else {
6293 } /* activity_tgt == NULL */
6294
6296 "%s.activity_count", unitstr), FALSE,
6297 "%s", secfile_error());
6298
6301 "%s.changed_from", unitstr);
6302
6304 "%s.changed_from_tgt", unitstr), FALSE,
6305 "%s", secfile_error());
6306
6307 if (extra_id >= 0 && extra_id < loading->extra.size) {
6308 punit->changed_from_target = loading->extra.order[extra_id];
6309 } else {
6311 }
6312
6315 "%s.changed_from_count", unitstr);
6316
6317 /* Special case: for a long time, we accidentally incremented
6318 * activity_count while a unit was sentried, so it could increase
6319 * without bound (bug #20641) and be saved in old savefiles.
6320 * We zero it to prevent potential trouble overflowing the range
6321 * in network packets, etc. */
6322 if (activity == ACTIVITY_SENTRY) {
6323 punit->activity_count = 0;
6324 }
6327 }
6328
6329 punit->veteran
6330 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6331 {
6332 /* Protect against change in veteran system in ruleset */
6333 const int levels = utype_veteran_levels(unit_type_get(punit));
6334
6335 if (punit->veteran >= levels) {
6336 fc_assert(levels >= 1);
6337 punit->veteran = levels - 1;
6338 }
6339 }
6342 "%s.done_moving", unitstr);
6345 "%s.battlegroup", unitstr);
6346
6348 "%s.go", unitstr)) {
6349 int gnat_x, gnat_y;
6350
6352 "%s.goto_x", unitstr), FALSE,
6353 "%s", secfile_error());
6355 "%s.goto_y", unitstr), FALSE,
6356 "%s", secfile_error());
6357
6359 } else {
6360 punit->goto_tile = NULL;
6361
6362 if (punit->activity == ACTIVITY_GOTO) {
6363 /* goto_tile should never be NULL with ACTIVITY_GOTO */
6364 sg_regr(3020200, "Unit %d on goto without goto_tile. Aborting goto.",
6365 punit->id);
6367 }
6368
6369 /* These variables are not used but needed for saving the unit table.
6370 * Load them to prevent unused variables errors. */
6371 secfile_entry_ignore(loading->file, "%s.goto_x", unitstr);
6372 secfile_entry_ignore(loading->file, "%s.goto_y", unitstr);
6373 }
6374
6375 /* Load AI data of the unit. */
6376 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6377
6380 "%s.server_side_agent",
6381 unitstr);
6382 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6383 /* Look up what server side agent the unconverted number represents. */
6384 punit->ssa_controller = loading->ssa.order[unconverted];
6385 } else {
6386 log_sg("Invalid server side agent %d for unit %d",
6387 unconverted, punit->id);
6388
6390 }
6391
6393 "%s.hp", unitstr), FALSE,
6394 "%s", secfile_error());
6395
6397 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6399 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6400 punit->moved
6401 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6404 "%s.paradropped", unitstr);
6405 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6406 if (str[0] != '\0') {
6408 }
6409
6410 /* The transport status (punit->transported_by) is loaded in
6411 * sg_player_units_transport(). */
6412
6413 /* Initialize upkeep values: these are hopefully initialized
6414 * elsewhere before use (specifically, in city_support(); but
6415 * fixme: check whether always correctly initialized?).
6416 * Below is mainly for units which don't have homecity --
6417 * otherwise these don't get initialized (and AI calculations
6418 * etc may use junk values). */
6422
6424 "%s.action_decision", unitstr),
6425 FALSE, "%s", secfile_error());
6426
6427 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6428 /* Look up what action decision want the unconverted number
6429 * represents. */
6430 punit->action_decision_want = loading->act_dec.order[unconverted];
6431 } else {
6432 log_sg("Invalid action decision want for unit %d", punit->id);
6433
6435 }
6436
6438 /* Load the tile to act against. */
6439 int adwt_x, adwt_y;
6440
6441 if (secfile_lookup_int(loading->file, &adwt_x,
6442 "%s.action_decision_tile_x", unitstr)
6444 "%s.action_decision_tile_y", unitstr)) {
6446 adwt_x, adwt_y);
6447 } else {
6450 log_sg("Bad action_decision_tile for unit %d", punit->id);
6451 }
6452 } else {
6453 secfile_entry_ignore(loading->file, "%s.action_decision_tile_x", unitstr);
6454 secfile_entry_ignore(loading->file, "%s.action_decision_tile_y", unitstr);
6455
6457 }
6458
6460
6461 /* Load the unit orders */
6462 {
6463 int len = secfile_lookup_int_default(loading->file, 0,
6464 "%s.orders_length", unitstr);
6465
6466 if (len > 0) {
6467 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6468 int j;
6469
6470 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6474 "%s.orders_index", unitstr);
6477 "%s.orders_repeat", unitstr);
6480 "%s.orders_vigilant", unitstr);
6481
6484 "%s.orders_list", unitstr);
6487 "%s.dir_list", unitstr);
6490 "%s.activity_list", unitstr);
6491
6493
6494 for (j = 0; j < len; j++) {
6495 struct unit_order *order = &punit->orders.list[j];
6497 int order_sub_tgt;
6498
6499 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6500 || act_unitstr[j] == '\0') {
6501 log_sg("Invalid unit orders.");
6503 break;
6504 }
6505 order->order = char2order(orders_unitstr[j]);
6506 order->dir = char2dir(dir_unitstr[j]);
6507 order->activity = char2activity(act_unitstr[j]);
6508
6510 "%s.action_vec,%d",
6511 unitstr, j);
6512
6513 if (unconverted == -1) {
6514 order->action = ACTION_NONE;
6515 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6516 /* Look up what action id the unconverted number represents. */
6517 order->action = loading->action.order[unconverted];
6518 } else {
6519 if (order->order == ORDER_PERFORM_ACTION) {
6520 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6521 }
6522
6523 order->action = ACTION_NONE;
6524 }
6525
6526 if (order->order == ORDER_LAST
6527 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6528 || (order->order == ORDER_ACTION_MOVE
6529 && !direction8_is_valid(order->dir))
6530 || (order->order == ORDER_PERFORM_ACTION
6531 && !action_id_exists(order->action))
6532 || (order->order == ORDER_ACTIVITY
6533 && (order->activity == ACTIVITY_LAST
6534 || !action_id_exists(order->action)))) {
6535 /* An invalid order. Just drop the orders for this unit. */
6537 punit->orders.list = NULL;
6538 punit->orders.length = 0;
6540 punit->goto_tile = NULL;
6541 break;
6542 }
6543
6545 "%s.tgt_vec,%d",
6546 unitstr, j);
6548 "%s.sub_tgt_vec,%d",
6549 unitstr, j);
6550
6551 if (order->order == ORDER_PERFORM_ACTION) {
6552 /* Validate sub target */
6553 switch (action_id_get_sub_target_kind(order->action)) {
6554 case ASTK_BUILDING:
6555 /* Sub target is a building. */
6556 if (order_sub_tgt < 0
6557 || order_sub_tgt >= loading->improvement.size
6558 || !loading->improvement.order[order_sub_tgt]) {
6559 /* Sub target is invalid. */
6560 log_sg("Cannot find building %d for %s to %s",
6563 order->sub_target = B_LAST;
6564 } else {
6565 struct impr_type *pimprove
6566 = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
6567
6568 if (pimprove != NULL) {
6569 order->sub_target = improvement_index(pimprove);
6570 }
6571 }
6572 break;
6573 case ASTK_TECH:
6574 /* Sub target is a technology. */
6575 {
6576 bool failure = order_sub_tgt < 0
6577 || order_sub_tgt >= loading->technology.size
6578 || !loading->technology.order[order_sub_tgt];
6579 struct advance *padvance = NULL;
6580
6581 if (!failure) {
6582 padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
6583 }
6584 if (padvance == NULL) {
6585 /* Target tech is invalid. */
6586 log_sg("Cannot find tech %d for %s to steal",
6588 order->sub_target = A_NONE;
6589 } else {
6591 }
6592 }
6593 break;
6594 case ASTK_EXTRA:
6596 /* These take an extra. */
6598 break;
6599 case ASTK_NONE:
6600 /* None of these can take a sub target. */
6602 "Specified sub target for action %d unsupported.",
6603 order->action);
6604 order->sub_target = NO_TARGET;
6605 break;
6606 case ASTK_COUNT:
6608 "Bad action action %d.",
6609 order->action);
6610 order->sub_target = NO_TARGET;
6611 break;
6612 }
6613 }
6614
6615 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6616 enum unit_activity act;
6617
6619 || !loading->extra.order[order_sub_tgt]) {
6620 if (order_sub_tgt != EXTRA_NONE) {
6621 log_sg("Cannot find extra %d for %s to build",
6623 }
6624
6625 order->sub_target = EXTRA_NONE;
6626 } else {
6627 order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
6628 }
6629
6630 /* An action or an activity may require an extra target. */
6631 if (action_wants_extra) {
6632 act = action_id_get_activity(order->action);
6633 } else {
6634 act = order->activity;
6635 }
6636
6637 if (unit_activity_is_valid(act)
6639 && order->sub_target == EXTRA_NONE) {
6640 /* Missing required action extra target. */
6642 punit->orders.list = NULL;
6643 punit->orders.length = 0;
6645 punit->goto_tile = NULL;
6646 break;
6647 }
6648 } else if (order->order != ORDER_PERFORM_ACTION) {
6649 if (order_sub_tgt != -1) {
6650 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6651 order_sub_tgt, -1, order->order);
6652 }
6653 order->sub_target = NO_TARGET;
6654 }
6655 }
6656
6657 for (; j < orders_max_length; j++) {
6659 "%s.action_vec,%d", unitstr, j);
6661 "%s.tgt_vec,%d", unitstr, j);
6663 "%s.sub_tgt_vec,%d", unitstr, j);
6664 }
6665 } else {
6666 int j;
6667
6669
6670 /* Never nullify goto_tile for a unit that is in active goto. */
6671 if (punit->activity != ACTIVITY_GOTO) {
6672 punit->goto_tile = NULL;
6673 }
6674
6675 punit->orders.list = NULL;
6676 punit->orders.length = 0;
6677
6678 secfile_entry_ignore(loading->file, "%s.orders_index", unitstr);
6679 secfile_entry_ignore(loading->file, "%s.orders_repeat", unitstr);
6680 secfile_entry_ignore(loading->file, "%s.orders_vigilant", unitstr);
6681 secfile_entry_ignore(loading->file, "%s.orders_list", unitstr);
6682 secfile_entry_ignore(loading->file, "%s.dir_list", unitstr);
6683 secfile_entry_ignore(loading->file, "%s.activity_list", unitstr);
6684 secfile_entry_ignore(loading->file, "%s.action_vec", unitstr);
6685 secfile_entry_ignore(loading->file, "%s.tgt_vec", unitstr);
6686 secfile_entry_ignore(loading->file, "%s.sub_tgt_vec", unitstr);
6687
6688 for (j = 1; j < orders_max_length; j++) {
6690 "%s.action_vec,%d", unitstr, j);
6692 "%s.tgt_vec,%d", unitstr, j);
6694 "%s.sub_tgt_vec,%d", unitstr, j);
6695 }
6696 }
6697 }
6698
6699 return TRUE;
6700}
6701
6702/************************************************************************/
6707 struct player *plr)
6708{
6709 int nunits, i, plrno = player_number(plr);
6710
6711 /* Check status and return if not OK (sg_success FALSE). */
6712 sg_check_ret();
6713
6714 /* Recheck the number of units for the player. This is a copied from
6715 * sg_load_player_units(). */
6717 "player%d.nunits", plrno),
6718 "%s", secfile_error());
6719 if (!plr->is_alive && nunits > 0) {
6720 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6721 nunits = 0; /* Some old savegames may be buggy. */
6722 }
6723
6724 for (i = 0; i < nunits; i++) {
6725 int id_unit, id_trans;
6726 struct unit *punit, *ptrans;
6727
6729 "player%d.u%d.id",
6730 plrno, i);
6732 fc_assert_action(punit != NULL, continue);
6733
6735 "player%d.u%d.transported_by",
6736 plrno, i);
6737 if (id_trans == -1) {
6738 /* Not transported. */
6739 continue;
6740 }
6741
6743 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6744
6745 if (ptrans) {
6746#ifndef FREECIV_NDEBUG
6747 bool load_success =
6748#endif
6750
6751 fc_assert_action(load_success, continue);
6752 }
6753 }
6754}
6755
6756/************************************************************************/
6760 struct player *plr)
6761{
6762 int i = 0;
6763 int longest_order = 0;
6764 int plrno = player_number(plr);
6765
6766 /* Check status and return if not OK (sg_success FALSE). */
6767 sg_check_ret();
6768
6770 "player%d.nunits", plrno);
6771
6772 /* Find the longest unit order so different order length won't break
6773 * storing units in the tabular format. */
6775 if (punit->has_orders) {
6776 if (longest_order < punit->orders.length) {
6778 }
6779 }
6781
6783 "player%d.orders_max_length", plrno);
6784
6786 char buf[32];
6787 char dirbuf[2] = " ";
6788 int nat_x, nat_y;
6789 int last_order, j;
6790
6791 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6792 dirbuf[0] = dir2char(punit->facing);
6793 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6794
6796 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6797 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6798
6799 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6802 "%s.nationality", buf);
6803 }
6804 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6805 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6806 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6808 "%s.type_by_name", buf);
6809
6810 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6812 "%s.activity_count", buf);
6813 if (punit->action == ACTION_NONE) {
6814 secfile_insert_int(saving->file, -1, "%s.action", buf);
6815 } else {
6816 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6817 }
6818 if (punit->activity_target == NULL) {
6819 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6820 } else {
6822 "%s.activity_tgt", buf);
6823 }
6824
6826 "%s.changed_from", buf);
6828 "%s.changed_from_count", buf);
6829 if (punit->changed_from_target == NULL) {
6830 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6831 } else {
6833 "%s.changed_from_tgt", buf);
6834 }
6835
6837 "%s.done_moving", buf);
6838 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6839 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6841 "%s.born", buf);
6843 "%s.current_form_turn", buf);
6845 "%s.battlegroup", buf);
6846
6847 if (punit->goto_tile) {
6849 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6850 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6851 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6852 } else {
6853 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6854 /* Set this values to allow saving it as table. */
6855 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6856 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6857 }
6858
6860 "%s.server_side_agent", buf);
6861
6862 /* Save AI data of the unit. */
6863 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6864
6866 "%s.ord_map", buf);
6868 "%s.ord_city", buf);
6869 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6871 "%s.paradropped", buf);
6873 ? unit_transport_get(punit)->id : -1,
6874 "%s.transported_by", buf);
6875 if (punit->carrying != NULL) {
6877 "%s.carrying", buf);
6878 } else {
6879 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6880 }
6881
6883 "%s.action_decision", buf);
6884
6885 /* Stored as tile rather than direction to make sure the target tile is
6886 * sane. */
6891 "%s.action_decision_tile_x", buf);
6893 "%s.action_decision_tile_y", buf);
6894 } else {
6895 /* Dummy values to get tabular format. */
6896 secfile_insert_int(saving->file, -1,
6897 "%s.action_decision_tile_x", buf);
6898 secfile_insert_int(saving->file, -1,
6899 "%s.action_decision_tile_y", buf);
6900 }
6901
6903 "%s.stay", buf);
6904
6905 if (punit->has_orders) {
6906 int len = punit->orders.length;
6907 char orders_buf[len + 1], dir_buf[len + 1];
6908 char act_buf[len + 1];
6909 int action_buf[len];
6910 int tgt_vec[len];
6911 int sub_tgt_vec[len];
6912
6913 last_order = len;
6914
6915 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6917 "%s.orders_index", buf);
6919 "%s.orders_repeat", buf);
6921 "%s.orders_vigilant", buf);
6922
6923 for (j = 0; j < len; j++) {
6925 dir_buf[j] = '?';
6926 act_buf[j] = '?';
6927 tgt_vec[j] = NO_TARGET;
6928 sub_tgt_vec[j] = -1;
6929 action_buf[j] = -1;
6930 switch (punit->orders.list[j].order) {
6931 case ORDER_MOVE:
6932 case ORDER_ACTION_MOVE:
6933 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6934 break;
6935 case ORDER_ACTIVITY:
6939 break;
6942 tgt_vec[j] = punit->orders.list[j].target;
6944 break;
6945 case ORDER_FULL_MP:
6946 case ORDER_LAST:
6947 break;
6948 }
6949
6950 if (action_buf[j] == ACTION_NONE) {
6951 action_buf[j] = -1;
6952 }
6953 }
6954 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6955
6956 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6957 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6958 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6959
6961 "%s.action_vec", buf);
6962 /* Fill in dummy values for order targets so the registry will save
6963 * the unit table in a tabular format. */
6964 for (j = last_order; j < longest_order; j++) {
6965 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6966 }
6967
6969 "%s.tgt_vec", buf);
6970 /* Fill in dummy values for order targets so the registry will save
6971 * the unit table in a tabular format. */
6972 for (j = last_order; j < longest_order; j++) {
6973 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6974 }
6975
6977 "%s.sub_tgt_vec", buf);
6978 /* Fill in dummy values for order targets so the registry will save
6979 * the unit table in a tabular format. */
6980 for (j = last_order; j < longest_order; j++) {
6981 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6982 }
6983 } else {
6984
6985 /* Put all the same fields into the savegame - otherwise the
6986 * registry code can't correctly use a tabular format and the
6987 * savegame will be bigger. */
6988 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6989 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6990 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6991 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6992 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6993 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6994 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6995
6996 /* Fill in dummy values for order targets so the registry will save
6997 * the unit table in a tabular format. */
6998
6999 /* The start of a vector has no number. */
7000 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
7001 for (j = 1; j < longest_order; j++) {
7002 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
7003 }
7004
7005 /* The start of a vector has no number. */
7006 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
7007 for (j = 1; j < longest_order; j++) {
7008 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
7009 }
7010
7011 /* The start of a vector has no number. */
7012 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
7013 for (j = 1; j < longest_order; j++) {
7014 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
7015 }
7016 }
7017
7018 i++;
7020}
7021
7022/************************************************************************/
7026 struct player *plr)
7027{
7028 int plrno = player_number(plr);
7029
7030 /* Check status and return if not OK (sg_success FALSE). */
7031 sg_check_ret();
7032
7033 /* Toss any existing attribute_block (should not exist) */
7034 if (plr->attribute_block.data) {
7036 plr->attribute_block.data = NULL;
7037 }
7038
7039 /* This is a big heap of opaque data for the client, check everything! */
7041 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
7042
7043 if (0 > plr->attribute_block.length) {
7044 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
7045 plr->attribute_block.length);
7046 plr->attribute_block.length = 0;
7047 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
7048 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
7050 plr->attribute_block.length = 0;
7051 } else if (0 < plr->attribute_block.length) {
7052 int part_nr, parts;
7053 int quoted_length;
7054 char *quoted;
7055#ifndef FREECIV_NDEBUG
7056 size_t actual_length;
7057#endif
7058
7061 "player%d.attribute_v2_block_length_quoted",
7062 plrno), "%s", secfile_error());
7065 "player%d.attribute_v2_block_parts", plrno),
7066 "%s", secfile_error());
7067
7069 quoted[0] = '\0';
7071 for (part_nr = 0; part_nr < parts; part_nr++) {
7072 const char *current =
7074 "player%d.attribute_v2_block_data.part%d",
7075 plrno, part_nr);
7076 if (!current) {
7077 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7078 break;
7079 }
7080 log_debug("attribute_v2_block_length_quoted=%d"
7081 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7082 quoted_length, strlen(quoted), strlen(current));
7083 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7084 strcat(quoted, current);
7085 }
7087 "attribute_v2_block_length_quoted=%d"
7088 " actual=" SIZE_T_PRINTF,
7090
7091#ifndef FREECIV_NDEBUG
7093#endif
7095 plr->attribute_block.data,
7096 plr->attribute_block.length);
7098 free(quoted);
7099 }
7100}
7101
7102/************************************************************************/
7106 struct player *plr)
7107{
7108 int plrno = player_number(plr);
7109
7110 /* Check status and return if not OK (sg_success FALSE). */
7111 sg_check_ret();
7112
7113 /* This is a big heap of opaque data from the client. Although the binary
7114 * format is not user editable, keep the lines short enough for debugging,
7115 * and hope that data compression will keep the file a reasonable size.
7116 * Note that the "quoted" format is a multiple of 3.
7117 */
7118#define PART_SIZE (3*256)
7119#define PART_ADJUST (3)
7120 if (plr->attribute_block.data) {
7121 char part[PART_SIZE + PART_ADJUST];
7122 int parts;
7123 int current_part_nr;
7125 plr->attribute_block.length);
7126 char *quoted_at = strchr(quoted, ':');
7127 size_t bytes_left = strlen(quoted);
7128 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7130
7132 "player%d.attribute_v2_block_length", plrno);
7134 "player%d.attribute_v2_block_length_quoted", plrno);
7135
7136 /* Try to wring some compression efficiencies out of the "quoted" format.
7137 * The first line has a variable length decimal, mis-aligning triples.
7138 */
7139 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7140 /* first line can be longer */
7141 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7142 } else {
7143 parts = 1;
7144 }
7145
7147 "player%d.attribute_v2_block_parts", plrno);
7148
7149 if (parts > 1) {
7151
7152 /* first line can be longer */
7154 part[size_of_current_part] = '\0';
7156 "player%d.attribute_v2_block_data.part%d",
7157 plrno, 0);
7160 current_part_nr = 1;
7161 } else {
7162 quoted_at = quoted;
7163 current_part_nr = 0;
7164 }
7165
7168
7170 part[size_of_current_part] = '\0';
7172 "player%d.attribute_v2_block_data.part%d",
7173 plrno,
7177 }
7178 fc_assert(bytes_left == 0);
7179 free(quoted);
7180 }
7181#undef PART_ADJUST
7182#undef PART_SIZE
7183}
7184
7185/************************************************************************/
7189 struct player *plr)
7190{
7191 int plrno = player_number(plr);
7192 int total_ncities
7194 "player%d.dc_total", plrno);
7195 int i;
7196 bool someone_alive = FALSE;
7197
7198 /* Check status and return if not OK (sg_success FALSE). */
7199 sg_check_ret();
7200
7203 if (pteam_member->is_alive) {
7205 break;
7206 }
7208
7209 if (!someone_alive) {
7210 /* Reveal all for completely dead teams. */
7212 }
7213 }
7214
7215 if (-1 == total_ncities
7216 || !game.info.fogofwar
7218 "game.save_private_map")) {
7219 /* We have:
7220 * - a dead player;
7221 * - fogged cities are not saved for any reason;
7222 * - a savegame with fog of war turned off;
7223 * - or game.save_private_map is not set to FALSE in the scenario /
7224 * savegame. The players private knowledge is set to be what they could
7225 * see without fog of war. */
7226 whole_map_iterate(&(wld.map), ptile) {
7227 if (map_is_known(ptile, plr)) {
7228 struct city *pcity = tile_city(ptile);
7229
7230 update_player_tile_last_seen(plr, ptile);
7231 update_player_tile_knowledge(plr, ptile);
7232
7233 if (NULL != pcity) {
7234 update_dumb_city(plr, pcity);
7235 }
7236 }
7238
7239 /* Nothing more to do; */
7240 return;
7241 }
7242
7243 /* Load player map (terrain). */
7244 LOAD_MAP_CHAR(ch, ptile,
7245 map_get_player_tile(ptile, plr)->terrain
7246 = char2terrain(ch), loading->file,
7247 "player%d.map_t%04d", plrno);
7248
7249 /* Load player map (extras). */
7250 halfbyte_iterate_extras(j, loading->extra.size) {
7251 LOAD_MAP_CHAR(ch, ptile,
7253 ch, loading->extra.order + 4 * j),
7254 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7256
7257 whole_map_iterate(&(wld.map), ptile) {
7258 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7259 bool regr_warn = FALSE;
7260
7262 int pres_id = extra_number(pres);
7263
7264 if (BV_ISSET(plrtile->extras, pres_id)) {
7265 if (plrtile->terrain == nullptr) {
7266 if (!regr_warn) {
7267 sg_regr(3030000, "FoW tile (%d, %d) has extras, though it's on unknown.",
7268 TILE_XY(ptile));
7269 regr_warn = TRUE;
7270 }
7271 BV_CLR(plrtile->extras, pres_id);
7272 } else {
7273 plrtile->resource = pres;
7274 if (!terrain_has_resource(plrtile->terrain, pres)) {
7275 BV_CLR(plrtile->extras, pres_id);
7276 }
7277 }
7278 }
7281
7283 /* Load player map (border). */
7284 int x, y;
7285
7286 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7287 const char *buffer
7288 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7289 plrno, y);
7290 const char *buffer2
7291 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7292 plrno, y);
7293 const char *ptr = buffer;
7294 const char *ptr2 = buffer2;
7295
7296 sg_failure_ret(NULL != buffer,
7297 "Savegame corrupt - map line %d not found.", y);
7298 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7299 char token[TOKEN_SIZE];
7300 char token2[TOKEN_SIZE];
7301 int number;
7302 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7303
7304 scanin(&ptr, ",", token, sizeof(token));
7305 sg_failure_ret('\0' != token[0],
7306 "Savegame corrupt - map size not correct.");
7307 if (strcmp(token, "-") == 0) {
7308 map_get_player_tile(ptile, plr)->owner = NULL;
7309 } else {
7310 sg_failure_ret(str_to_int(token, &number),
7311 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7312 token, x, y);
7313 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7314 }
7315
7316 scanin(&ptr2, ",", token2, sizeof(token2));
7317 sg_failure_ret('\0' != token2[0],
7318 "Savegame corrupt - map size not correct.");
7319 if (strcmp(token2, "-") == 0) {
7320 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7321 } else {
7323 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7324 token, x, y);
7325 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7326 }
7327 }
7328 }
7329 }
7330
7331 /* Load player map (update time). */
7332 for (i = 0; i < 4; i++) {
7333 /* put 4-bit segments of 16-bit "updated" field */
7334 if (i == 0) {
7335 LOAD_MAP_CHAR(ch, ptile,
7336 map_get_player_tile(ptile, plr)->last_updated
7337 = ascii_hex2bin(ch, i),
7338 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7339 } else {
7340 LOAD_MAP_CHAR(ch, ptile,
7341 map_get_player_tile(ptile, plr)->last_updated
7342 |= ascii_hex2bin(ch, i),
7343 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7344 }
7345 }
7346
7347 /* Load player map known cities. */
7348 for (i = 0; i < total_ncities; i++) {
7349 struct vision_site *pdcity;
7350 char buf[32];
7351 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7352
7356 pdcity);
7358 } else {
7359 /* Error loading the data. */
7360 log_sg("Skipping seen city %d for player %d.", i, plrno);
7361 if (pdcity != NULL) {
7363 }
7364 }
7365 }
7366
7367 /* Repair inconsistent player maps. */
7368 whole_map_iterate(&(wld.map), ptile) {
7369 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7370 struct city *pcity = tile_city(ptile);
7371
7372 update_player_tile_knowledge(plr, ptile);
7373 reality_check_city(plr, ptile);
7374
7375 if (NULL != pcity) {
7376 update_dumb_city(plr, pcity);
7377 }
7378 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7379 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7380 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7381
7382 plrtile->owner = tile_owner(ptile);
7383 }
7385}
7386
7387/************************************************************************/
7391 struct player *plr,
7392 struct vision_site *pdcity,
7393 const char *citystr)
7394{
7395 const char *str;
7396 int i, id, size;
7397 citizens city_size;
7398 int nat_x, nat_y;
7399 const char *stylename;
7400 enum capital_type cap;
7401 const char *vname;
7402
7404 citystr),
7405 FALSE, "%s", secfile_error());
7407 citystr),
7408 FALSE, "%s", secfile_error());
7409 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7410 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7411 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7412
7413 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7414 citystr),
7415 FALSE, "%s", secfile_error());
7416 pdcity->owner = player_by_number(id);
7417 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7418 "%s has invalid owner (%d); skipping.", citystr, id);
7419
7420 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7421 citystr),
7422 FALSE, "%s", secfile_error());
7423 if (id >= 0) {
7424 pdcity->original = player_by_number(id);
7425 sg_warn_ret_val(NULL != pdcity->original, FALSE,
7426 "%s has invalid original owner (%d); skipping.", citystr, id);
7427 } else {
7428 pdcity->original = nullptr;
7429 }
7430
7432 "%s.id", citystr),
7433 FALSE, "%s", secfile_error());
7435 "%s has invalid id (%d); skipping.", citystr, id);
7436
7438 "%s.size", citystr),
7439 FALSE, "%s", secfile_error());
7440 city_size = (citizens)size; /* set the correct type */
7441 sg_warn_ret_val(size == (int)city_size, FALSE,
7442 "Invalid city size: %d; set to %d.", size, city_size);
7443 vision_site_size_set(pdcity, city_size);
7444
7445 /* Initialise list of improvements */
7446 BV_CLR_ALL(pdcity->improvements);
7447 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7449 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7450 "Invalid length of '%s.improvements' ("
7451 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7452 citystr, strlen(str), loading->improvement.size);
7453 for (i = 0; i < loading->improvement.size; i++) {
7454 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7455 "Undefined value '%c' within '%s.improvements'.",
7456 str[i], citystr)
7457
7458 if (str[i] == '1') {
7459 struct impr_type *pimprove =
7460 improvement_by_rule_name(loading->improvement.order[i]);
7461 if (pimprove) {
7462 BV_SET(pdcity->improvements, improvement_index(pimprove));
7463 }
7464 }
7465 }
7466
7468 "%s.name", citystr);
7469
7470 if (vname != NULL) {
7471 pdcity->name = fc_strdup(vname);
7472 }
7473
7475 "%s.occupied", citystr);
7477 "%s.walls", citystr);
7479 "%s.happy", citystr);
7481 "%s.unhappy", citystr);
7483 "%s.style", citystr);
7484 if (stylename != NULL) {
7486 } else {
7487 pdcity->style = 0;
7488 }
7489 if (pdcity->style < 0) {
7490 pdcity->style = 0;
7491 }
7492
7493 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7494 "%s.city_image", citystr);
7495
7497 "%s.capital", citystr),
7499
7501 pdcity->capital = cap;
7502 } else {
7503 pdcity->capital = CAPITAL_NOT;
7504 }
7505
7506 return TRUE;
7507}
7508
7509/************************************************************************/
7513 struct player *plr)
7514{
7515 int i, plrno = player_number(plr);
7516
7517 /* Check status and return if not OK (sg_success FALSE). */
7518 sg_check_ret();
7519
7521 /* The player can see all, there's no reason to save the private map. */
7522 return;
7523 }
7524
7525 /* Save the map (terrain). */
7526 SAVE_MAP_CHAR(ptile,
7528 saving->file, "player%d.map_t%04d", plrno);
7529
7531 /* Save the map (borders). */
7532 int x, y;
7533
7534 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7536
7537 line[0] = '\0';
7538 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7539 char token[TOKEN_SIZE];
7540 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7541 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7542
7543 if (plrtile == NULL || plrtile->owner == NULL) {
7544 strcpy(token, "-");
7545 } else {
7546 fc_snprintf(token, sizeof(token), "%d",
7547 player_number(plrtile->owner));
7548 }
7549 strcat(line, token);
7550 if (x < MAP_NATIVE_WIDTH) {
7551 strcat(line, ",");
7552 }
7553 }
7554 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7555 plrno, y);
7556 }
7557
7558 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7560
7561 line[0] = '\0';
7562 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7563 char token[TOKEN_SIZE];
7564 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7565 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7566
7567 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7568 strcpy(token, "-");
7569 } else {
7570 fc_snprintf(token, sizeof(token), "%d",
7571 player_number(plrtile->extras_owner));
7572 }
7573 strcat(line, token);
7574 if (x < MAP_NATIVE_WIDTH) {
7575 strcat(line, ",");
7576 }
7577 }
7578 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7579 plrno, y);
7580 }
7581 }
7582
7583 /* Save the map (extras). */
7585 int mod[4];
7586 int l;
7587
7588 for (l = 0; l < 4; l++) {
7589 if (4 * j + 1 > game.control.num_extra_types) {
7590 mod[l] = -1;
7591 } else {
7592 mod[l] = 4 * j + l;
7593 }
7594 }
7595
7596 SAVE_MAP_CHAR(ptile,
7598 map_get_player_tile(ptile, plr)->resource,
7599 mod),
7600 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7602
7603 /* Save the map (update time). */
7604 for (i = 0; i < 4; i++) {
7605 /* put 4-bit segments of 16-bit "updated" field */
7606 SAVE_MAP_CHAR(ptile,
7608 map_get_player_tile(ptile, plr)->last_updated, i),
7609 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7610 }
7611
7612 /* Save known cities. */
7613 i = 0;
7614 whole_map_iterate(&(wld.map), ptile) {
7615 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7616 char impr_buf[B_LAST + 1];
7617 char buf[32];
7618
7619 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7620
7621 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7622 int nat_x, nat_y;
7623
7625 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7626 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7627
7628 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7630 "%s.owner", buf);
7631 if (pdcity->original != nullptr) {
7633 "%s.original", buf);
7634 } else {
7635 secfile_insert_int(saving->file, -1, "%s.original", buf);
7636 }
7637
7639 "%s.size", buf);
7640 secfile_insert_bool(saving->file, pdcity->occupied,
7641 "%s.occupied", buf);
7642 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7643 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7644 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7646 "%s.style", buf);
7647 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7649 "%s.capital", buf);
7650
7651 /* Save improvement list as bitvector. Note that improvement order
7652 * is saved in savefile.improvement.order. */
7653 improvement_iterate(pimprove) {
7654 impr_buf[improvement_index(pimprove)]
7655 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7656 ? '1' : '0';
7658 impr_buf[improvement_count()] = '\0';
7660 "Invalid size of the improvement vector (%s.improvements: "
7661 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7662 buf, strlen(impr_buf), sizeof(impr_buf));
7663 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7664 if (pdcity->name != NULL) {
7665 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7666 }
7667
7668 i++;
7669 }
7671
7672 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7673}
7674
7675/* =======================================================================
7676 * Load / save the researches.
7677 * ======================================================================= */
7678
7679/************************************************************************/
7683{
7684 struct research *presearch;
7685 int count;
7686 int number;
7687 const char *str;
7688 int i, j;
7689 int *vlist_research;
7690
7692 /* Check status and return if not OK (sg_success FALSE). */
7693 sg_check_ret();
7694
7695 /* Initialize all researches. */
7699
7700 /* May be unsaved (e.g. scenario case). */
7701 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7702 for (i = 0; i < count; i++) {
7704 "research.r%d.number", i),
7705 "%s", secfile_error());
7706 presearch = research_by_number(number);
7708 "Invalid research number %d in 'research.r%d.number'",
7709 number, i);
7710
7711 presearch->tech_goal = technology_load(loading->file,
7712 "research.r%d.goal", i);
7714 &presearch->future_tech,
7715 "research.r%d.futuretech", i),
7716 "%s", secfile_error());
7718 &presearch->bulbs_researched,
7719 "research.r%d.bulbs", i),
7720 "%s", secfile_error());
7722 &presearch->bulbs_researching_saved,
7723 "research.r%d.bulbs_before", i),
7724 "%s", secfile_error());
7725 presearch->researching_saved = technology_load(loading->file,
7726 "research.r%d.saved", i);
7727 presearch->researching = technology_load(loading->file,
7728 "research.r%d.now", i);
7730 &presearch->free_bulbs,
7731 "research.r%d.free_bulbs", i),
7732 "%s", secfile_error());
7733
7734 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7735 sg_failure_ret(str != NULL, "%s", secfile_error());
7736 sg_failure_ret(strlen(str) == loading->technology.size,
7737 "Invalid length of 'research.r%d.done' ("
7738 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7739 i, strlen(str), loading->technology.size);
7740 for (j = 0; j < loading->technology.size; j++) {
7741 sg_failure_ret(str[j] == '1' || str[j] == '0',
7742 "Undefined value '%c' within 'research.r%d.done'.",
7743 str[j], i);
7744
7745 if (str[j] == '1') {
7746 struct advance *padvance
7747 = advance_by_rule_name(loading->technology.order[j]);
7748
7749 if (padvance) {
7751 TECH_KNOWN);
7752 }
7753 }
7754 }
7755
7757 size_t count_res;
7758 int tn;
7759
7761 "research.r%d.vbs", i);
7762
7763 for (tn = 0; tn < count_res; tn++) {
7764 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7765
7766 if (padvance != NULL) {
7767 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7768 = vlist_research[tn];
7769 }
7770 }
7771 }
7772 }
7773
7774 /* In case of tech_leakage, we can update research only after all the
7775 * researches have been loaded */
7779}
7780
7781/************************************************************************/
7785{
7786 char invs[A_LAST];
7787 int i = 0;
7788 int *vlist_research;
7789
7791 /* Check status and return if not OK (sg_success FALSE). */
7792 sg_check_ret();
7793
7794 if (saving->save_players) {
7797 "research.r%d.number", i);
7798 technology_save(saving->file, "research.r%d.goal",
7799 i, presearch->tech_goal);
7800 secfile_insert_int(saving->file, presearch->future_tech,
7801 "research.r%d.futuretech", i);
7802 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7803 "research.r%d.bulbs_before", i);
7807 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7811 "research.r%d.vbs", i);
7812 if (vlist_research) {
7814 }
7815 }
7816 technology_save(saving->file, "research.r%d.saved",
7817 i, presearch->researching_saved);
7818 secfile_insert_int(saving->file, presearch->bulbs_researched,
7819 "research.r%d.bulbs", i);
7820 technology_save(saving->file, "research.r%d.now",
7821 i, presearch->researching);
7822 secfile_insert_int(saving->file, presearch->free_bulbs,
7823 "research.r%d.free_bulbs", i);
7824 /* Save technology lists as bytevector. Note that technology order is
7825 * saved in savefile.technology.order */
7826 advance_index_iterate(A_NONE, tech_id) {
7827 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7829 == TECH_KNOWN ? '1' : '0');
7832 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7833 i++;
7835 secfile_insert_int(saving->file, i, "research.count");
7836 }
7837}
7838
7839/* =======================================================================
7840 * Load / save the event cache. Should be the last thing to do.
7841 * ======================================================================= */
7842
7843/************************************************************************/
7847{
7848 /* Check status and return if not OK (sg_success FALSE). */
7849 sg_check_ret();
7850
7851 event_cache_load(loading->file, "event_cache");
7852}
7853
7854/************************************************************************/
7858{
7859 /* Check status and return if not OK (sg_success FALSE). */
7860 sg_check_ret();
7861
7862 if (saving->scenario) {
7863 /* Do _not_ save events in a scenario. */
7864 return;
7865 }
7866
7867 event_cache_save(saving->file, "event_cache");
7868}
7869
7870/* =======================================================================
7871 * Load / save the open treaties
7872 * ======================================================================= */
7873
7874/************************************************************************/
7878{
7879 int tidx;
7880 const char *plr0;
7881
7882 /* Check status and return if not OK (sg_success FALSE). */
7883 sg_check_ret();
7884
7885 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7886 "treaty%d.plr0", tidx)) != NULL ;
7887 tidx++) {
7888 const char *plr1;
7889 const char *ct;
7890 int cidx;
7891 struct player *p0, *p1;
7892
7893 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7894
7895 p0 = player_by_name(plr0);
7896 p1 = player_by_name(plr1);
7897
7898 if (p0 == NULL || p1 == NULL) {
7899 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7900 } else {
7901 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7902
7905
7906 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7907 "treaty%d.clause%d.type",
7908 tidx, cidx)) != NULL ;
7909 cidx++ ) {
7911 const char *plrx;
7912
7913 if (!clause_type_is_valid(type)) {
7914 log_error("Invalid clause type \"%s\"", ct);
7915 } else {
7916 struct player *pgiver = NULL;
7917
7918 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7919 tidx, cidx);
7920
7921 if (!fc_strcasecmp(plrx, plr0)) {
7922 pgiver = p0;
7923 } else if (!fc_strcasecmp(plrx, plr1)) {
7924 pgiver = p1;
7925 } else {
7926 log_error("Clause giver %s is not participant of the treaty"
7927 "between %s and %s", plrx, plr0, plr1);
7928 }
7929
7930 if (pgiver != NULL) {
7931 int value;
7932
7933 value = secfile_lookup_int_default(loading->file, 0,
7934 "treaty%d.clause%d.value",
7935 tidx, cidx);
7936
7937 add_clause(ptreaty, pgiver, type, value, NULL);
7938 }
7939 }
7940 }
7941
7942 /* These must be after clauses have been added so that acceptance
7943 * does not get cleared by what seems like changes to the treaty. */
7945 "treaty%d.accept0", tidx);
7947 "treaty%d.accept1", tidx);
7948 }
7949 }
7950}
7951
7952typedef struct {
7953 int tidx;
7956
7957/************************************************************************/
7960static void treaty_save(struct treaty *ptr, void *data_in)
7961{
7962 char tpath[512];
7963 int cidx = 0;
7965
7966 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7967
7968 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7969 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7970 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7971 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7972
7974 char cpath[512];
7975
7976 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7977
7978 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7979 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7980 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7982}
7983
7984/************************************************************************/
7988{
7989 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7990
7992}
7993
7994/* =======================================================================
7995 * Load / save the history report
7996 * ======================================================================= */
7997
7998/************************************************************************/
8002{
8004 int turn;
8005
8006 /* Check status and return if not OK (sg_success FALSE). */
8007 sg_check_ret();
8008
8009 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
8010
8011 if (turn != -2) {
8012 hist->turn = turn;
8013 }
8014
8015 if (turn + 1 >= game.info.turn) {
8016 const char *str;
8017
8018 str = secfile_lookup_str(loading->file, "history.title");
8019 sg_failure_ret(str != NULL, "%s", secfile_error());
8020 sz_strlcpy(hist->title, str);
8021 str = secfile_lookup_str(loading->file, "history.body");
8022 sg_failure_ret(str != NULL, "%s", secfile_error());
8023 sz_strlcpy(hist->body, str);
8024 }
8025}
8026
8027/************************************************************************/
8030static void sg_save_history(struct savedata *saving)
8031{
8033
8034 secfile_insert_int(saving->file, hist->turn, "history.turn");
8035
8036 if (hist->turn + 1 >= game.info.turn) {
8037 secfile_insert_str(saving->file, hist->title, "history.title");
8038 secfile_insert_str(saving->file, hist->body, "history.body");
8039 }
8040}
8041
8042/* =======================================================================
8043 * Load / save the mapimg definitions.
8044 * ======================================================================= */
8045
8046/************************************************************************/
8049static void sg_load_mapimg(struct loaddata *loading)
8050{
8051 int mapdef_count, i;
8052
8053 /* Check status and return if not OK (sg_success FALSE). */
8054 sg_check_ret();
8055
8056 /* Clear all defined map images. */
8057 while (mapimg_count() > 0) {
8058 mapimg_delete(0);
8059 }
8060
8062 "mapimg.count");
8063 log_verbose("Saved map image definitions: %d.", mapdef_count);
8064
8065 if (0 >= mapdef_count) {
8066 return;
8067 }
8068
8069 for (i = 0; i < mapdef_count; i++) {
8070 const char *p;
8071
8072 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
8073 if (NULL == p) {
8074 log_verbose("[Mapimg %4d] Missing definition.", i);
8075 continue;
8076 }
8077
8078 if (!mapimg_define(p, FALSE)) {
8079 log_error("Invalid map image definition %4d: %s.", i, p);
8080 }
8081
8082 log_verbose("Mapimg %4d loaded.", i);
8083 }
8084}
8085
8086/************************************************************************/
8089static void sg_save_mapimg(struct savedata *saving)
8090{
8091 /* Check status and return if not OK (sg_success FALSE). */
8092 sg_check_ret();
8093
8094 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8095 if (mapimg_count() > 0) {
8096 int i;
8097
8098 for (i = 0; i < mapimg_count(); i++) {
8099 char buf[MAX_LEN_MAPDEF];
8100
8101 mapimg_id2str(i, buf, sizeof(buf));
8102 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8103 }
8104 }
8105}
8106
8107/* =======================================================================
8108 * Sanity checks for loading / saving a game.
8109 * ======================================================================= */
8110
8111/************************************************************************/
8115{
8116 int players;
8117
8118 /* Check status and return if not OK (sg_success FALSE). */
8119 sg_check_ret();
8120
8121 if (game.info.is_new_game) {
8122 /* Nothing to do for new games (or not started scenarios). */
8123 return;
8124 }
8125
8126 /* Old savegames may have maxplayers lower than current player count,
8127 * fix. */
8128 players = normal_player_count();
8129 if (game.server.max_players < players) {
8130 log_verbose("Max players lower than current players, fixing");
8131 game.server.max_players = players;
8132 }
8133
8134 /* Fix ferrying sanity */
8135 players_iterate(pplayer) {
8136 unit_list_iterate_safe(pplayer->units, punit) {
8139 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8145 }
8148
8149 /* Fix stacking issues. We don't rely on the savegame preserving
8150 * alliance invariants (old savegames often did not) so if there are any
8151 * unallied units on the same tile we just bounce them. */
8152 players_iterate(pplayer) {
8154 resolve_unit_stacks(pplayer, aplayer, TRUE);
8157
8158 /* Recalculate the potential buildings for each city. Has caused some
8159 * problems with game random state.
8160 * This also changes the game state if you save the game directly after
8161 * loading it and compare the results. */
8162 players_iterate(pplayer) {
8163 /* Building advisor needs data phase open in order to work */
8164 adv_data_phase_init(pplayer, FALSE);
8165 building_advisor(pplayer);
8166 /* Close data phase again so it can be opened again when game starts. */
8167 adv_data_phase_done(pplayer);
8169
8170 /* Prevent a buggy or intentionally crafted save game from crashing
8171 * Freeciv. See hrm Bug #887748 */
8172 players_iterate(pplayer) {
8173 city_list_iterate(pplayer->cities, pcity) {
8174 worker_task_list_iterate(pcity->task_reqs, ptask) {
8175 if (!worker_task_is_sane(ptask)) {
8176 log_error("[city id: %d] Bad worker task %d.",
8177 pcity->id, ptask->act);
8178 worker_task_list_remove(pcity->task_reqs, ptask);
8179 free(ptask);
8180 ptask = NULL;
8181 }
8185
8186 /* Check worked tiles map */
8187#ifdef FREECIV_DEBUG
8188 if (loading->worked_tiles != NULL) {
8189 /* Check the entire map for unused worked tiles */
8190 whole_map_iterate(&(wld.map), ptile) {
8191 if (loading->worked_tiles[ptile->index] != -1) {
8192 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8193 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8194 }
8196 }
8197#endif /* FREECIV_DEBUG */
8198
8199 /* Check researching technologies and goals. */
8201 if (presearch->researching != A_UNSET
8202 && !is_future_tech(presearch->researching)
8203 && (valid_advance_by_number(presearch->researching) == NULL
8205 != TECH_PREREQS_KNOWN))) {
8206 log_sg(_("%s had invalid researching technology."),
8208 presearch->researching = A_UNSET;
8209 }
8210 if (presearch->tech_goal != A_UNSET
8211 && !is_future_tech(presearch->tech_goal)
8212 && (valid_advance_by_number(presearch->tech_goal) == NULL
8215 == TECH_KNOWN))) {
8216 log_sg(_("%s had invalid technology goal."),
8218 presearch->tech_goal = A_UNSET;
8219 }
8220
8223
8224 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8225 players_iterate(pplayer) {
8226 int unique_count[U_LAST];
8227
8228 memset(unique_count, 0, sizeof(unique_count));
8229
8230 unit_list_iterate(pplayer->units, punit) {
8233
8236 log_sg(_("%s has multiple units of type %s though it should be possible "
8237 "to have only one."),
8239 }
8242
8243 players_iterate(pplayer) {
8244 unit_list_iterate_safe(pplayer->units, punit) {
8245 if (punit->has_orders
8247 punit->orders.list)) {
8248 log_sg("Invalid unit orders for unit %d.", punit->id);
8250 }
8253
8254 /* Check max rates (rules may have changed since saving) */
8255 players_iterate(pplayer) {
8258
8259 /* Check initial city sanity */
8260 players_iterate(pplayer) {
8261 if (!player_has_flag(pplayer, PLRF_FIRST_CITY)
8262 && city_list_size(pplayer->cities) > 0) {
8263 log_sg(_("%s inconsistency: Has never had their first city, "
8264 "but has cities this very moment. Fixing."),
8265 player_name(pplayer));
8266 BV_SET(pplayer->flags, PLRF_FIRST_CITY);
8267 }
8269
8270 if (0 == strlen(server.game_identifier)
8271 || !is_base64url(server.game_identifier)) {
8272 /* This uses fc_rand(), so random state has to be initialized before. */
8273 randomize_base64url_string(server.game_identifier,
8274 sizeof(server.game_identifier));
8275 }
8276
8277 /* Restore game random state, just in case various initialization code
8278 * inexplicably altered the previously existing state. */
8279 if (!game.info.is_new_game) {
8280 fc_rand_set_state(loading->rstate);
8281 }
8282
8283 /* At the end do the default sanity checks. */
8284 sanity_check();
8285}
8286
8287/************************************************************************/
8291{
8292 /* Check status and return if not OK (sg_success FALSE). */
8293 sg_check_ret();
8294}
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:56
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1239
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:421
#define NUM_ACTIONS
Definition actions.h:63
#define action_id_get_activity(act_id)
Definition actions.h:466
#define ACTION_NONE
Definition actions.h:59
void building_advisor(struct player *pplayer)
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:270
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:573
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
int ai_type_get_count(void)
Definition ai.c:327
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define ai_type_iterate_end
Definition ai.h:372
#define ai_type_iterate(NAME_ai)
Definition ai.h:365
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
#define str
Definition astring.c:76
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:142
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:174
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
void citizens_init(struct city *pcity)
Definition citizens.c:32
void citizens_update(struct city *pcity, struct player *plr)
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:148
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c:1145
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
const char * city_style_rule_name(const int style)
Definition city.c:1765
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3469
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2884
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1180
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3396
void destroy_city_virtual(struct city *pcity)
Definition city.c:3555
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:514
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define cities_iterate(pcity)
Definition city.h:509
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:83
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define output_type_iterate(output)
Definition city.h:842
#define FREE_WORKED_TILES
Definition city.h:879
#define MAX_CITY_SIZE
Definition city.h:103
#define city_list_iterate_end
Definition city.h:507
#define I_NEVER
Definition city.h:244
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define output_type_iterate_end
Definition city.h:848
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2779
bool send_city_suppression(bool now)
Definition citytools.c:2170
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:136
void city_thaw_workers(struct city *pcity)
Definition citytools.c:146
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2850
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3454
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:366
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:851
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
char * incite_cost
Definition comments.c:76
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
int counter_index(const struct counter *pcount)
Definition counters.c:174
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
int counters_get_city_counters_count(void)
Definition counters.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:108
struct treaty * ptreaty
Definition diplodlg_g.h:28
void treaty_add(struct treaty *ptreaty)
Definition diptreaty.c:377
void init_treaty(struct treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
bool add_clause(struct treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
#define clause_list_iterate_end
Definition diptreaty.h:73
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:71
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1128
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h:214
int Tech_type_id
Definition fc_types.h:237
unsigned char citizens
Definition fc_types.h:248
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
@ CTGT_CITY
Definition fc_types.h:127
#define MAX_LEN_NAME
Definition fc_types.h:67
@ O_LAST
Definition fc_types.h:102
int Multiplier_type_id
Definition fc_types.h:246
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:93
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct unit * game_unit_by_number(int id)
Definition game.c:115
void initialize_globals(void)
Definition game.c:688
struct city * game_city_by_number(int id)
Definition game.c:106
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:603
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:602
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:605
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:604
#define GAME_DEFAULT_RULESETDIR
Definition game.h:681
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:607
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:622
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
struct government * government_by_rule_name(const char *name)
Definition government.c:55
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
const char * improvement_rule_name(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
struct impr_type * improvement_by_rule_name(const char *name)
Impr_type_id improvement_count(void)
#define improvement_iterate_end
#define WONDER_DESTROYED
#define improvement_iterate(_p)
#define WONDER_LOST
#define B_LAST
Definition improvement.h:42
void adv_city_free(struct city *pcity)
Definition infracache.c:502
void adv_city_alloc(struct city *pcity)
Definition infracache.c:489
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_fatal(message,...)
Definition log.h:101
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1813
#define nat_x
#define nat_y
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:2030
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1829
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1852
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1925
void map_init_topology(struct civ_map *nmap)
Definition map.c:315
void main_map_allocate(void)
Definition map.c:534
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
int map_startpos_count(void)
Definition map.c:2017
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1912
bool map_is_empty(void)
Definition map.c:148
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1796
#define map_startpos_iterate(NAME_psp)
Definition map.h:136
#define map_startpos_iterate_end
Definition map.h:139
#define whole_map_iterate(_map, _tile)
Definition map.h:582
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define whole_map_iterate_end
Definition map.h:591
map_generator
Definition map_types.h:46
@ MAPGEN_SCENARIO
Definition map_types.h:47
void assign_continent_numbers(void)
void player_map_init(struct player *pplayer)
Definition maphand.c:1226
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1472
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2171
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:899
bool send_tile_suppression(bool now)
Definition maphand.c:473
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:343
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1201
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1403
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1372
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1183
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1164
void map_calculate_borders(void)
Definition maphand.c:2329
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1637
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1314
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
bool mapimg_delete(int id)
Definition mapimg.c:1207
int mapimg_count(void)
Definition mapimg.c:573
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
void set_meta_patches_string(const char *string)
Definition meta.c:172
char * meta_addr_port(void)
Definition meta.c:203
const char * default_meta_patches_string(void)
Definition meta.c:83
const char * get_meta_patches_string(void)
Definition meta.c:107
#define DEFAULT_META_SERVER_ADDR
Definition meta.h:21
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
const char * multiplier_rule_name(const struct multiplier *pmul)
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
struct multiplier * multiplier_by_rule_name(const char *name)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
static struct nation_type * nations
Definition nation.c:46
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nation_hash_iterate_end
Definition nation.h:95
#define NO_NATION_SELECTED
Definition nation.h:30
void event_cache_load(struct section_file *file, const char *section)
Definition notify.c:783
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:903
int parts
Definition packhand.c:132
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1480
int player_count(void)
Definition player.c:817
int player_slot_count(void)
Definition player.c:418
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:463
int player_number(const struct player *pplayer)
Definition player.c:837
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:159
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_max_used_number(void)
Definition player.c:476
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
struct player * player_by_name(const char *name)
Definition player.c:881
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:240
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
int player_index(const struct player *pplayer)
Definition player.c:829
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:861
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player_slot * slots
Definition player.c:51
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1497
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1489
#define players_iterate_end
Definition player.h:542
dipl_reason
Definition player.h:192
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:194
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:194
#define players_iterate(_pplayer)
Definition player.h:537
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:223
#define player_list_iterate(playerlist, pplayer)
Definition player.h:560
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define player_slots_iterate(_pslot)
Definition player.h:528
#define is_ai(plr)
Definition player.h:232
#define player_list_iterate_end
Definition player.h:562
#define players_iterate_alive_end
Definition player.h:552
#define player_slots_iterate_end
Definition player.h:532
#define players_iterate_alive(_pplayer)
Definition player.h:547
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2270
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1896
int normal_player_count(void)
Definition plrhand.c:3217
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2059
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2466
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2416
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3263
void shuffle_players(void)
Definition plrhand.c:2391
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1945
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1620
void assign_player_colors(void)
Definition plrhand.c:1736
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3250
void fit_nationset_to_players(void)
Definition plrhand.c:2672
#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,...)
bool entry_str_set_gt_marking(struct entry *pentry, bool gt_marking)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
float secfile_lookup_float_default(const struct section_file *secfile, float def, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
#define secfile_insert_int_vec(secfile, values, dim, path,...)
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define secfile_entry_ignore_by_path(_sfile_, _path_)
#define secfile_insert_float(secfile, value, path,...)
struct history_report * history_report_get(void)
Definition report.c:1859
const char * universal_rule_name(const struct universal *psource)
const char * universal_type_rule_name(const struct universal *psource)
struct universal universal_by_rule_name(const char *kind, const char *value)
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:668
const char * research_name_translation(const struct research *presearch)
Definition research.c:156
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:637
struct research * research_by_number(int number)
Definition research.c:118
int research_number(const struct research *presearch)
Definition research.c:109
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1353
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
void research_update(struct research *presearch)
Definition research.c:501
#define researches_iterate(_presearch)
Definition research.h:155
#define researches_iterate_end
Definition research.h:158
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Definition rgbcolor.c:74
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, char *path,...)
Definition rgbcolor.c:121
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleload.c:9243
#define sanity_check()
Definition sanitycheck.h:43
#define sanity_check_city(x)
Definition sanitycheck.h:41
int current_compat_ver(void)
Definition savecompat.c:212
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:222
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:145
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:234
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:190
#define sg_check_ret(...)
Definition savecompat.h:148
#define sg_warn(condition, message,...)
Definition savecompat.h:158
#define hex_chars
Definition savecompat.h:203
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:182
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:175
#define sg_regr(fixversion, message,...)
Definition savecompat.h:191
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:144
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:169
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:434
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:8030
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1206
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2762
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3027
static void unit_ordering_apply(void)
Definition savegame3.c:1087
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3719
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:1020
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3599
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3258
bool sg_success
Definition savecompat.c:35
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:155
static char * quote_block(const void *const data, int length)
Definition savegame3.c:897
#define halfbyte_iterate_extras_end
Definition savegame3.c:263
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:258
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2821
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:3090
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3560
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:154
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4175
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:222
static void treaty_save(struct treaty *ptr, void *data_in)
Definition savegame3.c:7960
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5687
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5639
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5052
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2926
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:6165
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:1343
static enum unit_activity char2activity(char activity)
Definition savegame3.c:874
static void unit_ordering_calc(void)
Definition savegame3.c:1058
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2671
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6096
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1258
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2442
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3203
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7682
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3516
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:175
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2048
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2401
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1782
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6706
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:8001
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7987
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3380
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7784
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:279
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2480
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2506
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2095
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:4236
static char order2char(enum unit_orders order)
Definition savegame3.c:737
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7877
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2594
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1141
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6759
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2250
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1173
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1270
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7512
static enum direction8 char2dir(char dir)
Definition savegame3.c:761
#define ACTIVITY_LAST_SAVEGAME3
Definition savegame3.c:156
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:5176
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1235
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8290
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:8049
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7025
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7105
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2071
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2881
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7188
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2966
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:8089
static const char savefile_options_default[]
Definition savegame3.c:281
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:7390
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2709
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3116
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:623
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3980
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:2994
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1306
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7857
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3058
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8114
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7846
void savegame3_load(struct section_file *file)
Definition savegame3.c:461
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1108
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2270
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4726
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2491
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2687
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3656
void save_restore_sane_state(void)
Definition savemain.c:347
void script_server_state_save(struct section_file *file)
void script_server_state_load(struct section_file *file)
void settings_game_load(struct section_file *file, const char *section)
Definition settings.c:4913
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4825
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
sex_t sex_by_name(const char *name)
Definition sex.c:27
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
@ SEX_FEMALE
Definition sex.h:22
@ SEX_MALE
Definition sex.h:23
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
bool str_to_int(const char *str, int *pint)
Definition shared.c:515
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
bool is_base64url(const char *s)
Definition shared.c:321
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1923
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:343
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX_LEN_PATH
Definition shared.h:32
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
@ SSHIP_LAUNCHED
Definition spaceship.h:85
@ SSHIP_NONE
Definition spaceship.h:84
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
const char * aifill(int amount)
Definition srv_main.c:2552
bool game_was_started(void)
Definition srv_main.c:356
void identity_number_reserve(int id)
Definition srv_main.c:2080
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:2357
enum server_states server_state(void)
Definition srv_main.c:340
int x
Definition rand.h:52
RANDOM_TYPE v[56]
Definition rand.h:51
int k
Definition rand.h:52
bool is_init
Definition rand.h:53
int j
Definition rand.h:52
struct player * first
int wonder_city
Definition advdata.h:55
int val
Definition traits.h:38
int mod
Definition traits.h:39
Definition city.h:317
size_t length
Definition city.h:414
bool multiresearch
Definition game.h:170
bool last_updated_year
Definition game.h:243
int world_peace_start
Definition game.h:245
float turn_change_time
Definition game.h:225
bool vision_reveal_tiles
Definition game.h:207
struct packet_scenario_description scenario_desc
Definition game.h:88
bool save_private_map
Definition game.h:269
struct packet_ruleset_control control
Definition game.h:83
bool fogofwar_old
Definition game.h:241
struct packet_game_info info
Definition game.h:89
int timeoutcounter
Definition game.h:214
char rulesetdir[MAX_LEN_NAME]
Definition game.h:246
int additional_phase_seconds
Definition game.h:219
struct section_file * luadata
Definition game.h:254
int scoreturn
Definition game.h:232
randseed seed
Definition game.h:234
int dbid
Definition game.h:255
struct packet_scenario_info scenario
Definition game.h:87
int timeoutint
Definition game.h:210
struct timer * phase_timer
Definition game.h:218
unsigned revealmap
Definition game.h:184
char orig_game_version[MAX_LEN_NAME]
Definition game.h:228
bool save_known
Definition game.h:266
bool foggedborders
Definition game.h:154
struct civ_game::@32::@36::@39 save_options
char * ruleset_capabilities
Definition game.h:86
int timeoutincmult
Definition game.h:212
struct civ_game::@32::@36 server
int timeoutinc
Definition game.h:211
int phase_mode_stored
Definition game.h:223
int max_players
Definition game.h:163
bool save_starts
Definition game.h:268
int timeoutintinc
Definition game.h:213
randseed seed
Definition map_types.h:105
bool have_resources
Definition map_types.h:121
bool altitude_info
Definition map_types.h:74
struct civ_map::@44::@46 server
bool have_huts
Definition map_types.h:120
enum map_generator generator
Definition map_types.h:111
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
int changed_to_times
Definition government.h:64
struct section_file * file
Definition savecompat.h:46
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
int primary_capital_id
Definition player.h:275
bool is_male
Definition player.h:257
int wonders[B_LAST]
Definition player.h:305
bool unassigned_ranked
Definition player.h:255
struct government * target_government
Definition player.h:259
int autoselect_weight
Definition player.h:299
char username[MAX_LEN_NAME]
Definition player.h:252
int revolution_finishes
Definition player.h:273
int nturns_idle
Definition player.h:265
struct government * government
Definition player.h:258
struct team * team
Definition player.h:261
int turns_alive
Definition player.h:266
const struct ai_type * ai
Definition player.h:289
struct unit_list * units
Definition player.h:282
char ranked_username[MAX_LEN_NAME]
Definition player.h:254
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
bv_player real_embassy
Definition player.h:277
struct player::@73::@75 server
struct player_economic economic
Definition player.h:284
struct player_spaceship spaceship
Definition player.h:286
struct attribute_block_s attribute_block
Definition player.h:307
struct player_score score
Definition player.h:283
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:314
struct nation_type * nation
Definition player.h:260
struct nation_style * style
Definition player.h:279
bool border_vision
Definition player.h:327
bool phase_done
Definition player.h:263
struct adv_data * adv
Definition player.h:334
int history
Definition player.h:316
char orig_username[MAX_LEN_NAME]
Definition player.h:347
int last_war_action
Definition player.h:270
struct rgbcolor * rgb
Definition player.h:312
bool unassigned_user
Definition player.h:253
const char * save_reason
Definition savegame3.c:272
struct section_file * file
Definition savegame3.c:268
bool scenario
Definition savegame3.c:273
bool save_players
Definition savegame3.c:276
char secfile_options[512]
Definition savegame3.c:269
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:7954
struct player * plr1
Definition diptreaty.h:82
struct clause_list * clauses
Definition diptreaty.h:84
bool accept1
Definition diptreaty.h:83
struct player * plr0
Definition diptreaty.h:82
bool accept0
Definition diptreaty.h:83
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:139
int length
Definition unit.h:197
int upkeep[O_LAST]
Definition unit.h:149
bool has_orders
Definition unit.h:195
enum action_decision action_decision_want
Definition unit.h:204
int battlegroup
Definition unit.h:193
enum unit_activity activity
Definition unit.h:158
int moves_left
Definition unit.h:151
int id
Definition unit.h:146
enum gen_action action
Definition unit.h:159
int ord_city
Definition unit.h:244
struct unit::@83 orders
bool moved
Definition unit.h:175
int ord_map
Definition unit.h:243
int index
Definition unit.h:197
struct vision * vision
Definition unit.h:246
bool vigilant
Definition unit.h:199
int hp
Definition unit.h:152
int fuel
Definition unit.h:154
struct extra_type * changed_from_target
Definition unit.h:172
int current_form_turn
Definition unit.h:210
bool stay
Definition unit.h:207
enum direction8 facing
Definition unit.h:143
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:141
struct extra_type * activity_target
Definition unit.h:166
int activity_count
Definition unit.h:164
struct unit_order * list
Definition unit.h:200
enum unit_activity changed_from
Definition unit.h:170
struct unit_adv * adv
Definition unit.h:238
struct player * nationality
Definition unit.h:145
bool repeat
Definition unit.h:198
int homecity
Definition unit.h:147
bool paradropped
Definition unit.h:176
bool done_moving
Definition unit.h:183
int birth_turn
Definition unit.h:209
struct goods_type * carrying
Definition unit.h:188
struct tile * goto_tile
Definition unit.h:156
struct tile * action_decision_tile
Definition unit.h:205
int veteran
Definition unit.h:153
int changed_from_count
Definition unit.h:171
enum server_side_agent ssa_controller
Definition unit.h:174
struct civ_map map
int city_style(struct city *pcity)
Definition style.c:241
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
int team_index(const struct team *pteam)
Definition team.c:384
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
bool team_add_player(struct player *pplayer, struct team *pteam)
Definition team.c:468
struct team * team_new(struct team_slot *tslot)
Definition team.c:318
const struct player_list * team_members(const struct team *pteam)
Definition team.c:457
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define A_FUTURE
Definition tech.h:46
#define advance_index_iterate_end
Definition tech.h:244
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:271
#define A_UNSET
Definition tech.h:48
#define advance_iterate_end
Definition tech.h:272
#define A_UNKNOWN
Definition tech.h:49
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:240
void init_tech(struct research *research, bool update)
Definition techtools.c:1091
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:185
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:125
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:246
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:254
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define T_UNKNOWN
Definition terrain.h:62
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:88
#define terrain_type_iterate_end
Definition terrain.h:273
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c: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:119
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
void timer_stop(struct timer *t)
Definition timing.c:305
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:379
#define TIMER_DEBUG
Definition timing.h:61
@ TIMER_CPU
Definition timing.h:41
int city_num_trade_routes(const struct city *pcity)
struct goods_type * goods_by_rule_name(const char *name)
const char * goods_rule_name(struct goods_type *pgood)
struct goods_type * goods_by_number(Goods_type_id id)
#define trade_routes_iterate_end
#define trade_routes_iterate(c, proute)
void free_unit_orders(struct unit *punit)
Definition unit.c:1832
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2473
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1300
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2544
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:883
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1687
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2752
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:1158
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1792
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1310
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1140
#define unit_tile(_pu)
Definition unit.h:406
#define BATTLEGROUP_NONE
Definition unit.h:192
unit_orders
Definition unit.h:37
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_owner(_pu)
Definition unit.h:405
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1406
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5016
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1230
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1063
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1771
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1591
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2629
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1564
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
#define unit_type_iterate(_p)
Definition unittype.h:860
#define U_LAST
Definition unittype.h:40
#define unit_type_iterate_end
Definition unittype.h:867
const char * freeciv_datafile_version(void)
Definition version.c:186
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:180
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:170
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
#define vision_site_owner(v)
Definition vision.h: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