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
985 for (i = 0; i < pwl->length; i++) {
986 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
987
988 /* We lookup the production value by name. An invalid entry isn't a
989 * fatal error; we just truncate the worklist. */
990 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
991 path_str, i);
992 pwl->entries[i] = universal_by_rule_name(kind, name);
993 if (pwl->entries[i].kind == universals_n_invalid()) {
994 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
995 name);
996 pwl->length = i;
997 break;
998 }
999 }
1000
1001 /* Padding entries */
1002 for (; i < wlist_max_length; i++) {
1003 secfile_entry_ignore(file, "%s.wl_kind%d", path_str, i);
1004 secfile_entry_ignore(file, "%s.wl_value%d", path_str, i);
1005 }
1006}
1007
1008/************************************************************************/
1012static void worklist_save(struct section_file *file,
1013 const struct worklist *pwl,
1014 int max_length, const char *path, ...)
1015{
1016 char path_str[1024];
1017 int i;
1018 va_list ap;
1019
1020 /* The first part of the registry path is taken from the varargs to the
1021 * function. */
1022 va_start(ap, path);
1023 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1024 va_end(ap);
1025
1026 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1027
1028 for (i = 0; i < pwl->length; i++) {
1029 const struct universal *entry = pwl->entries + i;
1031 "%s.wl_kind%d", path_str, i);
1033 "%s.wl_value%d", path_str, i);
1034 }
1035
1037
1038 /* We want to keep savegame in tabular format, so each line has to be
1039 * of equal length. Fill table up to maximum worklist size. */
1040 for (i = pwl->length ; i < max_length; i++) {
1041 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1042 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1043 }
1044}
1045
1046/************************************************************************/
1050static void unit_ordering_calc(void)
1051{
1052 int j;
1053
1054 players_iterate(pplayer) {
1055 /* to avoid junk values for unsupported units: */
1056 unit_list_iterate(pplayer->units, punit) {
1057 punit->server.ord_city = 0;
1059 city_list_iterate(pplayer->cities, pcity) {
1060 j = 0;
1061 unit_list_iterate(pcity->units_supported, punit) {
1062 punit->server.ord_city = j++;
1066
1067 whole_map_iterate(&(wld.map), ptile) {
1068 j = 0;
1069 unit_list_iterate(ptile->units, punit) {
1070 punit->server.ord_map = j++;
1073}
1074
1075/************************************************************************/
1079static void unit_ordering_apply(void)
1080{
1081 players_iterate(pplayer) {
1082 city_list_iterate(pplayer->cities, pcity) {
1083 unit_list_sort_ord_city(pcity->units_supported);
1084 }
1087
1088 whole_map_iterate(&(wld.map), ptile) {
1089 unit_list_sort_ord_map(ptile->units);
1091}
1092
1093/************************************************************************/
1100static void sg_extras_set_dbv(struct dbv *extras, char ch,
1101 struct extra_type **idx)
1102{
1103 int i, bin;
1104 const char *pch = strchr(hex_chars, ch);
1105
1106 if (!pch || ch == '\0') {
1107 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1108 bin = 0;
1109 } else {
1110 bin = pch - hex_chars;
1111 }
1112
1113 for (i = 0; i < 4; i++) {
1114 struct extra_type *pextra = idx[i];
1115
1116 if (pextra == NULL) {
1117 continue;
1118 }
1119 if ((bin & (1 << i))
1120 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1121 dbv_set(extras, extra_index(pextra));
1122 }
1123 }
1124}
1125
1126/************************************************************************/
1134 struct extra_type **idx)
1135{
1136 int i, bin;
1137 const char *pch = strchr(hex_chars, ch);
1138
1139 if (!pch || ch == '\0') {
1140 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1141 bin = 0;
1142 } else {
1143 bin = pch - hex_chars;
1144 }
1145
1146 for (i = 0; i < 4; i++) {
1147 struct extra_type *pextra = idx[i];
1148
1149 if (pextra == NULL) {
1150 continue;
1151 }
1152 if ((bin & (1 << i))
1153 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1154 BV_SET(*extras, extra_index(pextra));
1155 }
1156 }
1157}
1158
1159/************************************************************************/
1165static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1166 const int *idx)
1167{
1168 int i, bin = 0;
1169 int max = dbv_bits(extras);
1170
1171 for (i = 0; i < 4; i++) {
1172 int extra = idx[i];
1173
1174 if (extra < 0) {
1175 break;
1176 }
1177
1178 if (extra < max
1179 && (dbv_isset(extras, extra)
1180 /* An invalid resource, a resource that can't exist at the tile's
1181 * current terrain, isn't in the bit extra vector. Save it so it
1182 * can return if the tile's terrain changes to something it can
1183 * exist on. */
1184 || extra_by_number(extra) == presource)) {
1185 bin |= (1 << i);
1186 }
1187 }
1188
1189 return hex_chars[bin];
1190}
1191
1192/************************************************************************/
1198static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1199 const int *idx)
1200{
1201 int i, bin = 0;
1202
1203 for (i = 0; i < 4; i++) {
1204 int extra = idx[i];
1205
1206 if (extra < 0) {
1207 break;
1208 }
1209
1210 if (BV_ISSET(extras, extra)
1211 /* An invalid resource, a resource that can't exist at the tile's
1212 * current terrain, isn't in the bit extra vector. Save it so it
1213 * can return if the tile's terrain changes to something it can
1214 * exist on. */
1215 || extra_by_number(extra) == presource) {
1216 bin |= (1 << i);
1217 }
1218 }
1219
1220 return hex_chars[bin];
1221}
1222
1223/************************************************************************/
1227static struct terrain *char2terrain(char ch)
1228{
1229 /* terrain_by_identifier plus fatal error */
1231 return T_UNKNOWN;
1232 }
1233 terrain_type_iterate(pterrain) {
1234 if (pterrain->identifier_load == ch) {
1235 return pterrain;
1236 }
1238
1239 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1240
1242
1244}
1245
1246/************************************************************************/
1250static char terrain2char(const struct terrain *pterrain)
1251{
1252 if (pterrain == T_UNKNOWN) {
1254 } else {
1255 return pterrain->identifier;
1256 }
1257}
1258
1259/************************************************************************/
1263 const char *path, int plrno)
1264{
1265 char path_with_name[128];
1266 const char *name;
1267 struct advance *padvance;
1268
1270 "%s_name", path);
1271
1273
1274 if (!name || name[0] == '\0') {
1275 /* Used by researching_saved */
1276 return A_UNKNOWN;
1277 }
1278 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1279 return A_FUTURE;
1280 }
1281 if (fc_strcasecmp(name, "A_NONE") == 0) {
1282 return A_NONE;
1283 }
1284 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1285 return A_UNSET;
1286 }
1287
1290 "%s: unknown technology \"%s\".", path_with_name, name);
1291
1292 return advance_number(padvance);
1293}
1294
1295/************************************************************************/
1298static void technology_save(struct section_file *file,
1299 const char *path, int plrno, Tech_type_id tech)
1300{
1301 char path_with_name[128];
1302 const char *name;
1303
1305 "%s_name", path);
1306
1307 switch (tech) {
1308 case A_UNKNOWN: /* Used by researching_saved */
1309 name = "";
1310 break;
1311 case A_NONE:
1312 name = "A_NONE";
1313 break;
1314 case A_UNSET:
1315 name = "A_UNSET";
1316 break;
1317 case A_FUTURE:
1318 name = "A_FUTURE";
1319 break;
1320 default:
1322 break;
1323 }
1324
1326}
1327
1328/* =======================================================================
1329 * Load / save savefile data.
1330 * ======================================================================= */
1331
1332/************************************************************************/
1336{
1337 int i;
1338 const char *terr_name;
1339 bool ruleset_datafile;
1341 const char *str;
1342
1343 /* Check status and return if not OK (sg_success FALSE). */
1344 sg_check_ret();
1345
1346 /* Load savefile options. */
1347 loading->secfile_options
1348 = secfile_lookup_str(loading->file, "savefile.options");
1349
1350 /* We don't need these entries, but read them anyway to avoid
1351 * warnings about unread secfile entries. */
1352 secfile_entry_ignore_by_path(loading->file, "savefile.reason");
1353 secfile_entry_ignore_by_path(loading->file, "savefile.revision");
1354
1355 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1357
1358 if (game.scenario.datafile[0] != '\0') {
1360 } else {
1362 }
1363
1366 const char *req_caps;
1367
1370 /* Failed to load correct ruleset */
1371 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1373 }
1374
1375 req_caps = secfile_lookup_str_default(loading->file, "",
1376 "scenario.ruleset_caps");
1377 strncpy(game.scenario.req_caps, req_caps,
1378 sizeof(game.scenario.req_caps) - 1);
1379 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1380
1381 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1382 /* Current ruleset lacks required capabilities. */
1383 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1384 log_normal(_("Ruleset has capabilities: %s"),
1386 /* TRANS: ... ruleset dir ... scenario name ... */
1387 log_error(_("Current ruleset %s not compatible with the scenario %s."
1388 " Trying to switch to the ruleset specified by the"
1389 " scenario."),
1391
1393 }
1394 }
1395
1398 const char *ruleset, *alt_dir;
1399
1402 "savefile.rulesetdir");
1403
1404 /* Load ruleset. */
1406 if (!strcmp("default", game.server.rulesetdir)) {
1407 /* Here 'default' really means current default.
1408 * Saving happens with real ruleset name, so savegames containing this
1409 * are special scenarios. */
1411 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1413 }
1414
1415 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1416 "savefile.ruleset_alt_dir");
1417
1418 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1419 if (alt_dir) {
1421 _("Failed to load either of rulesets '%s' or '%s' "
1422 "needed for savegame."),
1423 ruleset, alt_dir);
1424 } else {
1426 _("Failed to load ruleset '%s' needed for savegame."),
1427 ruleset);
1428 }
1429 }
1430
1432 /* TRANS: ruleset dir */
1433 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1434 }
1435 }
1436
1437 /* Remove all aifill players. Correct number of them get created later
1438 * with correct skill level etc. */
1439 (void) aifill(0);
1440
1441 /* Time to load scenario specific luadata */
1442 if (game.scenario.datafile[0] != '\0') {
1443 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1445 } else {
1446 const struct strvec *paths[] = { get_scenario_dirs(), NULL };
1447 const struct strvec **path;
1448 const char *found = NULL;
1449 char testfile[MAX_LEN_PATH];
1450 struct section_file *secfile;
1451
1452 for (path = paths; found == NULL && *path != NULL; path++) {
1453 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1454
1455 found = fileinfoname(*path, testfile);
1456 }
1457
1458 if (found == NULL) {
1459 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1460 sg_success = FALSE;
1461 return;
1462 }
1463
1464 secfile = secfile_load(found, FALSE);
1465 if (secfile == NULL) {
1466 log_error(_("Failed to load scenario luadata file %s.luadata"),
1468 sg_success = FALSE;
1469 return;
1470 }
1471
1472 game.server.luadata = secfile;
1473 }
1474 }
1475
1477 "savefile.dbid");
1478
1479 /* This is in the savegame only if the game has been started before savegame3.c time,
1480 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1482 "savefile.last_updated_as_year");
1483
1484 /* Load improvements. */
1485 loading->improvement.size
1487 "savefile.improvement_size");
1488 if (loading->improvement.size) {
1489 loading->improvement.order
1490 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1491 "savefile.improvement_vector");
1492 sg_failure_ret(loading->improvement.size != 0,
1493 "Failed to load improvement order: %s",
1494 secfile_error());
1495 }
1496
1497 /* Load technologies. */
1498 loading->technology.size
1500 "savefile.technology_size");
1501 if (loading->technology.size) {
1502 loading->technology.order
1503 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1504 "savefile.technology_vector");
1505 sg_failure_ret(loading->technology.size != 0,
1506 "Failed to load technology order: %s",
1507 secfile_error());
1508 }
1509
1510 /* Load Activities. */
1511 loading->activities.size
1513 "savefile.activities_size");
1514 if (loading->activities.size) {
1515 loading->activities.order
1516 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1517 "savefile.activities_vector");
1518 sg_failure_ret(loading->activities.size != 0,
1519 "Failed to load activity order: %s",
1520 secfile_error());
1521 }
1522
1523 /* Load traits. */
1524 loading->trait.size
1526 "savefile.trait_size");
1527 if (loading->trait.size) {
1528 loading->trait.order
1529 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1530 "savefile.trait_vector");
1531 sg_failure_ret(loading->trait.size != 0,
1532 "Failed to load trait order: %s",
1533 secfile_error());
1534 }
1535
1536 /* Load extras. */
1537 loading->extra.size
1539 "savefile.extras_size");
1540 if (loading->extra.size) {
1541 const char **modname;
1542 size_t nmod;
1543 int j;
1544
1545 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1546 "savefile.extras_vector");
1547 sg_failure_ret(loading->extra.size != 0,
1548 "Failed to load extras order: %s",
1549 secfile_error());
1551 "Number of extras defined by the ruleset (= %d) are "
1552 "lower than the number in the savefile (= %d).",
1553 game.control.num_extra_types, (int)loading->extra.size);
1554 /* make sure that the size of the array is divisible by 4 */
1555 nmod = 4 * ((loading->extra.size + 3) / 4);
1556 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1557 for (j = 0; j < loading->extra.size; j++) {
1558 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1559 }
1560 free(modname);
1561 for (; j < nmod; j++) {
1562 loading->extra.order[j] = NULL;
1563 }
1564 }
1565
1566 /* Load multipliers. */
1567 loading->multiplier.size
1569 "savefile.multipliers_size");
1570 if (loading->multiplier.size) {
1571 const char **modname;
1572 int j;
1573
1574 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1575 "savefile.multipliers_vector");
1576 sg_failure_ret(loading->multiplier.size != 0,
1577 "Failed to load multipliers order: %s",
1578 secfile_error());
1579 /* It's OK for the set of multipliers in the savefile to differ
1580 * from those in the ruleset. */
1581 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1582 sizeof(*loading->multiplier.order));
1583 for (j = 0; j < loading->multiplier.size; j++) {
1584 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1585 if (!loading->multiplier.order[j]) {
1586 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1587 "discarding", modname[j]);
1588 }
1589 }
1590 free(modname);
1591 }
1592
1593 /* Load specialists. */
1594 loading->specialist.size
1596 "savefile.specialists_size");
1597 if (loading->specialist.size) {
1598 const char **modname;
1599 size_t nmod;
1600 int j;
1601
1602 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1603 "savefile.specialists_vector");
1604 sg_failure_ret(loading->specialist.size != 0,
1605 "Failed to load specialists order: %s",
1606 secfile_error());
1608 "Number of specialists defined by the ruleset (= %d) are "
1609 "lower than the number in the savefile (= %d).",
1610 game.control.num_specialist_types, (int)loading->specialist.size);
1611 /* make sure that the size of the array is divisible by 4 */
1612 /* That's not really needed with specialists at the moment, but done this way
1613 * for consistency with other types, and to be prepared for the time it needs
1614 * to be this way. */
1615 nmod = 4 * ((loading->specialist.size + 3) / 4);
1616 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1617 for (j = 0; j < loading->specialist.size; j++) {
1618 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1619 }
1620 free(modname);
1621 for (; j < nmod; j++) {
1622 loading->specialist.order[j] = NULL;
1623 }
1624 }
1625
1626 /* Load action order. */
1627 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1628 "savefile.action_size");
1629
1630 sg_failure_ret(loading->action.size > 0,
1631 "Failed to load action order: %s",
1632 secfile_error());
1633
1634 if (loading->action.size) {
1635 const char **modname;
1636 int j;
1637
1638 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1639 "savefile.action_vector");
1640
1641 loading->action.order = fc_calloc(loading->action.size,
1642 sizeof(*loading->action.order));
1643
1644 for (j = 0; j < loading->action.size; j++) {
1646
1647 if (real_action) {
1648 loading->action.order[j] = real_action->id;
1649 } else {
1650 log_sg("Unknown action \'%s\'", modname[j]);
1651 loading->action.order[j] = ACTION_NONE;
1652 }
1653 }
1654
1655 free(modname);
1656 }
1657
1658 /* Load action decision order. */
1659 loading->act_dec.size
1661 "savefile.action_decision_size");
1662
1663 sg_failure_ret(loading->act_dec.size > 0,
1664 "Failed to load action decision order: %s",
1665 secfile_error());
1666
1667 if (loading->act_dec.size) {
1668 const char **modname;
1669 int j;
1670
1671 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1672 "savefile.action_decision_vector");
1673
1674 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1675 sizeof(*loading->act_dec.order));
1676
1677 for (j = 0; j < loading->act_dec.size; j++) {
1678 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1680 }
1681
1682 free(modname);
1683 }
1684
1685 /* Load server side agent order. */
1686 loading->ssa.size
1688 "savefile.server_side_agent_size");
1689
1690 sg_failure_ret(loading->ssa.size > 0,
1691 "Failed to load server side agent order: %s",
1692 secfile_error());
1693
1694 if (loading->ssa.size) {
1695 const char **modname;
1696 int j;
1697
1698 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1699 "savefile.server_side_agent_list");
1700
1701 loading->ssa.order = fc_calloc(loading->ssa.size,
1702 sizeof(*loading->ssa.order));
1703
1704 for (j = 0; j < loading->ssa.size; j++) {
1705 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1707 }
1708
1709 free(modname);
1710 }
1711
1712 /* Load city options order. */
1713 loading->coptions.size
1715 "savefile.city_options_size");
1716
1717 sg_failure_ret(loading->coptions.size > 0,
1718 "Failed to load city options order: %s",
1719 secfile_error());
1720
1721 if (loading->coptions.size) {
1722 const char **modname;
1723 int j;
1724
1725 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1726 "savefile.city_options_vector");
1727
1728 loading->coptions.order = fc_calloc(loading->coptions.size,
1729 sizeof(*loading->coptions.order));
1730
1731 for (j = 0; j < loading->coptions.size; j++) {
1732 loading->coptions.order[j] = city_options_by_name(modname[j],
1734 }
1735
1736 free(modname);
1737 }
1738
1739 /* Terrain identifiers */
1741 pterr->identifier_load = '\0';
1743
1744 i = 0;
1746 "savefile.terrident%d.name", i)) != NULL) {
1748
1749 if (pterr != NULL) {
1750 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1751 "savefile.terrident%d.identifier", i);
1752
1753 pterr->identifier_load = *iptr;
1754 } else {
1755 log_error("Identifier for unknown terrain type %s.", terr_name);
1756 }
1757 i++;
1758 }
1759
1762 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1763 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1764 "%s and %s share a saved identifier",
1766 }
1769}
1770
1771/************************************************************************/
1775{
1776 int i;
1777
1778 /* Check status and return if not OK (sg_success FALSE). */
1779 sg_check_ret();
1780
1781 /* Save savefile options. */
1783
1784 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1785
1786 /* Save reason of the savefile generation. */
1787 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1788
1789 /* Save as accurate freeciv revision information as possible */
1790 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1791
1792 /* Freeciv version used in the very first launch of this game -
1793 * or even saving in pregame. */
1795 "savefile.orig_version");
1796
1797 /* Save rulesetdir at this point as this ruleset is required by this
1798 * savefile. */
1799 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1800
1801 if (game.control.version[0] != '\0') {
1802 /* Current ruleset has version information, save it.
1803 * This is never loaded, but exist in savegame file only for debugging purposes. */
1804 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1805 }
1806
1807 if (game.control.alt_dir[0] != '\0') {
1808 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1809 }
1810
1812 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1813 }
1814
1815 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1816
1817 /* Save improvement order in savegame, so we are not dependent on ruleset
1818 * order. If the game isn't started improvements aren't loaded so we can
1819 * not save the order. */
1821 "savefile.improvement_size");
1822 if (improvement_count() > 0) {
1823 const char *buf[improvement_count()];
1824
1825 improvement_iterate(pimprove) {
1826 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1828
1830 "savefile.improvement_vector");
1831 }
1832
1833 /* Save technology order in savegame, so we are not dependent on ruleset
1834 * order. If the game isn't started advances aren't loaded so we can not
1835 * save the order. */
1837 "savefile.technology_size");
1838 if (game.control.num_tech_types > 0) {
1839 const char *buf[game.control.num_tech_types];
1840
1841 buf[A_NONE] = "A_NONE";
1842 advance_iterate(a) {
1846 "savefile.technology_vector");
1847 }
1848
1849 /* Save activities order in the savegame. */
1851 "savefile.activities_size");
1852 if (ACTIVITY_LAST > 0) {
1853 const char **modname;
1854 int j;
1855
1856 i = 0;
1857
1859
1860 for (j = 0; j < ACTIVITY_LAST; j++) {
1862 }
1863
1866 "savefile.activities_vector");
1867 free(modname);
1868 }
1869
1870 /* Save specialists order in the savegame. */
1872 "savefile.specialists_size");
1873 {
1874 const char **modname;
1875
1876 i = 0;
1878
1882
1884 "savefile.specialists_vector");
1885
1886 free(modname);
1887 }
1888
1889 /* Save trait order in savegame. */
1891 "savefile.trait_size");
1892 {
1893 const char **modname;
1894 enum trait tr;
1895 int j;
1896
1897 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1898
1899 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1900 modname[j] = trait_name(tr);
1901 }
1902
1904 "savefile.trait_vector");
1905 free(modname);
1906 }
1907
1908 /* Save extras order in the savegame. */
1910 "savefile.extras_size");
1911 if (game.control.num_extra_types > 0) {
1912 const char **modname;
1913
1914 i = 0;
1916
1917 extra_type_iterate(pextra) {
1918 modname[i++] = extra_rule_name(pextra);
1920
1923 "savefile.extras_vector");
1924 free(modname);
1925 }
1926
1927 /* Save multipliers order in the savegame. */
1929 "savefile.multipliers_size");
1930 if (multiplier_count() > 0) {
1931 const char **modname;
1932
1934
1935 multipliers_iterate(pmul) {
1938
1941 "savefile.multipliers_vector");
1942 free(modname);
1943 }
1944
1945 /* Save city_option order in the savegame. */
1947 "savefile.city_options_size");
1948 if (CITYO_LAST > 0) {
1949 const char **modname;
1950 int j;
1951
1952 i = 0;
1953 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1954
1955 for (j = 0; j < CITYO_LAST; j++) {
1956 modname[i++] = city_options_name(j);
1957 }
1958
1960 CITYO_LAST,
1961 "savefile.city_options_vector");
1962 free(modname);
1963 }
1964
1965 /* Save action order in the savegame. */
1967 "savefile.action_size");
1968 if (NUM_ACTIONS > 0) {
1969 const char **modname;
1970 int j;
1971
1972 i = 0;
1973 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1974
1975 for (j = 0; j < NUM_ACTIONS; j++) {
1977 }
1978
1981 "savefile.action_vector");
1982 free(modname);
1983 }
1984
1985 /* Save action decision order in the savegame. */
1987 "savefile.action_decision_size");
1988 if (ACT_DEC_COUNT > 0) {
1989 const char **modname;
1990 int j;
1991
1992 i = 0;
1994
1995 for (j = 0; j < ACT_DEC_COUNT; j++) {
1997 }
1998
2001 "savefile.action_decision_vector");
2002 free(modname);
2003 }
2004
2005 /* Save server side agent order in the savegame. */
2007 "savefile.server_side_agent_size");
2008 if (SSA_COUNT > 0) {
2009 const char **modname;
2010 int j;
2011
2012 i = 0;
2013 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2014
2015 for (j = 0; j < SSA_COUNT; j++) {
2017 }
2018
2020 SSA_COUNT,
2021 "savefile.server_side_agent_list");
2022 free(modname);
2023 }
2024
2025 /* Save terrain character mapping in the savegame. */
2026 i = 0;
2028 char buf[2];
2029
2030 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2032 buf[1] = '\0';
2033 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2035}
2036
2037/************************************************************************/
2041 const char *option)
2042{
2043 /* Check status and return if not OK (sg_success FALSE). */
2044 sg_check_ret();
2045
2046 if (option == NULL) {
2047 /* no additional option */
2048 return;
2049 }
2050
2051 sz_strlcat(saving->secfile_options, option);
2052 secfile_replace_str(saving->file, saving->secfile_options,
2053 "savefile.options");
2054}
2055
2056/* =======================================================================
2057 * Load / save game status.
2058 * ======================================================================= */
2059
2060/************************************************************************/
2064{
2065 int i;
2066 const char *name;
2067
2068 /* Check status and return if not OK (sg_success FALSE). */
2069 sg_check_ret();
2070
2071 for (i = 0;
2073 "ruledata.government%d.name", i));
2074 i++) {
2076
2077 if (gov != NULL) {
2079 "ruledata.government%d.changes", i);
2080 }
2081 }
2082}
2083
2084/************************************************************************/
2087static void sg_load_game(struct loaddata *loading)
2088{
2089 const char *str;
2090 int i;
2091
2092 /* Check status and return if not OK (sg_success FALSE). */
2093 sg_check_ret();
2094
2095 /* Load server state. */
2096 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2097 "game.server_state");
2098 loading->server_state = server_states_by_name(str, strcmp);
2099 if (!server_states_is_valid(loading->server_state)) {
2100 /* Don't take any risk! */
2101 loading->server_state = S_S_INITIAL;
2102 }
2103
2105 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2106
2109 "game.meta_patches");
2111
2113 /* Do not overwrite this if the user requested a specific metaserver
2114 * from the command line (option --Metaserver). */
2118 "game.meta_server"));
2119 }
2120
2121 if ('\0' == srvarg.serverid[0]) {
2122 /* Do not overwrite this if the user requested a specific metaserver
2123 * from the command line (option --serverid). */
2126 "game.serverid"));
2127 }
2128 sz_strlcpy(server.game_identifier,
2129 secfile_lookup_str_default(loading->file, "", "game.id"));
2130 /* We are not checking game_identifier legality just yet.
2131 * That's done when we are sure that rand seed has been initialized,
2132 * so that we can generate new game_identifier, if needed.
2133 * See sq_load_sanitycheck(). */
2134
2136 "game.phase_mode");
2137 if (str != NULL) {
2140 log_error("Illegal phase mode \"%s\"", str);
2142 }
2143 } else {
2144 log_error("Phase mode missing");
2145 }
2146
2148 "game.phase_mode_stored");
2149 if (str != NULL) {
2152 log_error("Illegal stored phase mode \"%s\"", str);
2154 }
2155 } else {
2156 log_error("Stored phase mode missing");
2157 }
2160 "game.phase");
2164 "game.scoreturn");
2165
2168 "game.timeoutint");
2171 "game.timeoutintinc");
2174 "game.timeoutinc");
2177 "game.timeoutincmult");
2180 "game.timeoutcounter");
2181
2182 game.info.turn
2183 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2185 "game.year"), "%s", secfile_error());
2187 "game.world_peace_start"), "%s", secfile_error());
2189 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2190
2192 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2194 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2196 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2197
2199 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2201 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2203 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2204
2205 /* Savegame may have stored random_seed for documentation purposes only,
2206 * but we want to keep it for resaving. */
2207 game.server.seed = secfile_lookup_int_default(loading->file, 0, "game.random_seed");
2208
2209 /* Global advances. */
2211 "game.global_advances");
2212 if (str != NULL) {
2213 sg_failure_ret(strlen(str) == loading->technology.size,
2214 "Invalid length of 'game.global_advances' ("
2215 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2216 strlen(str), loading->technology.size);
2217 for (i = 0; i < loading->technology.size; i++) {
2218 sg_failure_ret(str[i] == '1' || str[i] == '0',
2219 "Undefined value '%c' within 'game.global_advances'.",
2220 str[i]);
2221 if (str[i] == '1') {
2222 struct advance *padvance
2223 = advance_by_rule_name(loading->technology.order[i]);
2224
2225 if (padvance != NULL) {
2227 }
2228 }
2229 }
2230 }
2231
2233 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2234
2236 = secfile_lookup_float_default(loading->file, 0, "game.last_turn_change_time");
2237}
2238
2239/************************************************************************/
2243{
2244 int set_count = 0;
2245
2247 char path[256];
2248
2249 fc_snprintf(path, sizeof(path),
2250 "ruledata.government%d", set_count++);
2251
2253 "%s.name", path);
2254 secfile_insert_int(saving->file, pgov->changed_to_times,
2255 "%s.changes", path);
2257}
2258
2259/************************************************************************/
2262static void sg_save_game(struct savedata *saving)
2263{
2265 char global_advances[game.control.num_tech_types + 1];
2266 int i;
2267
2268 /* Check status and return if not OK (sg_success FALSE). */
2269 sg_check_ret();
2270
2271 /* Game state: once the game is no longer a new game (ie, has been
2272 * started the first time), it should always be considered a running
2273 * game for savegame purposes. */
2274 if (saving->scenario && !game.scenario.players) {
2276 } else {
2278 }
2280 "game.server_state");
2281
2282 if (game.server.phase_timer != NULL) {
2286 "game.phase_seconds");
2287 }
2288
2290 "game.meta_patches");
2291 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2292
2293 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2294 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2295
2298 "game.phase_mode");
2301 "game.phase_mode_stored");
2303 "game.phase");
2305 "game.scoreturn");
2306
2308 "game.timeoutint");
2310 "game.timeoutintinc");
2312 "game.timeoutinc");
2314 "game.timeoutincmult");
2316 "game.timeoutcounter");
2317
2318 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2319 secfile_insert_int(saving->file, game.info.year, "game.year");
2320 secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
2322 "game.year_0_hack");
2323
2325 "game.globalwarming");
2327 "game.heating");
2329 "game.warminglevel");
2330
2332 "game.nuclearwinter");
2334 "game.cooling");
2336 "game.coolinglevel");
2337 /* For debugging purposes only.
2338 * Do not save it if it's 0 (not known);
2339 * this confuses people reading this 'document' less than
2340 * saving 0. */
2341 if (game.server.seed != 0) {
2343 "game.random_seed");
2344 }
2345
2346 /* Global advances. */
2347 for (i = 0; i < game.control.num_tech_types; i++) {
2348 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2349 }
2350 global_advances[i] = '\0';
2351 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2352
2353 if (!game_was_started()) {
2354 saving->save_players = FALSE;
2355 } else {
2356 if (saving->scenario) {
2357 saving->save_players = game.scenario.players;
2358 } else {
2359 saving->save_players = TRUE;
2360 }
2361#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2363 "game.last_turn_change_time");
2364#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2366 "game.last_turn_change_time");
2367#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2368 }
2369 secfile_insert_bool(saving->file, saving->save_players,
2370 "game.save_players");
2371
2372 if (srv_state != S_S_INITIAL) {
2373 const char *ainames[ai_type_get_count()];
2374
2375 i = 0;
2376 ai_type_iterate(ait) {
2377 ainames[i] = ait->name;
2378 i++;
2380
2382 "game.ai_types");
2383 }
2384}
2385
2386/* =======================================================================
2387 * Load / save random status.
2388 * ======================================================================= */
2389
2390/************************************************************************/
2393static void sg_load_random(struct loaddata *loading)
2394{
2395 /* Check status and return if not OK (sg_success FALSE). */
2396 sg_check_ret();
2397
2398 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2399 const char *str;
2400 int i;
2401
2403 "random.index_J"), "%s", secfile_error());
2405 "random.index_K"), "%s", secfile_error());
2407 "random.index_X"), "%s", secfile_error());
2408
2409 for (i = 0; i < 8; i++) {
2410 str = secfile_lookup_str(loading->file, "random.table%d",i);
2411 sg_failure_ret(NULL != str, "%s", secfile_error());
2412 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2413 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2414 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2415 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2416 }
2417 loading->rstate.is_init = TRUE;
2418 fc_rand_set_state(loading->rstate);
2419 } else {
2420 /* No random values - mark the setting. */
2421 secfile_entry_ignore_by_path(loading->file, "random.saved");
2422
2423 /* We're loading a game without a seed (which is okay, if it's a scenario).
2424 * We need to generate the game seed now because it will be needed later
2425 * during the load. */
2427 loading->rstate = fc_rand_state();
2428 }
2429}
2430
2431/************************************************************************/
2434static void sg_save_random(struct savedata *saving)
2435{
2436 /* Check status and return if not OK (sg_success FALSE). */
2437 sg_check_ret();
2438
2439 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2440 int i;
2441 RANDOM_STATE rstate = fc_rand_state();
2442
2443 secfile_insert_bool(saving->file, TRUE, "random.saved");
2444 fc_assert(rstate.is_init);
2445
2446 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2447 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2448 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2449
2450 for (i = 0; i < 8; i++) {
2451 char vec[100];
2452
2453 fc_snprintf(vec, sizeof(vec),
2454 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2455 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2456 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2457 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2458 secfile_insert_str(saving->file, vec, "random.table%d", i);
2459 }
2460 } else {
2461 secfile_insert_bool(saving->file, FALSE, "random.saved");
2462 }
2463}
2464
2465/* =======================================================================
2466 * Load / save lua script data.
2467 * ======================================================================= */
2468
2469/************************************************************************/
2472static void sg_load_script(struct loaddata *loading)
2473{
2474 /* Check status and return if not OK (sg_success FALSE). */
2475 sg_check_ret();
2476
2478}
2479
2480/************************************************************************/
2483static void sg_save_script(struct savedata *saving)
2484{
2485 /* Check status and return if not OK (sg_success FALSE). */
2486 sg_check_ret();
2487
2489}
2490
2491/* =======================================================================
2492 * Load / save scenario data.
2493 * ======================================================================= */
2494
2495/************************************************************************/
2499{
2500 const char *buf;
2501 int game_version;
2502
2503 /* Check status and return if not OK (sg_success FALSE). */
2504 sg_check_ret();
2505
2506 /* Load version. */
2508 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2509 /* We require at least version 2.90.99 - and at that time we saved version
2510 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2511 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2512 "version 2.90.99 required.");
2513
2514 loading->full_version = game_version;
2515
2516 game.scenario.datafile[0] = '\0';
2517
2519 "scenario.is_scenario"), "%s", secfile_error());
2520 if (!game.scenario.is_scenario) {
2521 return;
2522 }
2523
2524 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2525 if (buf[0] != '\0') {
2527 }
2528
2530 "scenario.authors");
2531 if (buf[0] != '\0') {
2533 } else {
2534 game.scenario.authors[0] = '\0';
2535 }
2536
2538 "scenario.description");
2539 if (buf[0] != '\0') {
2541 } else {
2542 game.scenario_desc.description[0] = '\0';
2543 }
2545 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2547 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2550 "scenario.startpos_nations");
2553 "scenario.prevent_new_cities");
2556 "scenario.lake_flooding");
2559 "scenario.handmade");
2562 "scenario.allow_ai_type_fallback");
2563
2566 "scenario.ruleset_locked");
2567
2569 "scenario.datafile");
2570 if (buf[0] != '\0') {
2572 }
2573
2574 sg_failure_ret(loading->server_state == S_S_INITIAL
2575 || (loading->server_state == S_S_RUNNING
2576 && game.scenario.players),
2577 "Invalid scenario definition (server state '%s' and "
2578 "players are %s).",
2579 server_states_name(loading->server_state),
2580 game.scenario.players ? "saved" : "not saved");
2581}
2582
2583/************************************************************************/
2587{
2588 struct entry *mod_entry;
2589 int game_version;
2590
2591 /* Check status and return if not OK (sg_success FALSE). */
2592 sg_check_ret();
2593
2594 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2595#ifdef EMERGENCY_VERSION
2597#endif /* EMERGENCY_VERSION */
2598 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2599
2600 if (!saving->scenario || !game.scenario.is_scenario) {
2601 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2602 return;
2603 }
2604
2605 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2606
2607 /* Name is mandatory to the level that is saved even if empty. */
2608 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2610
2611 /* Authors list is saved only if it exist */
2612 if (game.scenario.authors[0] != '\0') {
2614 "scenario.authors");
2616 }
2617
2618 /* Description is saved only if it exist */
2619 if (game.scenario_desc.description[0] != '\0') {
2621 "scenario.description");
2623 }
2624
2625 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2626 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2628 "scenario.startpos_nations");
2631 "scenario.prevent_new_cities");
2632 }
2634 "scenario.lake_flooding");
2635 if (game.scenario.handmade) {
2637 "scenario.handmade");
2638 }
2641 "scenario.allow_ai_type_fallback");
2642 }
2643
2644 if (game.scenario.datafile[0] != '\0') {
2646 "scenario.datafile");
2647 }
2649 "scenario.ruleset_locked");
2650 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2652 "scenario.ruleset_caps");
2653 }
2654}
2655
2656/* =======================================================================
2657 * Load / save game settings.
2658 * ======================================================================= */
2659
2660/************************************************************************/
2664{
2665 /* Check status and return if not OK (sg_success FALSE). */
2666 sg_check_ret();
2667
2668 settings_game_load(loading->file, "settings");
2669
2670 /* Save current status of fogofwar. */
2672
2673 /* Add all compatibility settings here. */
2674}
2675
2676/************************************************************************/
2680{
2682
2683 /* Check status and return if not OK (sg_success FALSE). */
2684 sg_check_ret();
2685
2686 if (saving->scenario) {
2687 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2688 }
2689
2690 settings_game_save(saving->file, "settings");
2691 /* Restore real map generator. */
2693
2694 /* Add all compatibility settings here. */
2695}
2696
2697
2698/************************************************************************/
2702{
2703 struct city *pcity;
2704 int i, j;
2705 size_t length, length2;
2706 int *city_count;
2708 "savefile.city_counters_order_size");
2709
2710 if (0==length) {
2711
2712 return;
2713 }
2714
2715 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2716
2717 sg_failure_ret(loading->counter.order != 0,
2718 "Failed to load counter's ruleset order: %s",
2719 secfile_error());
2720 sg_failure_ret(loading->counter.size = length,
2721 "Counter vector in savegame have bad size: %s",
2722 secfile_error());
2723
2724 int corder[length];
2725
2726 for (i = 0; i < length; i++) {
2727
2728 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2730 }
2731
2732 i = 0;
2733 while (NULL != (city_count =
2735 "counters.c%d", i))) {
2736
2737 sg_failure_ret((length2 -1 == (size_t) length), ( "Bad city counters vector size. Should be " SIZE_T_PRINTF ". Is " SIZE_T_PRINTF "." ), length, length2 - 1);
2738
2740
2741 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2742
2743 for (j = 0; j < length; j++) {
2744
2745 pcity->counter_values[corder[j]] = city_count[j+1];
2746 }
2747 i++;
2748 }
2749}
2750
2751/************************************************************************/
2755{
2756 /* Check status and return if not OK (sg_success FALSE). */
2757 sg_check_ret();
2758
2759 const char **countnames;
2760 int *countvalues;
2761 int i, j, count;
2762
2764
2765 secfile_insert_int(saving->file, count,
2766 "savefile.city_counters_order_size");
2767
2768 if (0 == count) {
2769
2770 return;
2771 }
2772
2773 countnames = fc_calloc(count, sizeof(*countnames));
2774 for (j = 0; j < count; j++) {
2776 }
2777
2779 "savefile.city_counters_order_vector");
2780
2782
2783 // Saving city's counters
2784
2785 j = 0;
2786 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2787
2789
2790 city_list_iterate(_pplayer->cities, pcity) {
2791
2792 countvalues[0] = pcity->id;
2793 for (i = 0; i < count; ++i) {
2794
2795 countvalues[i+1] = pcity->counter_values[i];
2796 }
2797
2798 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2799 ++j;
2802
2804}
2805
2806/* =======================================================================
2807 * Load / save the main map.
2808 * ======================================================================= */
2809
2810/************************************************************************/
2813static void sg_load_map(struct loaddata *loading)
2814{
2815 /* Check status and return if not OK (sg_success FALSE). */
2816 sg_check_ret();
2817
2818 /* This defaults to TRUE even if map has not been generated.
2819 * We rely on that
2820 * 1) scenario maps have it explicitly right.
2821 * 2) when map is actually generated, it re-initialize this to FALSE. */
2823 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2824
2826 = secfile_lookup_bool_default(loading->file, TRUE, "map.altitude");
2827
2829 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2830
2832
2833 /* Savegame may have stored random_seed for documentation purposes only,
2834 * but we want to keep it for resaving. */
2836 = secfile_lookup_int_default(loading->file, 0, "map.random_seed");
2837
2838 if (S_S_INITIAL == loading->server_state
2840 /* Generator MAPGEN_SCENARIO is used;
2841 * this map was done with the map editor. */
2842
2843 /* Load tiles. */
2847
2848 /* Nothing more needed for a scenario. */
2849 secfile_entry_ignore(loading->file, "game.save_known");
2850
2851 return;
2852 }
2853
2854 if (S_S_INITIAL == loading->server_state) {
2855 /* Nothing more to do if it is not a scenario but in initial state. */
2856 return;
2857 }
2858
2860 if (wld.map.altitude_info) {
2862 }
2868}
2869
2870/************************************************************************/
2873static void sg_save_map(struct savedata *saving)
2874{
2875 /* Check status and return if not OK (sg_success FALSE). */
2876 sg_check_ret();
2877
2878 if (map_is_empty()) {
2879 /* No map. */
2880 return;
2881 }
2882
2883 if (saving->scenario) {
2885 "map.have_huts");
2887 "map.have_resources");
2888 } else {
2889 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2890 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2891 }
2892
2893 secfile_insert_bool(saving->file, wld.map.altitude_info, "map.altitude");
2894
2895 /* For debugging purposes only.
2896 * Do not save it if it's 0 (not known);
2897 * this confuses people reading this 'document' less than
2898 * saving 0. */
2899 if (wld.map.server.seed != 0) {
2901 "map.random_seed");
2902 }
2903
2905 if (wld.map.altitude_info) {
2907 }
2913}
2914
2915/************************************************************************/
2919{
2920 /* Check status and return if not OK (sg_success FALSE). */
2921 sg_check_ret();
2922
2923 /* Initialize the map for the current topology. 'map.xsize' and
2924 * 'map.ysize' must be set. */
2926
2927 /* Allocate map. */
2929
2930 /* get the terrain type */
2931 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2932 "map.t%04d");
2934
2935 /* Check for special tile sprites. */
2936 whole_map_iterate(&(wld.map), ptile) {
2937 const char *spec_sprite;
2938 const char *label;
2939 int nat_x, nat_y;
2940
2942 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2943 nat_x, nat_y);
2944 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2945 nat_x, nat_y);
2946 if (NULL != ptile->spec_sprite) {
2947 ptile->spec_sprite = fc_strdup(spec_sprite);
2948 }
2949 if (label != NULL) {
2950 tile_set_label(ptile, label);
2951 }
2953}
2954
2955/************************************************************************/
2959{
2960 /* Check status and return if not OK (sg_success FALSE). */
2961 sg_check_ret();
2962
2963 /* Save the terrain type. */
2964 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2965 "map.t%04d");
2966
2967 /* Save special tile sprites. */
2968 whole_map_iterate(&(wld.map), ptile) {
2969 int nat_x, nat_y;
2970
2972 if (ptile->spec_sprite) {
2973 secfile_insert_str(saving->file, ptile->spec_sprite,
2974 "map.spec_sprite_%d_%d", nat_x, nat_y);
2975 }
2976 if (ptile->label != NULL) {
2977 secfile_insert_str(saving->file, ptile->label,
2978 "map.label_%d_%d", nat_x, nat_y);
2979 }
2981}
2982
2983/************************************************************************/
2987{
2988 int y;
2989
2990 /* Check status and return if not OK (sg_success FALSE). */
2991 sg_check_ret();
2992
2993 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
2994 const char *buffer = secfile_lookup_str(loading->file,
2995 "map.alt%04d", y);
2996 const char *ptr = buffer;
2997 int x;
2998
2999 sg_failure_ret(buffer != nullptr, "%s", secfile_error());
3000
3001 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3002 char token[TOKEN_SIZE];
3003 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3004 int number;
3005
3006 scanin(&ptr, ",", token, sizeof(token));
3007 sg_failure_ret(token[0] != '\0',
3008 "Map size not correct (map.alt%d).", y);
3009 sg_failure_ret(str_to_int(token, &number),
3010 "Got map alt %s in (%d, %d).", token, x, y);
3011 ptile->altitude = number;
3012 }
3013 }
3014}
3015
3016/************************************************************************/
3020{
3021 int y;
3022
3023 /* Check status and return if not OK (sg_success FALSE). */
3024 sg_check_ret();
3025
3026 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3028 int x;
3029
3030 line[0] = '\0';
3031 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3032 char token[TOKEN_SIZE];
3033 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3034
3035 fc_snprintf(token, sizeof(token), "%d", ptile->altitude);
3036
3037 strcat(line, token);
3038 if (x + 1 < MAP_NATIVE_WIDTH) {
3039 strcat(line, ",");
3040 }
3041 }
3042
3043 secfile_insert_str(saving->file, line, "map.alt%04d", y);
3044 }
3045}
3046
3047/************************************************************************/
3051{
3052 /* Check status and return if not OK (sg_success FALSE). */
3053 sg_check_ret();
3054
3055 /* Load extras. */
3056 halfbyte_iterate_extras(j, loading->extra.size) {
3057 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
3058 loading->extra.order + 4 * j),
3059 loading->file, "map.e%02d_%04d", j);
3061
3062 if (S_S_INITIAL != loading->server_state
3065 whole_map_iterate(&(wld.map), ptile) {
3067 if (tile_has_extra(ptile, pres)) {
3068 tile_set_resource(ptile, pres);
3069
3070 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
3071 BV_CLR(ptile->extras, extra_index(pres));
3072 }
3073 }
3076 }
3077}
3078
3079/************************************************************************/
3083{
3084 /* Check status and return if not OK (sg_success FALSE). */
3085 sg_check_ret();
3086
3087 /* Save extras. */
3089 int mod[4];
3090 int l;
3091
3092 for (l = 0; l < 4; l++) {
3093 if (4 * j + 1 > game.control.num_extra_types) {
3094 mod[l] = -1;
3095 } else {
3096 mod[l] = 4 * j + l;
3097 }
3098 }
3099 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3100 saving->file, "map.e%02d_%04d", j);
3102}
3103
3104/************************************************************************/
3109{
3110 struct nation_type *pnation;
3111 struct startpos *psp;
3112 struct tile *ptile;
3113 const char SEPARATOR = '#';
3114 const char *nation_names;
3115 int nat_x, nat_y;
3116 bool exclude;
3117 int i, startpos_count;
3118
3119 /* Check status and return if not OK (sg_success FALSE). */
3120 sg_check_ret();
3121
3123 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3124
3125 if (0 == startpos_count) {
3126 /* Nothing to do. */
3127 return;
3128 }
3129
3130 for (i = 0; i < startpos_count; i++) {
3131 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3132 || !secfile_lookup_int(loading->file, &nat_y,
3133 "map.startpos%d.y", i)) {
3134 log_sg("Warning: Undefined coordinates for startpos %d", i);
3135 continue;
3136 }
3137
3138 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3139 if (NULL == ptile) {
3140 log_error("Start position native coordinates (%d, %d) do not exist "
3141 "in this map. Skipping...", nat_x, nat_y);
3142 continue;
3143 }
3144
3145 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3146 "map.startpos%d.exclude", i);
3147
3148 psp = map_startpos_new(ptile);
3149
3151 "map.startpos%d.nations", i);
3152 if (NULL != nation_names && '\0' != nation_names[0]) {
3153 const size_t size = strlen(nation_names) + 1;
3154 char buf[size], *start, *end;
3155
3157 for (start = buf - 1; NULL != start; start = end) {
3158 start++;
3159 if ((end = strchr(start, SEPARATOR))) {
3160 *end = '\0';
3161 }
3162
3163 pnation = nation_by_rule_name(start);
3164 if (NO_NATION_SELECTED != pnation) {
3165 if (exclude) {
3166 startpos_disallow(psp, pnation);
3167 } else {
3168 startpos_allow(psp, pnation);
3169 }
3170 } else {
3171 log_verbose("Missing nation \"%s\".", start);
3172 }
3173 }
3174 }
3175 }
3176
3177 if (0 < map_startpos_count()
3178 && loading->server_state == S_S_INITIAL
3180 log_verbose("Number of starts (%d) are lower than rules.max_players "
3181 "(%d), lowering rules.max_players.",
3184 }
3185
3186 /* Re-initialize nation availability in light of start positions.
3187 * This has to be after loading [scenario] and [map].startpos and
3188 * before we seek nations for players. */
3190}
3191
3192/************************************************************************/
3196{
3197 struct tile *ptile;
3198 const char SEPARATOR = '#';
3199 int i = 0;
3200
3201 /* Check status and return if not OK (sg_success FALSE). */
3202 sg_check_ret();
3203
3205 return;
3206 }
3207
3209 "map.startpos_count");
3210
3212 int nat_x, nat_y;
3213
3214 ptile = startpos_tile(psp);
3215
3217 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3218 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3219
3221 "map.startpos%d.exclude", i);
3222 if (startpos_allows_all(psp)) {
3223 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3224 } else {
3225 const struct nation_hash *nations = startpos_raw_nations(psp);
3227
3228 nation_names[0] = '\0';
3229 nation_hash_iterate(nations, pnation) {
3230 if ('\0' == nation_names[0]) {
3232 sizeof(nation_names));
3233 } else {
3235 "%c%s", SEPARATOR, nation_rule_name(pnation));
3236 }
3239 "map.startpos%d.nations", i);
3240 }
3241 i++;
3243
3245}
3246
3247/************************************************************************/
3251{
3252 int y;
3253 struct tile *claimer = NULL;
3254 struct extra_type *placing = NULL;
3255
3256 /* Check status and return if not OK (sg_success FALSE). */
3257 sg_check_ret();
3258
3259 if (game.info.is_new_game) {
3260 /* No owner/source information for a new game / scenario. */
3261 return;
3262 }
3263
3264 /* Owner, ownership source, and infra turns are stored as plain numbers */
3265 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3266 const char *buffer1 = secfile_lookup_str(loading->file,
3267 "map.owner%04d", y);
3268 const char *buffer2 = secfile_lookup_str(loading->file,
3269 "map.source%04d", y);
3270 const char *buffer3 = secfile_lookup_str(loading->file,
3271 "map.eowner%04d", y);
3273 NULL,
3274 "map.placing%04d", y);
3276 NULL,
3277 "map.infra_turns%04d", y);
3278 const char *ptr1 = buffer1;
3279 const char *ptr2 = buffer2;
3280 const char *ptr3 = buffer3;
3281 const char *ptr_placing = buffer_placing;
3282 const char *ptr_turns = buffer_turns;
3283 int x;
3284
3288
3289 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3290 char token1[TOKEN_SIZE];
3291 char token2[TOKEN_SIZE];
3292 char token3[TOKEN_SIZE];
3294 char token_turns[TOKEN_SIZE];
3295 struct player *owner = NULL;
3296 struct player *eowner = NULL;
3297 int turns;
3298 int number;
3299 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3300
3301 scanin(&ptr1, ",", token1, sizeof(token1));
3302 sg_failure_ret(token1[0] != '\0',
3303 "Map size not correct (map.owner%d).", y);
3304 if (strcmp(token1, "-") == 0) {
3305 owner = NULL;
3306 } else {
3308 "Got map owner %s in (%d, %d).", token1, x, y);
3309 owner = player_by_number(number);
3310 }
3311
3312 scanin(&ptr2, ",", token2, sizeof(token2));
3313 sg_failure_ret(token2[0] != '\0',
3314 "Map size not correct (map.source%d).", y);
3315 if (strcmp(token2, "-") == 0) {
3316 claimer = NULL;
3317 } else {
3319 "Got map source %s in (%d, %d).", token2, x, y);
3320 claimer = index_to_tile(&(wld.map), number);
3321 }
3322
3323 scanin(&ptr3, ",", token3, sizeof(token3));
3324 sg_failure_ret(token3[0] != '\0',
3325 "Map size not correct (map.eowner%d).", y);
3326 if (strcmp(token3, "-") == 0) {
3327 eowner = NULL;
3328 } else {
3330 "Got base owner %s in (%d, %d).", token3, x, y);
3331 eowner = player_by_number(number);
3332 }
3333
3334 if (ptr_placing != NULL) {
3336 sg_failure_ret(token_placing[0] != '\0',
3337 "Map size not correct (map.placing%d).", y);
3338 if (strcmp(token_placing, "-") == 0) {
3339 placing = NULL;
3340 } else {
3342 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3343 placing = extra_by_number(number);
3344 }
3345 } else {
3346 placing = NULL;
3347 }
3348
3349 if (ptr_turns != NULL) {
3350 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3351 sg_failure_ret(token_turns[0] != '\0',
3352 "Map size not correct (map.infra_turns%d).", y);
3354 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3355 turns = number;
3356 } else {
3357 turns = 1;
3358 }
3359
3361 tile_claim_bases(ptile, eowner);
3362 ptile->placing = placing;
3363 ptile->infra_turns = turns;
3364 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3365 }
3366 }
3367}
3368
3369/************************************************************************/
3373{
3374 int y;
3375
3376 /* Check status and return if not OK (sg_success FALSE). */
3377 sg_check_ret();
3378
3379 if (saving->scenario && !saving->save_players) {
3380 /* Nothing to do for a scenario without saved players. */
3381 return;
3382 }
3383
3384 /* Store owner and ownership source as plain numbers. */
3385 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3387 int x;
3388
3389 line[0] = '\0';
3390 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3391 char token[TOKEN_SIZE];
3392 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3393
3394 if (!saving->save_players || tile_owner(ptile) == NULL) {
3395 strcpy(token, "-");
3396 } else {
3397 fc_snprintf(token, sizeof(token), "%d",
3398 player_number(tile_owner(ptile)));
3399 }
3400 strcat(line, token);
3401 if (x + 1 < MAP_NATIVE_WIDTH) {
3402 strcat(line, ",");
3403 }
3404 }
3405
3406 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3407 }
3408
3409 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3411 int x;
3412
3413 line[0] = '\0';
3414 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3415 char token[TOKEN_SIZE];
3416 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3417
3418 if (ptile->claimer == NULL) {
3419 strcpy(token, "-");
3420 } else {
3421 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3422 }
3423 strcat(line, token);
3424 if (x + 1 < MAP_NATIVE_WIDTH) {
3425 strcat(line, ",");
3426 }
3427 }
3428
3429 secfile_insert_str(saving->file, line, "map.source%04d", y);
3430 }
3431
3432 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3434 int x;
3435
3436 line[0] = '\0';
3437 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3438 char token[TOKEN_SIZE];
3439 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3440
3441 if (!saving->save_players || extra_owner(ptile) == NULL) {
3442 strcpy(token, "-");
3443 } else {
3444 fc_snprintf(token, sizeof(token), "%d",
3445 player_number(extra_owner(ptile)));
3446 }
3447 strcat(line, token);
3448 if (x + 1 < MAP_NATIVE_WIDTH) {
3449 strcat(line, ",");
3450 }
3451 }
3452
3453 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3454 }
3455
3456 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3458 int x;
3459
3460 line[0] = '\0';
3461 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3462 char token[TOKEN_SIZE];
3463 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3464
3465 if (ptile->placing == NULL) {
3466 strcpy(token, "-");
3467 } else {
3468 fc_snprintf(token, sizeof(token), "%d",
3469 extra_number(ptile->placing));
3470 }
3471 strcat(line, token);
3472 if (x + 1 < MAP_NATIVE_WIDTH) {
3473 strcat(line, ",");
3474 }
3475 }
3476
3477 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3478 }
3479
3480 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3482 int x;
3483
3484 line[0] = '\0';
3485 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3486 char token[TOKEN_SIZE];
3487 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3488
3489 if (ptile->placing != NULL) {
3490 fc_snprintf(token, sizeof(token), "%d",
3491 ptile->infra_turns);
3492 } else {
3493 fc_snprintf(token, sizeof(token), "0");
3494 }
3495 strcat(line, token);
3496 if (x + 1 < MAP_NATIVE_WIDTH) {
3497 strcat(line, ",");
3498 }
3499 }
3500
3501 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3502 }
3503}
3504
3505/************************************************************************/
3509{
3510 int x, y;
3511
3512 /* Check status and return if not OK (sg_success FALSE). */
3513 sg_check_ret();
3514
3515 sg_failure_ret(loading->worked_tiles == NULL,
3516 "City worked map not loaded!");
3517
3518 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3519 sizeof(*loading->worked_tiles));
3520
3521 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3522 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3523 y);
3524 const char *ptr = buffer;
3525
3526 sg_failure_ret(NULL != buffer,
3527 "Savegame corrupt - map line %d not found.", y);
3528 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3529 char token[TOKEN_SIZE];
3530 int number;
3531 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3532
3533 scanin(&ptr, ",", token, sizeof(token));
3534 sg_failure_ret('\0' != token[0],
3535 "Savegame corrupt - map size not correct.");
3536 if (strcmp(token, "-") == 0) {
3537 number = -1;
3538 } else {
3539 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3540 "Savegame corrupt - got tile worked by city "
3541 "id=%s in (%d, %d).", token, x, y);
3542 }
3543
3544 loading->worked_tiles[ptile->index] = number;
3545 }
3546 }
3547}
3548
3549/************************************************************************/
3553{
3554 int x, y;
3555
3556 /* Check status and return if not OK (sg_success FALSE). */
3557 sg_check_ret();
3558
3559 if (saving->scenario && !saving->save_players) {
3560 /* Nothing to do for a scenario without saved players. */
3561 return;
3562 }
3563
3564 /* Additionally save the tiles worked by the cities */
3565 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
3567
3568 line[0] = '\0';
3569 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
3570 char token[TOKEN_SIZE];
3571 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3572 struct city *pcity = tile_worked(ptile);
3573
3574 if (pcity == NULL) {
3575 strcpy(token, "-");
3576 } else {
3577 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3578 }
3579 strcat(line, token);
3580 if (x < MAP_NATIVE_WIDTH) {
3581 strcat(line, ",");
3582 }
3583 }
3584 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3585 }
3586}
3587
3588/************************************************************************/
3592{
3593 /* Check status and return if not OK (sg_success FALSE). */
3594 sg_check_ret();
3595
3596 players_iterate(pplayer) {
3597 /* Allocate player private map here; it is needed in different modules
3598 * besides this one ((i.e. sg_load_player_*()). */
3599 player_map_init(pplayer);
3601
3603 "game.save_known")) {
3604 int lines = player_slot_max_used_number() / 32 + 1;
3605 int j, p, l, i;
3606 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3607
3608 for (l = 0; l < lines; l++) {
3609 for (j = 0; j < 8; j++) {
3610 for (i = 0; i < 4; i++) {
3611 /* Only bother trying to load the map for this halfbyte if at least
3612 * one of the corresponding player slots is in use. */
3613 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3614 LOAD_MAP_CHAR(ch, ptile,
3615 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3616 |= ascii_hex2bin(ch, j),
3617 loading->file, "map.k%02d_%04d", l * 8 + j);
3618 break;
3619 }
3620 }
3621 }
3622 }
3623
3624 players_iterate(pplayer) {
3625 dbv_clr_all(&pplayer->tile_known);
3627
3628 /* HACK: we read the known data from hex into 32-bit integers, and
3629 * now we convert it to the known tile data of each player. */
3630 whole_map_iterate(&(wld.map), ptile) {
3631 players_iterate(pplayer) {
3632 p = player_index(pplayer);
3633 l = player_index(pplayer) / 32;
3634
3635 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3636 map_set_known(ptile, pplayer);
3637 }
3640
3641 FC_FREE(known);
3642 }
3643}
3644
3645/************************************************************************/
3649{
3650 /* Check status and return if not OK (sg_success FALSE). */
3651 sg_check_ret();
3652
3653 if (!saving->save_players) {
3654 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3655 return;
3656 } else {
3657 int lines = player_slot_max_used_number() / 32 + 1;
3658
3660 "game.save_known");
3662 int j, p, l, i;
3663 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3664
3665 /* HACK: we convert the data into a 32-bit integer, and then save it as
3666 * hex. */
3667
3668 whole_map_iterate(&(wld.map), ptile) {
3669 players_iterate(pplayer) {
3670 if (map_is_known(ptile, pplayer)) {
3671 p = player_index(pplayer);
3672 l = p / 32;
3673 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3674 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3675 }
3678
3679 for (l = 0; l < lines; l++) {
3680 for (j = 0; j < 8; j++) {
3681 for (i = 0; i < 4; i++) {
3682 /* Only bother saving the map for this halfbyte if at least one
3683 * of the corresponding player slots is in use */
3684 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3685 /* put 4-bit segments of the 32-bit "known" field */
3687 + tile_index(ptile)], j),
3688 saving->file, "map.k%02d_%04d", l * 8 + j);
3689 break;
3690 }
3691 }
3692 }
3693 }
3694
3695 FC_FREE(known);
3696 }
3697 }
3698}
3699
3700/* =======================================================================
3701 * Load / save player data.
3702 *
3703 * This is split into two parts as some data can only be loaded if the
3704 * number of players is known and the corresponding player slots are
3705 * defined.
3706 * ======================================================================= */
3707
3708/************************************************************************/
3712{
3713 int i, k, nplayers;
3714 const char *str;
3715 bool shuffle_loaded = TRUE;
3716
3717 /* Check status and return if not OK (sg_success FALSE). */
3718 sg_check_ret();
3719
3720 if (S_S_INITIAL == loading->server_state
3721 || game.info.is_new_game) {
3722 /* Nothing more to do. */
3723 return;
3724 }
3725
3726 /* Load destroyed wonders: */
3728 "players.destroyed_wonders");
3729 sg_failure_ret(str != NULL, "%s", secfile_error());
3730 sg_failure_ret(strlen(str) == loading->improvement.size,
3731 "Invalid length for 'players.destroyed_wonders' ("
3732 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3733 strlen(str), loading->improvement.size);
3734 for (k = 0; k < loading->improvement.size; k++) {
3735 sg_failure_ret(str[k] == '1' || str[k] == '0',
3736 "Undefined value '%c' within "
3737 "'players.destroyed_wonders'.", str[k]);
3738
3739 if (str[k] == '1') {
3740 struct impr_type *pimprove
3741 = improvement_by_rule_name(loading->improvement.order[k]);
3742
3743 if (pimprove != NULL) {
3746 }
3747 }
3748 }
3749
3750 server.identity_number
3751 = secfile_lookup_int_default(loading->file, server.identity_number,
3752 "players.identity_number_used");
3753
3754 /* First remove all defined players. */
3755 players_iterate(pplayer) {
3756 server_remove_player(pplayer);
3758
3759 /* Now, load the players from the savefile. */
3760 player_slots_iterate(pslot) {
3761 struct player *pplayer;
3762 struct rgbcolor *prgbcolor = NULL;
3763 int pslot_id = player_slot_index(pslot);
3764
3765 if (NULL == secfile_section_lookup(loading->file, "player%d",
3766 pslot_id)) {
3767 continue;
3768 }
3769
3770 /* Get player AI type. */
3771 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3772 player_slot_index(pslot));
3773 sg_failure_ret(str != NULL, "%s", secfile_error());
3774
3775 /* Get player color */
3776 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3777 pslot_id)) {
3778 if (game_was_started()) {
3779 log_sg("Game has started, yet player %d has no color defined.",
3780 pslot_id);
3781 /* This will be fixed up later */
3782 } else {
3783 log_verbose("No color defined for player %d.", pslot_id);
3784 /* Colors will be assigned on game start, or at end of savefile
3785 * loading if game has already started */
3786 }
3787 }
3788
3789 /* Create player. */
3790 pplayer = server_create_player(player_slot_index(pslot), str,
3791 prgbcolor,
3794 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3795
3796 server_player_init(pplayer, FALSE, FALSE);
3797
3798 /* Free the color definition. */
3800
3801 /* Multipliers (policies) */
3802
3803 /* First initialise player values with ruleset defaults; this will
3804 * cover any in the ruleset not known when the savefile was created. */
3805 multipliers_iterate(pmul) {
3806 pplayer->multipliers[multiplier_index(pmul)].value
3807 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3809
3810 /* Now override with any values from the savefile. */
3811 for (k = 0; k < loading->multiplier.size; k++) {
3812 const struct multiplier *pmul = loading->multiplier.order[k];
3813
3814 if (pmul) {
3816 int val =
3818 "player%d.multiplier%d.val",
3819 player_slot_index(pslot), k);
3820 int rval = (((CLIP(pmul->start, val, pmul->stop)
3821 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3822
3823 if (rval != val) {
3824 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3825 "was %d, clamped to %d", pslot_id,
3826 multiplier_rule_name(pmul), val, rval);
3827 }
3828 pplayer->multipliers[idx].value = rval;
3829
3830 val =
3832 pplayer->multipliers[idx].value,
3833 "player%d.multiplier%d.target",
3834 player_slot_index(pslot), k);
3835 rval = (((CLIP(pmul->start, val, pmul->stop)
3836 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3837
3838 if (rval != val) {
3839 log_verbose("Player %d had illegal value for multiplier_target "
3840 " \"%s\": was %d, clamped to %d", pslot_id,
3841 multiplier_rule_name(pmul), val, rval);
3842 }
3843 pplayer->multipliers[idx].target = rval;
3844
3845 pplayer->multipliers[idx].changed
3847 "player%d.multiplier%d.changed",
3848 player_slot_index(pslot), k);
3849 } /* else silently discard multiplier not in current ruleset */
3850 }
3851
3852 /* Must be loaded before tile owner is set. */
3853 pplayer->server.border_vision =
3855 "player%d.border_vision",
3856 player_slot_index(pslot));
3857
3859 "player%d.autoselect_weight",
3860 pslot_id);
3862
3863 /* check number of players */
3864 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3865 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3866 "(%d) from the loaded game does not match the number of "
3867 "players present (%d).", nplayers, player_count());
3868
3869 /* Load team information. */
3870 players_iterate(pplayer) {
3871 int team;
3872 struct team_slot *tslot = NULL;
3873
3875 "player%d.team_no",
3876 player_number(pplayer))
3878 "Invalid team definition for player %s (nb %d).",
3879 player_name(pplayer), player_number(pplayer));
3880 /* Should never fail when slot given is not nullptr */
3881 team_add_player(pplayer, team_new(tslot));
3883
3884 /* Loading the shuffle list is quite complex. At the time of saving the
3885 * shuffle data is saved as
3886 * shuffled_player_<number> = player_slot_id
3887 * where number is an increasing number and player_slot_id is a number
3888 * between 0 and the maximum number of player slots. Now we have to create
3889 * a list
3890 * shuffler_players[number] = player_slot_id
3891 * where all player slot IDs are used exactly one time. The code below
3892 * handles this ... */
3893 if (secfile_lookup_int_default(loading->file, -1,
3894 "players.shuffled_player_%d", 0) >= 0) {
3895 int slots = player_slot_count();
3896 int plrcount = player_count();
3899
3900 for (i = 0; i < slots; i++) {
3901 /* Array to save used numbers. */
3903 /* List of all player IDs (needed for set_shuffled_players()). It is
3904 * initialised with the value -1 to indicate that no value is set. */
3905 shuffled_players[i] = -1;
3906 }
3907
3908 /* Load shuffled player list. */
3909 for (i = 0; i < plrcount; i++) {
3910 int shuffle
3912 "players.shuffled_player_%d", i);
3913
3914 if (shuffle == -1) {
3915 log_sg("Missing player shuffle information (index %d) "
3916 "- reshuffle player list!", i);
3918 break;
3919 } else if (shuffled_player_set[shuffle]) {
3920 log_sg("Player shuffle %d used two times "
3921 "- reshuffle player list!", shuffle);
3923 break;
3924 }
3925 /* Set this ID as used. */
3927
3928 /* Save the player ID in the shuffle list. */
3930 }
3931
3932 if (shuffle_loaded) {
3933 /* Insert missing numbers. */
3934 int shuffle_index = plrcount;
3935
3936 for (i = 0; i < slots; i++) {
3937 if (!shuffled_player_set[i]) {
3939 }
3940
3941 /* shuffle_index must not grow higher than size of shuffled_players. */
3943 "Invalid player shuffle data!");
3944 }
3945
3946#ifdef FREECIV_DEBUG
3947 log_debug("[load shuffle] player_count() = %d", player_count());
3948 player_slots_iterate(pslot) {
3949 int plrid = player_slot_index(pslot);
3950
3951 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3953 shuffled_player_set[plrid] ? "is used" : "-");
3955#endif /* FREECIV_DEBUG */
3956
3957 /* Set shuffle list from savegame. */
3959 }
3960 }
3961
3962 if (!shuffle_loaded) {
3963 /* No shuffled players included or error loading them, so shuffle them
3964 * (this may include scenarios). */
3966 }
3967}
3968
3969/************************************************************************/
3973{
3974 /* Check status and return if not OK (sg_success FALSE). */
3975 sg_check_ret();
3976
3977 if (game.info.is_new_game) {
3978 /* Nothing to do. */
3979 return;
3980 }
3981
3982 players_iterate(pplayer) {
3983 sg_load_player_main(loading, pplayer);
3985 sg_load_player_units(loading, pplayer);
3987
3988 /* Check the success of the functions above. */
3989 sg_check_ret();
3990
3991 /* Print out some information */
3992 if (is_ai(pplayer)) {
3993 log_normal(_("%s has been added as %s level AI-controlled player "
3994 "(%s)."), player_name(pplayer),
3995 ai_level_translated_name(pplayer->ai_common.skill_level),
3996 ai_name(pplayer->ai));
3997 } else {
3998 log_normal(_("%s has been added as human player."),
3999 player_name(pplayer));
4000 }
4002
4003 /* Also load the transport status of the units here. It must be a special
4004 * case as all units must be known (unit on an allied transporter). */
4005 players_iterate(pplayer) {
4006 /* Load unit transport status. */
4009
4010 /* Savegame may contain nation assignments that are incompatible with the
4011 * current nationset. Ensure they are compatible, one way or another. */
4013
4014 /* Some players may have invalid nations in the ruleset. Once all players
4015 * are loaded, pick one of the remaining nations for them. */
4016 players_iterate(pplayer) {
4017 if (pplayer->nation == NO_NATION_SELECTED) {
4020 /* TRANS: Minor error message: <Leader> ... <Poles>. */
4021 log_sg(_("%s had invalid nation; changing to %s."),
4022 player_name(pplayer), nation_plural_for_player(pplayer));
4023
4024 ai_traits_init(pplayer);
4025 }
4027
4028 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
4031 if (pplayers_allied(plr, aplayer)) {
4033 DS_ALLIANCE);
4034
4037 log_sg("Illegal alliance structure detected: "
4038 "%s alliance to %s reduced to peace treaty.",
4043 }
4044 }
4047
4048 /* Update cached city illness. This can depend on trade routes,
4049 * so can't be calculated until all players have been loaded. */
4050 if (game.info.illness_on) {
4052 pcity->server.illness
4054 &(pcity->illness_trade), NULL);
4056 }
4057
4058 /* Update all city information. This must come after all cities are
4059 * loaded (in player_load) but before player (dumb) cities are loaded
4060 * in player_load_vision(). */
4061 players_iterate(plr) {
4062 city_list_iterate(plr->cities, pcity) {
4065 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
4068
4069 /* Since the cities must be placed on the map to put them on the
4070 player map we do this afterwards */
4071 players_iterate(pplayer) {
4073 /* Check the success of the function above. */
4074 sg_check_ret();
4076
4077 /* Check shared vision and tiles. */
4078 players_iterate(pplayer) {
4079 BV_CLR_ALL(pplayer->gives_shared_vision);
4080 BV_CLR_ALL(pplayer->gives_shared_tiles);
4081 BV_CLR_ALL(pplayer->server.really_gives_vision);
4083
4084 /* Set up shared vision... */
4085 players_iterate(pplayer) {
4086 int plr1 = player_index(pplayer);
4087
4089 int plr2 = player_index(pplayer2);
4090
4092 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4093 give_shared_vision(pplayer, pplayer2);
4094 }
4096 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4097 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4098 }
4101
4102 /* ...and check it */
4105 /* TODO: Is there a good reason player is not marked as
4106 * giving shared vision to themselves -> really_gives_vision()
4107 * returning FALSE when pplayer1 == pplayer2 */
4108 if (pplayer1 != pplayer2
4111 sg_regr(3000900,
4112 _("%s did not give shared vision to team member %s."),
4115 }
4117 sg_regr(3000900,
4118 _("%s did not give shared vision to team member %s."),
4121 }
4122 }
4125
4128
4129 /* All vision is ready; this calls city_thaw_workers_queue(). */
4131
4132 /* Make sure everything is consistent. */
4133 players_iterate(pplayer) {
4134 unit_list_iterate(pplayer->units, punit) {
4136 struct tile *ptile = unit_tile(punit);
4137
4138 log_sg("%s doing illegal activity in savegame!",
4140 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4144 : "missing",
4145 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4147 }
4150
4153 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4155
4156 /* Player colors are always needed once game has started. Pre-2.4 savegames
4157 * lack them. This cannot be in compatibility conversion layer as we need
4158 * all the player data available to be able to assign best colors. */
4159 if (game_was_started()) {
4161 }
4162}
4163
4164/************************************************************************/
4167static void sg_save_players(struct savedata *saving)
4168{
4169 /* Check status and return if not OK (sg_success FALSE). */
4170 sg_check_ret();
4171
4172 if ((saving->scenario && !saving->save_players)
4173 || !game_was_started()) {
4174 /* Nothing to do for a scenario without saved players or a game in
4175 * INITIAL state. */
4176 return;
4177 }
4178
4179 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4180
4181 /* Save destroyed wonders as bitvector. Note that improvement order
4182 * is saved in 'savefile.improvement.order'. */
4183 {
4184 char destroyed[B_LAST+1];
4185
4186 improvement_iterate(pimprove) {
4187 if (is_great_wonder(pimprove)
4188 && great_wonder_is_destroyed(pimprove)) {
4189 destroyed[improvement_index(pimprove)] = '1';
4190 } else {
4191 destroyed[improvement_index(pimprove)] = '0';
4192 }
4194 destroyed[improvement_count()] = '\0';
4196 "players.destroyed_wonders");
4197 }
4198
4199 secfile_insert_int(saving->file, server.identity_number,
4200 "players.identity_number_used");
4201
4202 /* Save player order. */
4203 {
4204 int i = 0;
4205 shuffled_players_iterate(pplayer) {
4206 secfile_insert_int(saving->file, player_number(pplayer),
4207 "players.shuffled_player_%d", i);
4208 i++;
4210 }
4211
4212 /* Sort units. */
4214
4215 /* Save players. */
4216 players_iterate(pplayer) {
4217 sg_save_player_main(saving, pplayer);
4218 sg_save_player_cities(saving, pplayer);
4219 sg_save_player_units(saving, pplayer);
4221 sg_save_player_vision(saving, pplayer);
4223}
4224
4225/************************************************************************/
4229 struct player *plr)
4230{
4231 const char **slist;
4232 int i, plrno = player_number(plr);
4233 const char *str;
4234 struct government *gov;
4235 const char *level;
4236 const char *barb_str;
4237 size_t nval;
4238 const char *kind;
4239
4240 /* Check status and return if not OK (sg_success FALSE). */
4241 sg_check_ret();
4242
4243 /* Basic player data. */
4244 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4245 sg_failure_ret(str != NULL, "%s", secfile_error());
4247 sz_strlcpy(plr->username,
4249 "player%d.username", plrno));
4251 "player%d.unassigned_user", plrno),
4252 "%s", secfile_error());
4255 "player%d.orig_username", plrno));
4258 "player%d.ranked_username",
4259 plrno));
4261 "player%d.unassigned_ranked", plrno),
4262 "%s", secfile_error());
4264 "player%d.delegation_username",
4265 plrno);
4266 /* Defaults to no delegation. */
4267 if (strlen(str)) {
4269 }
4270
4271 /* Player flags */
4272 BV_CLR_ALL(plr->flags);
4273 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4274 for (i = 0; i < nval; i++) {
4275 const char *sval = slist[i];
4277
4278 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4279
4280 BV_SET(plr->flags, fid);
4281 }
4282 free(slist);
4283
4284 /* Nation */
4285 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4287 if (plr->nation != NULL) {
4288 ai_traits_init(plr);
4289 }
4290
4291 /* Government */
4292 str = secfile_lookup_str(loading->file, "player%d.government_name",
4293 plrno);
4295 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4296 plrno, str);
4297 plr->government = gov;
4298
4299 /* Target government */
4301 "player%d.target_government_name", plrno);
4302 if (str != NULL) {
4304 } else {
4305 plr->target_government = NULL;
4306 }
4309 "player%d.revolution_finishes", plrno);
4310
4311 /* Load diplomatic data (diplstate + embassy + vision).
4312 * Shared vision is loaded in sg_load_players(). */
4314 players_iterate(pplayer) {
4315 char buf[32];
4316 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4317 i = player_index(pplayer);
4318
4319 /* Load diplomatic status */
4320 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4321
4322 ds->type =
4324 diplstate_type, "%s.current", buf);
4325 ds->max_state =
4327 diplstate_type, "%s.closest", buf);
4328
4329 /* FIXME: If either party is barbarian, we cannot enforce below check */
4330#if 0
4331 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4332 sg_regr(3020000,
4333 "Player%d: War with player %d who has never been met. "
4334 "Reverted to No Contact state.", plrno, i);
4335 ds->type = DS_NO_CONTACT;
4336 }
4337#endif
4338
4339 if (valid_dst_closest(ds) != ds->max_state) {
4340 sg_regr(3020000,
4341 "Player%d: closest diplstate to player %d less than current. "
4342 "Updated.", plrno, i);
4343 ds->max_state = ds->type;
4344 }
4345
4346 ds->first_contact_turn =
4348 "%s.first_contact_turn", buf);
4349 ds->turns_left =
4350 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4351 ds->has_reason_to_cancel =
4353 "%s.has_reason_to_cancel", buf);
4354 ds->contact_turns_left =
4356 "%s.contact_turns_left", buf);
4357
4358 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4359 buf)) {
4360 BV_SET(plr->real_embassy, i);
4361 }
4362 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4363 * must be known. */
4365
4366 /* load ai data */
4368 char buf[32];
4369
4370 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4372
4374 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4375 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4377
4379 "player%d.adv.wonder_city",
4380 plrno);
4381
4382 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4383
4384 /* Some sane defaults */
4385 plr->ai_common.fuzzy = 0;
4386 plr->ai_common.expand = 100;
4387 plr->ai_common.science_cost = 100;
4388
4389
4391 "player%d.ai.level", plrno);
4392 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4393 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4395 } else {
4397 }
4398
4400 log_sg("Player%d: Invalid AI level \"%s\". "
4401 "Changed to \"%s\".", plrno, level,
4404 }
4405
4407 "player%d.ai.barb_type", plrno);
4409
4411 log_sg("Player%d: Invalid barbarian type \"%s\". "
4412 "Changed to \"None\".", plrno, barb_str);
4414 }
4415
4416 if (is_barbarian(plr)) {
4417 server.nbarbarians++;
4418 }
4419
4420 if (is_ai(plr)) {
4422 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4423 }
4424
4425 /* Load nation style. */
4426 {
4427 struct nation_style *style;
4428
4429 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4430
4431 sg_failure_ret(str != NULL, "%s", secfile_error());
4432 style = style_by_rule_name(str);
4433 if (style == NULL) {
4434 style = style_by_number(0);
4435 log_sg("Player%d: unsupported city_style_name \"%s\". "
4436 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4437 }
4438 plr->style = style;
4439 }
4440
4442 "player%d.idle_turns", plrno),
4443 "%s", secfile_error());
4444 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4445 if (sex_by_name(kind) == SEX_MALE) {
4446 plr->is_male = TRUE;
4447 } else {
4448 plr->is_male = FALSE;
4449 }
4451 "player%d.is_alive", plrno),
4452 "%s", secfile_error());
4454 "player%d.turns_alive", plrno),
4455 "%s", secfile_error());
4457 "player%d.last_war", plrno),
4458 "%s", secfile_error());
4460 "player%d.phase_done", plrno);
4462 "player%d.gold", plrno),
4463 "%s", secfile_error());
4465 "player%d.rates.tax", plrno),
4466 "%s", secfile_error());
4468 "player%d.rates.science", plrno),
4469 "%s", secfile_error());
4471 "player%d.rates.luxury", plrno),
4472 "%s", secfile_error());
4474 "player%d.infrapts",
4475 plrno);
4476 plr->server.bulbs_last_turn =
4478 "player%d.research.bulbs_last_turn", plrno);
4479
4480 /* Traits */
4481 if (plr->nation) {
4482 for (i = 0; i < loading->trait.size; i++) {
4483 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4484
4485 if (trait_is_valid(tr)) {
4486 int val;
4487
4488 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4489 plrno, i),
4490 "%s", secfile_error());
4491 plr->ai_common.traits[tr].val = val;
4492
4494 "player%d.trait%d.mod", plrno, i),
4495 "%s", secfile_error());
4496 plr->ai_common.traits[tr].mod = val;
4497 }
4498 }
4499 }
4500
4501 /* Achievements */
4502 {
4503 int count;
4504
4505 count = secfile_lookup_int_default(loading->file, -1,
4506 "player%d.achievement_count", plrno);
4507
4508 if (count > 0) {
4509 for (i = 0; i < count; i++) {
4510 const char *name;
4511 struct achievement *pach;
4512 bool first;
4513
4515 "player%d.achievement%d.name", plrno, i);
4517
4519 "Unknown achievement \"%s\".", name);
4520
4522 "player%d.achievement%d.first",
4523 plrno, i),
4524 "achievement error: %s", secfile_error());
4525
4526 sg_failure_ret(pach->first == NULL || !first,
4527 "Multiple players listed as first to get achievement \"%s\".",
4528 name);
4529
4530 BV_SET(pach->achievers, player_index(plr));
4531
4532 if (first) {
4533 pach->first = plr;
4534 }
4535 }
4536 }
4537 }
4538
4539 /* Player score. */
4540 plr->score.happy =
4542 "score%d.happy", plrno);
4543 plr->score.content =
4545 "score%d.content", plrno);
4546 plr->score.unhappy =
4548 "score%d.unhappy", plrno);
4549 plr->score.angry =
4551 "score%d.angry", plrno);
4552
4553 /* Make sure that the score about specialists in current ruleset that
4554 * were not present at saving time are set to zero. */
4556 plr->score.specialists[sp] = 0;
4558
4559 for (i = 0; i < loading->specialist.size; i++) {
4560 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4562 "score%d.specialists%d", plrno, i);
4563 }
4564
4565 plr->score.wonders =
4567 "score%d.wonders", plrno);
4568 plr->score.techs =
4570 "score%d.techs", plrno);
4571 plr->score.techout =
4573 "score%d.techout", plrno);
4574 plr->score.landarea =
4576 "score%d.landarea", plrno);
4577 plr->score.settledarea =
4579 "score%d.settledarea", plrno);
4580 plr->score.population =
4582 "score%d.population", plrno);
4583 plr->score.cities =
4585 "score%d.cities", plrno);
4586 plr->score.units =
4588 "score%d.units", plrno);
4589 plr->score.pollution =
4591 "score%d.pollution", plrno);
4592 plr->score.literacy =
4594 "score%d.literacy", plrno);
4595 plr->score.bnp =
4597 "score%d.bnp", plrno);
4598 plr->score.mfg =
4600 "score%d.mfg", plrno);
4601 plr->score.spaceship =
4603 "score%d.spaceship", plrno);
4604 plr->score.units_built =
4606 "score%d.units_built", plrno);
4607 plr->score.units_killed =
4609 "score%d.units_killed", plrno);
4610 plr->score.units_lost =
4612 "score%d.units_lost", plrno);
4613 plr->score.units_used =
4615 "score%d.units_used", plrno);
4616 plr->score.culture =
4618 "score%d.culture", plrno);
4619 plr->score.game =
4621 "score%d.total", plrno);
4622
4623 /* Load space ship data. */
4624 {
4625 struct player_spaceship *ship = &plr->spaceship;
4626 char prefix[32];
4627 const char *st;
4628 int ei;
4629
4630 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4633 &ei,
4634 "%s.state", prefix),
4635 "%s", secfile_error());
4636 ship->state = ei;
4637
4638 if (ship->state != SSHIP_NONE) {
4639 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4640 "%s.structurals", prefix),
4641 "%s", secfile_error());
4642 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4643 "%s.components", prefix),
4644 "%s", secfile_error());
4646 "%s.modules", prefix),
4647 "%s", secfile_error());
4649 "%s.fuel", prefix),
4650 "%s", secfile_error());
4651 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4652 "%s.propulsion", prefix),
4653 "%s", secfile_error());
4654 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4655 "%s.habitation", prefix),
4656 "%s", secfile_error());
4657 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4658 "%s.life_support", prefix),
4659 "%s", secfile_error());
4660 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4661 "%s.solar_panels", prefix),
4662 "%s", secfile_error());
4663
4664 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4665 sg_failure_ret(st != NULL, "%s", secfile_error())
4666 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4667 sg_failure_ret(st[i] == '1' || st[i] == '0',
4668 "Undefined value '%c' within '%s.structure'.", st[i],
4669 prefix)
4670
4671 if (!(st[i] == '0')) {
4672 BV_SET(ship->structure, i);
4673 }
4674 }
4675 if (ship->state >= SSHIP_LAUNCHED) {
4676 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4677 "%s.launch_year", prefix),
4678 "%s", secfile_error());
4679 }
4681 }
4682 }
4683
4684 /* Load lost wonder data. */
4685 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4686 /* If not present, probably an old savegame; nothing to be done */
4687 if (str != NULL) {
4688 int k;
4689
4690 sg_failure_ret(strlen(str) == loading->improvement.size,
4691 "Invalid length for 'player%d.lost_wonders' ("
4692 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4693 plrno, strlen(str), loading->improvement.size);
4694 for (k = 0; k < loading->improvement.size; k++) {
4695 sg_failure_ret(str[k] == '1' || str[k] == '0',
4696 "Undefined value '%c' within "
4697 "'player%d.lost_wonders'.", plrno, str[k]);
4698
4699 if (str[k] == '1') {
4700 struct impr_type *pimprove =
4701 improvement_by_rule_name(loading->improvement.order[k]);
4702 if (pimprove) {
4703 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4704 }
4705 }
4706 }
4707 }
4708
4709 plr->history =
4710 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4711 plr->server.huts =
4712 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4713}
4714
4715/************************************************************************/
4719 struct player *plr)
4720{
4721 int i, k, plrno = player_number(plr);
4722 struct player_spaceship *ship = &plr->spaceship;
4723 const char *flag_names[PLRF_COUNT];
4724 int set_count;
4725
4726 /* Check status and return if not OK (sg_success FALSE). */
4727 sg_check_ret();
4728
4729 set_count = 0;
4730 for (i = 0; i < PLRF_COUNT; i++) {
4731 if (player_has_flag(plr, i)) {
4733 }
4734 }
4735
4737 "player%d.flags", plrno);
4738
4739 secfile_insert_str(saving->file, ai_name(plr->ai),
4740 "player%d.ai_type", plrno);
4742 "player%d.name", plrno);
4744 "player%d.username", plrno);
4746 "player%d.unassigned_user", plrno);
4747 if (plr->rgb != NULL) {
4748 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4749 } else {
4750 /* Colorless players are ok in pregame */
4751 if (game_was_started()) {
4752 log_sg("Game has started, yet player %d has no color defined.", plrno);
4753 }
4754 }
4756 "player%d.ranked_username", plrno);
4758 "player%d.unassigned_ranked", plrno);
4760 "player%d.orig_username", plrno);
4763 : "",
4764 "player%d.delegation_username", plrno);
4766 "player%d.nation", plrno);
4767 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4768 "player%d.team_no", plrno);
4769
4772 "player%d.government_name", plrno);
4773
4774 if (plr->target_government) {
4777 "player%d.target_government_name", plrno);
4778 }
4779
4781 "player%d.style_by_name", plrno);
4782
4784 "player%d.idle_turns", plrno);
4785 if (plr->is_male) {
4787 "player%d.kind", plrno);
4788 } else {
4790 "player%d.kind", plrno);
4791 }
4793 "player%d.is_alive", plrno);
4795 "player%d.turns_alive", plrno);
4797 "player%d.last_war", plrno);
4799 "player%d.phase_done", plrno);
4800
4801 players_iterate(pplayer) {
4802 char buf[32];
4803 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4804
4805 i = player_index(pplayer);
4806
4807 /* save diplomatic state */
4808 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4809
4810 secfile_insert_enum(saving->file, ds->type,
4811 diplstate_type, "%s.current", buf);
4812 secfile_insert_enum(saving->file, ds->max_state,
4813 diplstate_type, "%s.closest", buf);
4814 secfile_insert_int(saving->file, ds->first_contact_turn,
4815 "%s.first_contact_turn", buf);
4816 secfile_insert_int(saving->file, ds->turns_left,
4817 "%s.turns_left", buf);
4818 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4819 "%s.has_reason_to_cancel", buf);
4820 secfile_insert_int(saving->file, ds->contact_turns_left,
4821 "%s.contact_turns_left", buf);
4823 "%s.embassy", buf);
4824 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4825 "%s.gives_shared_vision", buf);
4826 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4827 "%s.gives_shared_tiles", buf);
4829
4832 /* save ai data */
4834 "player%d.ai%d.love", plrno, i);
4835 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4837
4839 "player%d.adv.wonder_city", plrno);
4840
4841 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4842
4843 /* Multipliers (policies) */
4844 i = multiplier_count();
4845
4846 for (k = 0; k < i; k++) {
4848 "player%d.multiplier%d.val", plrno, k);
4850 "player%d.multiplier%d.target", plrno, k);
4852 "player%d.multiplier%d.changed", plrno, k);
4853 }
4854
4856 "player%d.ai.level", plrno);
4858 "player%d.ai.barb_type", plrno);
4860 "player%d.gold", plrno);
4862 "player%d.rates.tax", plrno);
4864 "player%d.rates.science", plrno);
4866 "player%d.rates.luxury", plrno);
4868 "player%d.infrapts", plrno);
4870 "player%d.research.bulbs_last_turn", plrno);
4871
4872 /* Save traits */
4873 {
4874 enum trait tr;
4875 int j;
4876
4877 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4879 "player%d.trait%d.val", plrno, j);
4881 "player%d.trait%d.mod", plrno, j);
4882 }
4883 }
4884
4885 /* Save achievements */
4886 {
4887 int j = 0;
4888
4890 if (achievement_player_has(pach, plr)) {
4892 "player%d.achievement%d.name", plrno, j);
4893 if (pach->first == plr) {
4895 "player%d.achievement%d.first", plrno, j);
4896 } else {
4898 "player%d.achievement%d.first", plrno, j);
4899 }
4900
4901 j++;
4902 }
4904
4905 secfile_insert_int(saving->file, j,
4906 "player%d.achievement_count", plrno);
4907 }
4908
4910 "player%d.revolution_finishes", plrno);
4911
4912 /* Player score */
4914 "score%d.happy", plrno);
4916 "score%d.content", plrno);
4918 "score%d.unhappy", plrno);
4920 "score%d.angry", plrno);
4923 "score%d.specialists%d", plrno, sp);
4926 "score%d.wonders", plrno);
4928 "score%d.techs", plrno);
4930 "score%d.techout", plrno);
4932 "score%d.landarea", plrno);
4934 "score%d.settledarea", plrno);
4936 "score%d.population", plrno);
4938 "score%d.cities", plrno);
4940 "score%d.units", plrno);
4942 "score%d.pollution", plrno);
4944 "score%d.literacy", plrno);
4945 secfile_insert_int(saving->file, plr->score.bnp,
4946 "score%d.bnp", plrno);
4947 secfile_insert_int(saving->file, plr->score.mfg,
4948 "score%d.mfg", plrno);
4950 "score%d.spaceship", plrno);
4952 "score%d.units_built", plrno);
4954 "score%d.units_killed", plrno);
4956 "score%d.units_lost", plrno);
4958 "score%d.units_used", plrno);
4960 "score%d.culture", plrno);
4961 secfile_insert_int(saving->file, plr->score.game,
4962 "score%d.total", plrno);
4963
4964 /* Save space ship status. */
4965 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4966 plrno);
4967 if (ship->state != SSHIP_NONE) {
4968 char buf[32];
4969 char st[NUM_SS_STRUCTURALS+1];
4970 int ssi;
4971
4972 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4973
4974 secfile_insert_int(saving->file, ship->structurals,
4975 "%s.structurals", buf);
4976 secfile_insert_int(saving->file, ship->components,
4977 "%s.components", buf);
4978 secfile_insert_int(saving->file, ship->modules,
4979 "%s.modules", buf);
4980 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4981 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4982 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4983 secfile_insert_int(saving->file, ship->life_support,
4984 "%s.life_support", buf);
4985 secfile_insert_int(saving->file, ship->solar_panels,
4986 "%s.solar_panels", buf);
4987
4988 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4989 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4990 }
4991 st[ssi] = '\0';
4992 secfile_insert_str(saving->file, st, "%s.structure", buf);
4993 if (ship->state >= SSHIP_LAUNCHED) {
4994 secfile_insert_int(saving->file, ship->launch_year,
4995 "%s.launch_year", buf);
4996 }
4997 }
4998
4999 /* Save lost wonders info. */
5000 {
5001 char lost[B_LAST+1];
5002
5003 improvement_iterate(pimprove) {
5004 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
5005 lost[improvement_index(pimprove)] = '1';
5006 } else {
5007 lost[improvement_index(pimprove)] = '0';
5008 }
5010 lost[improvement_count()] = '\0';
5012 "player%d.lost_wonders", plrno);
5013 }
5014
5015 secfile_insert_int(saving->file, plr->history,
5016 "player%d.history", plrno);
5018 "player%d.hut_count", plrno);
5019
5021 "player%d.border_vision", plrno);
5022
5023 if (saving->scenario) {
5024 if (plr->autoselect_weight < 0) { /* Apply default behavior */
5025 int def = 1; /* We want users to get a player in a scenario */
5026
5028 /* This isn't usable player */
5029 def = 0;
5030 }
5031
5032 secfile_insert_int(saving->file, def,
5033 "player%d.autoselect_weight", plrno);
5034 } else {
5036 "player%d.autoselect_weight", plrno);
5037 }
5038 }
5039}
5040
5041/************************************************************************/
5045 struct player *plr)
5046{
5047 int ncities, i, plrno = player_number(plr);
5048 bool tasks_handled;
5050
5051 /* Check status and return if not OK (sg_success FALSE). */
5052 sg_check_ret();
5053
5055 "player%d.ncities", plrno),
5056 "%s", secfile_error());
5057
5058 if (!plr->is_alive && ncities > 0) {
5059 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
5060 ncities = 0;
5061 }
5062
5064 "player%d.wl_max_length",
5065 plrno);
5067 "player%d.routes_max_length", plrno);
5068
5069 /* Load all cities of the player. */
5070 for (i = 0; i < ncities; i++) {
5071 char buf[32];
5072 struct city *pcity;
5073
5074 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5075
5076 /* Create a dummy city. */
5083 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
5084 }
5085
5088
5089 /* Load the information about the nationality of citizens. This is done
5090 * here because the city sanity check called by citizens_update() requires
5091 * that the city is registered. */
5093
5094 /* After everything is loaded, but before vision. */
5096
5097 /* adding the city contribution to fog-of-war */
5101
5103 }
5104
5106 for (i = 0; !tasks_handled; i++) {
5107 int city_id;
5108 struct city *pcity = NULL;
5109
5110 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5111 plrno, i);
5112
5113 if (city_id != -1) {
5114 pcity = player_city_by_number(plr, city_id);
5115 }
5116
5117 if (pcity != NULL) {
5118 const char *str;
5119 int nat_x, nat_y;
5120 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5121
5122 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5123 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5124
5125 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5126
5127 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5129
5131 "Unknown workertask activity %s", str);
5132
5133 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5134
5135 if (strcmp("-", str)) {
5137
5138 sg_failure_ret(ptask->tgt != NULL,
5139 "Unknown workertask target %s", str);
5140 } else {
5141 ptask->tgt = NULL;
5142
5143 if (ptask->act == ACTIVITY_IRRIGATE) {
5145 } else if (ptask->act == ACTIVITY_MINE) {
5146 ptask->act = ACTIVITY_MINE;
5147 }
5148 }
5149
5150 ptask->want = secfile_lookup_int_default(loading->file, 1,
5151 "player%d.task%d.want", plrno, i);
5152
5153 worker_task_list_append(pcity->task_reqs, ptask);
5154 } else {
5156 }
5157 }
5158}
5159
5160/************************************************************************/
5163static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5164 struct city *pcity, const char *citystr,
5166{
5167 struct player *past;
5168 const char *kind, *name, *str;
5169 int id, i, repair, sp_count = 0, workers = 0, value;
5170 int nat_x, nat_y;
5171 citizens size;
5172 const char *stylename;
5173 int partner;
5174 int want;
5175 int tmp_int;
5176 const struct civ_map *nmap = &(wld.map);
5177 enum capital_type cap;
5178
5180 FALSE, "%s", secfile_error());
5182 FALSE, "%s", secfile_error());
5185 "%s has invalid center tile (%d, %d)",
5186 citystr, nat_x, nat_y);
5188 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5189
5190 /* Instead of dying, use 'citystr' string for damaged name. */
5192 "%s.name", citystr));
5193
5195 citystr), FALSE, "%s", secfile_error());
5196
5198 "%s.original", citystr);
5199 past = player_by_number(id);
5200 if (NULL != past) {
5201 pcity->original = past;
5202 }
5203
5204 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5205 citystr), FALSE, "%s", secfile_error());
5206 size = (citizens)value; /* Set the correct type */
5207 sg_warn_ret_val(value == (int)size, FALSE,
5208 "Invalid city size: %d, set to %d", value, size);
5210
5212 "%s.capital", citystr),
5214
5216 pcity->capital = cap;
5217 if (cap == CAPITAL_PRIMARY) {
5218 plr->primary_capital_id = pcity->id;
5219 }
5220 } else {
5221 pcity->capital = CAPITAL_NOT;
5222 }
5223
5224 for (i = 0; i < loading->specialist.size; i++) {
5225 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5226 citystr, i),
5227 FALSE, "%s", secfile_error());
5228 pcity->specialists[specialist_index(loading->specialist.order[i])]
5229 = (citizens)value;
5230 sp_count += value;
5231 }
5232
5233 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5234 for (i = 0; partner != 0; i++) {
5235 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5236 const char *dir;
5237 const char *good_str;
5238
5239 /* Append to routes list immediately, so the pointer can be found for freeing
5240 * even if we abort */
5242
5243 proute->partner = partner;
5244 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5246 "No traderoute direction found for %s", citystr);
5249 "Illegal route direction %s", dir);
5250 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5252 "No good found for %s", citystr);
5254 sg_warn_ret_val(proute->goods != NULL, FALSE,
5255 "Illegal good %s", good_str);
5256
5257 /* Next one */
5259 "%s.traderoute%d", citystr, i + 1);
5260 }
5261
5262 for (; i < routes_max; i++) {
5263 secfile_entry_ignore(loading->file, "%s.traderoute%d", citystr, i);
5264 secfile_entry_ignore(loading->file, "%s.route_direction%d", citystr, i);
5265 secfile_entry_ignore(loading->file, "%s.route_good%d", citystr, i);
5266 }
5267
5268 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5269 "%s.food_stock", citystr),
5270 FALSE, "%s", secfile_error());
5271 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5272 "%s.shield_stock", citystr),
5273 FALSE, "%s", secfile_error());
5274 pcity->history =
5275 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5276
5277 pcity->airlift =
5278 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5279 pcity->was_happy =
5280 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5281 citystr);
5282 pcity->had_famine =
5283 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5284 citystr);
5285
5286 pcity->turn_plague =
5287 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5288
5290 "%s.anarchy", citystr),
5291 FALSE, "%s", secfile_error());
5292 pcity->rapture =
5293 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5294 pcity->steal =
5295 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5296
5297 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5298 "%s.turn_founded", citystr),
5299 FALSE, "%s", secfile_error());
5301 "%s.acquire_t", citystr),
5302 FALSE, "%s", secfile_error());
5303 pcity->acquire_t = tmp_int;
5304 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5305 citystr), FALSE, "%s", secfile_error());
5306 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5307 citystr), FALSE, "%s", secfile_error());
5308
5309 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5310 "%s.turn_last_built", citystr),
5311 FALSE, "%s", secfile_error());
5312
5313 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5314 citystr);
5315 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5316 citystr);
5317 pcity->production = universal_by_rule_name(kind, name);
5318 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5319 "%s.currently_building: unknown \"%s\" \"%s\".",
5320 citystr, kind, name);
5321
5322 want = secfile_lookup_int_default(loading->file, 0,
5323 "%s.current_want", citystr);
5324 if (pcity->production.kind == VUT_IMPROVEMENT) {
5325 pcity->server.adv->
5326 building_want[improvement_index(pcity->production.value.building)]
5327 = want;
5328 }
5329
5330 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5331 citystr);
5332 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5333 citystr);
5336 "%s.changed_from: unknown \"%s\" \"%s\".",
5337 citystr, kind, name);
5338
5339 pcity->before_change_shields =
5340 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5341 "%s.before_change_shields", citystr);
5342 pcity->caravan_shields =
5344 "%s.caravan_shields", citystr);
5345 pcity->disbanded_shields =
5347 "%s.disbanded_shields", citystr);
5348 pcity->last_turns_shield_surplus =
5350 "%s.last_turns_shield_surplus",
5351 citystr);
5352
5354 "%s.style", citystr);
5355 if (stylename != NULL) {
5357 } else {
5358 pcity->style = 0;
5359 }
5360 if (pcity->style < 0) {
5361 pcity->style = city_style(pcity);
5362 }
5363
5364 pcity->server.synced = FALSE; /* Must re-sync with clients */
5365
5366 /* Initialise list of city improvements. */
5367 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5368 pcity->built[i].turn = I_NEVER;
5369 }
5370
5371 /* Load city improvements. */
5372 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5374 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5375 "Invalid length of '%s.improvements' ("
5376 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5377 citystr, strlen(str), loading->improvement.size);
5378 for (i = 0; i < loading->improvement.size; i++) {
5379 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5380 "Undefined value '%c' within '%s.improvements'.",
5381 str[i], citystr)
5382
5383 if (str[i] == '1') {
5384 struct impr_type *pimprove
5385 = improvement_by_rule_name(loading->improvement.order[i]);
5386
5387 if (pimprove) {
5388 city_add_improvement(pcity, pimprove);
5389 }
5390 }
5391 }
5392
5393 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5394 "No worked tiles map defined.");
5395
5397
5398 /* Load new savegame with variable (squared) city radius and worked
5399 * tiles map */
5400
5401 int radius_sq
5402 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5403 citystr);
5404 city_map_radius_sq_set(pcity, radius_sq);
5405
5407 if (loading->worked_tiles[ptile->index] == pcity->id) {
5408 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5409 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5410 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5411 TILE_XY(pcity->tile), TILE_XY(ptile));
5412 pcity->specialists[DEFAULT_SPECIALIST]++;
5413 sp_count++;
5414 } else {
5415 tile_set_worked(ptile, pcity);
5416 workers++;
5417 }
5418
5419#ifdef FREECIV_DEBUG
5420 /* Set this tile to unused; a check for not reset tiles is
5421 * included in game_load_internal() */
5422 loading->worked_tiles[ptile->index] = -1;
5423#endif /* FREECIV_DEBUG */
5424 }
5426
5427 if (tile_worked(city_tile(pcity)) != pcity) {
5428 struct city *pwork = tile_worked(city_tile(pcity));
5429
5430 if (NULL != pwork) {
5431 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5432 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5435
5436 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5437 pwork->specialists[DEFAULT_SPECIALIST]++;
5439 } else {
5440 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5443 }
5444
5445 /* Repair pcity */
5448 }
5449
5451 if (0 != repair) {
5452 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5453 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5455 workers, FREE_WORKED_TILES, sp_count);
5456
5457 /* Repair pcity */
5459 }
5460
5461 /* worklist_init() done in create_city_virtual() */
5462 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5463
5464 /* Load city options. */
5465 BV_CLR_ALL(pcity->city_options);
5466 for (i = 0; i < loading->coptions.size; i++) {
5467 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5468 citystr, i)) {
5469 BV_SET(pcity->city_options, loading->coptions.order[i]);
5470 }
5471 }
5473 "%s.wlcb", citystr),
5474 FALSE, "%s", secfile_error());
5475 pcity->wlcb = tmp_int;
5476
5477 /* Load the city rally point. */
5478 {
5479 int len = secfile_lookup_int_default(loading->file, 0,
5480 "%s.rally_point_length", citystr);
5481 int unconverted;
5482
5483 pcity->rally_point.length = len;
5484 if (len > 0) {
5486
5487 pcity->rally_point.orders
5488 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5489 pcity->rally_point.persistent
5491 "%s.rally_point_persistent", citystr);
5492 pcity->rally_point.vigilant
5494 "%s.rally_point_vigilant", citystr);
5495
5498 "%s.rally_point_orders", citystr);
5501 "%s.rally_point_dirs", citystr);
5504 "%s.rally_point_activities", citystr);
5505
5506 for (i = 0; i < len; i++) {
5507 struct unit_order *order = &pcity->rally_point.orders[i];
5508
5509 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5510 || rally_activities[i] == '\0') {
5511 log_sg("Invalid rally point.");
5512 free(pcity->rally_point.orders);
5513 pcity->rally_point.orders = NULL;
5514 pcity->rally_point.length = 0;
5515 break;
5516 }
5517 order->order = char2order(rally_orders[i]);
5518 order->dir = char2dir(rally_dirs[i]);
5519 order->activity = char2activity(rally_activities[i]);
5520
5522 "%s.rally_point_action_vec,%d",
5523 citystr, i);
5524
5525 if (unconverted == -1) {
5526 order->action = ACTION_NONE;
5527 } else if (unconverted >= 0 && unconverted < loading->action.size) {
5528 /* Look up what action id the unconverted number represents. */
5529 order->action = loading->action.order[unconverted];
5530 } else {
5531 if (order->order == ORDER_PERFORM_ACTION) {
5532 sg_regr(3020000, "Invalid action id in order for city rally point %d",
5533 pcity->id);
5534 }
5535
5536 order->action = ACTION_NONE;
5537 }
5538
5539 order->target
5541 "%s.rally_point_tgt_vec,%d",
5542 citystr, i);
5543 order->sub_target
5545 "%s.rally_point_sub_tgt_vec,%d",
5546 citystr, i);
5547 }
5548 } else {
5549 pcity->rally_point.orders = NULL;
5550
5551 secfile_entry_ignore(loading->file, "%s.rally_point_persistent",
5552 citystr);
5553 secfile_entry_ignore(loading->file, "%s.rally_point_vigilant",
5554 citystr);
5555 secfile_entry_ignore(loading->file, "%s.rally_point_orders",
5556 citystr);
5557 secfile_entry_ignore(loading->file, "%s.rally_point_dirs",
5558 citystr);
5559 secfile_entry_ignore(loading->file, "%s.rally_point_activities",
5560 citystr);
5561 secfile_entry_ignore(loading->file, "%s.rally_point_action_vec",
5562 citystr);
5564 "%s.rally_point_tgt_vec", citystr);
5566 "%s.rally_point_sub_tgt_vec", citystr);
5567 }
5568 }
5569
5570 /* Load the city manager parameters. */
5571 {
5572 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5573 "%s.cma_enabled", citystr);
5574 if (enabled) {
5575 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5576
5577 for (i = 0; i < O_LAST; i++) {
5579 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5581 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5582 }
5583
5585 loading->file, FALSE, "%s.max_growth", citystr);
5587 loading->file, FALSE, "%s.require_happy", citystr);
5589 loading->file, FALSE, "%s.allow_disorder", citystr);
5591 loading->file, FALSE, "%s.allow_specialists", citystr);
5593 loading->file, 0, "%s.happy_factor", citystr);
5594 pcity->cm_parameter = param;
5595 } else {
5596 pcity->cm_parameter = NULL;
5597
5598 for (i = 0; i < O_LAST; i++) {
5600 "%s.cma_minimal_surplus,%d", citystr, i);
5602 "%s.cma_factor,%d", citystr, i);
5603 }
5604
5605 secfile_entry_ignore(loading->file, "%s.max_growth",
5606 citystr);
5607 secfile_entry_ignore(loading->file, "%s.require_happy",
5608 citystr);
5609 secfile_entry_ignore(loading->file, "%s.allow_disorder",
5610 citystr);
5611 secfile_entry_ignore(loading->file, "%s.allow_specialists",
5612 citystr);
5613 secfile_entry_ignore(loading->file, "%s.happy_factor",
5614 citystr);
5615 }
5616 }
5617
5618 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5619
5620 return TRUE;
5621}
5622
5623/************************************************************************/
5627 struct player *plr,
5628 struct city *pcity,
5629 const char *citystr)
5630{
5632 citizens size;
5633
5635 player_slots_iterate(pslot) {
5636 int nationality;
5637
5638 nationality = secfile_lookup_int_default(loading->file, -1,
5639 "%s.citizen%d", citystr,
5640 player_slot_index(pslot));
5641 if (nationality > 0 && !player_slot_is_used(pslot)) {
5642 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5644 continue;
5645 }
5646
5647 if (nationality != -1 && player_slot_is_used(pslot)) {
5648 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5649 "Invalid value for citizens of player %d in %s: %d.",
5650 player_slot_index(pslot), city_name_get(pcity), nationality);
5651 citizens_nation_set(pcity, pslot, nationality);
5652 }
5654 /* Sanity check. */
5656 if (size != city_size_get(pcity)) {
5657 if (size != 0) {
5658 /* size == 0 can be result from the fact that ruleset had no
5659 * nationality enabled at saving time, so no citizens at all
5660 * were saved. But something more serious must be going on if
5661 * citizens have been saved partially - if some of them are there. */
5662 log_sg("City size and number of citizens does not match in %s "
5663 "(%d != %d)! Repairing ...", city_name_get(pcity),
5665 }
5667 }
5668 }
5669}
5670
5671/************************************************************************/
5675 struct player *plr)
5676{
5678 int i = 0;
5679 int plrno = player_number(plr);
5681
5682 /* Check status and return if not OK (sg_success FALSE). */
5683 sg_check_ret();
5684
5686 "player%d.ncities", plrno);
5687
5689 /* Initialise the nation list for the citizens information. */
5690 player_slots_iterate(pslot) {
5693 }
5694
5695 /* First determine length of longest worklist, rally point order, and the
5696 * nationalities we have. */
5698 int routes;
5699
5700 /* Check the sanity of the city. */
5703
5704 if (pcity->worklist.length > wlist_max_length) {
5705 wlist_max_length = pcity->worklist.length;
5706 }
5707
5708 if (pcity->rally_point.length > rally_point_max_length) {
5709 rally_point_max_length = pcity->rally_point.length;
5710 }
5711
5712 routes = city_num_trade_routes(pcity);
5713 if (routes > routes_max) {
5714 routes_max = routes;
5715 }
5716
5718 /* Find all nations of the citizens,*/
5719 players_iterate(pplayer) {
5720 if (!nations[player_index(pplayer)]
5721 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5722 nations[player_index(pplayer)] = TRUE;
5723 }
5725 }
5727
5729 "player%d.wl_max_length", plrno);
5731 "player%d.routes_max_length", plrno);
5732
5734 struct tile *pcenter = city_tile(pcity);
5735 char impr_buf[B_LAST + 1];
5736 char buf[32];
5737 int j, nat_x, nat_y;
5738
5739 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5740
5741
5743 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5744 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5745
5746 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5747
5748 if (pcity->original != NULL) {
5749 secfile_insert_int(saving->file, player_number(pcity->original),
5750 "%s.original", buf);
5751 } else {
5752 secfile_insert_int(saving->file, -1, "%s.original", buf);
5753 }
5754 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5755
5757 "%s.capital", buf);
5758
5759 j = 0;
5761 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5762 buf, j++);
5764
5765 j = 0;
5767 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5768 buf, j);
5770 "%s.route_direction%d", buf, j);
5772 "%s.route_good%d", buf, j);
5773 j++;
5775
5776 /* Save dummy values to keep tabular format happy */
5777 for (; j < routes_max; j++) {
5778 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5780 "%s.route_direction%d", buf, j);
5782 "%s.route_good%d", buf, j);
5783 }
5784
5785 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5786 buf);
5787 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5788 buf);
5789 secfile_insert_int(saving->file, pcity->history, "%s.history",
5790 buf);
5791
5792 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5793 buf);
5794 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5795 buf);
5796 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5797 buf);
5798 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5799 buf);
5800
5801 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5802 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5803 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5804 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5805 buf);
5806 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5807 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5808 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5809 secfile_insert_int(saving->file, pcity->turn_last_built,
5810 "%s.turn_last_built", buf);
5811
5812 /* For visual debugging, variable length strings together here */
5813 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5814
5816 "%s.currently_building_kind", buf);
5818 "%s.currently_building_name", buf);
5819
5820 if (pcity->production.kind == VUT_IMPROVEMENT) {
5822 pcity->server.adv->
5823 building_want[improvement_index(pcity->production.value.building)],
5824 "%s.current_want", buf);
5825 } else {
5826 secfile_insert_int(saving->file, 0,
5827 "%s.current_want", buf);
5828 }
5829
5831 "%s.changed_from_kind", buf);
5833 "%s.changed_from_name", buf);
5834
5835 secfile_insert_int(saving->file, pcity->before_change_shields,
5836 "%s.before_change_shields", buf);
5837 secfile_insert_int(saving->file, pcity->caravan_shields,
5838 "%s.caravan_shields", buf);
5839 secfile_insert_int(saving->file, pcity->disbanded_shields,
5840 "%s.disbanded_shields", buf);
5841 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5842 "%s.last_turns_shield_surplus", buf);
5843
5845 "%s.style", buf);
5846
5847 /* Save the squared city radius and all tiles within the corresponding
5848 * city map. */
5849 secfile_insert_int(saving->file, pcity->city_radius_sq,
5850 "player%d.c%d.city_radius_sq", plrno, i);
5851 /* The tiles worked by the city are saved using the main map.
5852 * See also sg_save_map_worked(). */
5853
5854 /* Save improvement list as bytevector. Note that improvement order
5855 * is saved in savefile.improvement_order. */
5856 improvement_iterate(pimprove) {
5857 impr_buf[improvement_index(pimprove)]
5858 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5859 : '1';
5861 impr_buf[improvement_count()] = '\0';
5862
5864 "Invalid size of the improvement vector (%s.improvements: "
5865 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5866 strlen(impr_buf), sizeof(impr_buf));
5867 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5868
5869 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5870 buf);
5871
5872 for (j = 0; j < CITYO_LAST; j++) {
5873 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5874 "%s.option%d", buf, j);
5875 }
5876 secfile_insert_int(saving->file, pcity->wlcb,
5877 "%s.wlcb", buf);
5878
5879 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5880
5882 /* Save nationality of the citizens,*/
5883 players_iterate(pplayer) {
5884 if (nations[player_index(pplayer)]) {
5886 citizens_nation_get(pcity, pplayer->slot),
5887 "%s.citizen%d", buf, player_index(pplayer));
5888 }
5890 }
5891
5892 secfile_insert_int(saving->file, pcity->rally_point.length,
5893 "%s.rally_point_length", buf);
5894 if (pcity->rally_point.length) {
5895 int len = pcity->rally_point.length;
5896 char orders[len + 1], dirs[len + 1], activities[len + 1];
5897 int actions[len];
5898 int targets[len];
5899 int sub_targets[len];
5900
5901 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5902 "%s.rally_point_persistent", buf);
5903 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5904 "%s.rally_point_vigilant", buf);
5905
5906 for (j = 0; j < len; j++) {
5907 orders[j] = order2char(pcity->rally_point.orders[j].order);
5908 dirs[j] = '?';
5909 activities[j] = '?';
5910 targets[j] = NO_TARGET;
5911 sub_targets[j] = NO_TARGET;
5912 actions[j] = -1;
5913 switch (pcity->rally_point.orders[j].order) {
5914 case ORDER_MOVE:
5915 case ORDER_ACTION_MOVE:
5916 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5917 break;
5918 case ORDER_ACTIVITY:
5919 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5920 activities[j]
5921 = activity2char(pcity->rally_point.orders[j].activity);
5922 actions[j]
5923 = pcity->rally_point.orders[j].action;
5924 break;
5926 actions[j] = pcity->rally_point.orders[j].action;
5927 targets[j] = pcity->rally_point.orders[j].target;
5928 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5929 break;
5930 case ORDER_FULL_MP:
5931 case ORDER_LAST:
5932 break;
5933 }
5934
5935 if (actions[j] == ACTION_NONE) {
5936 actions[j] = -1;
5937 }
5938 }
5939 orders[len] = dirs[len] = activities[len] = '\0';
5940
5941 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5942 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5943 secfile_insert_str(saving->file, activities,
5944 "%s.rally_point_activities", buf);
5945
5947 "%s.rally_point_action_vec", buf);
5948 /* Fill in dummy values for order targets so the registry will save
5949 * the unit table in a tabular format. */
5950 for (j = len; j < rally_point_max_length; j++) {
5951 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5952 buf, j);
5953 }
5954
5955 secfile_insert_int_vec(saving->file, targets, len,
5956 "%s.rally_point_tgt_vec", buf);
5957 /* Fill in dummy values for order targets so the registry will save
5958 * the unit table in a tabular format. */
5959 for (j = len; j < rally_point_max_length; j++) {
5961 "%s.rally_point_tgt_vec,%d", buf, j);
5962 }
5963
5964 secfile_insert_int_vec(saving->file, sub_targets, len,
5965 "%s.rally_point_sub_tgt_vec", buf);
5966 /* Fill in dummy values for order targets so the registry will save
5967 * the unit table in a tabular format. */
5968 for (j = len; j < rally_point_max_length; j++) {
5969 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5970 buf, j);
5971 }
5972 } else {
5973 /* Put all the same fields into the savegame - otherwise the
5974 * registry code can't correctly use a tabular format and the
5975 * savegame will be bigger. */
5976 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5977 buf);
5978 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5979 buf);
5980 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5981 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5982 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5983 buf);
5984
5985 /* Fill in dummy values for order targets so the registry will save
5986 * the unit table in a tabular format. */
5987
5988 /* The start of a vector has no number. */
5989 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5990 buf);
5991 for (j = 1; j < rally_point_max_length; j++) {
5992 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5993 buf, j);
5994 }
5995
5996 /* The start of a vector has no number. */
5997 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5998 buf);
5999 for (j = 1; j < rally_point_max_length; j++) {
6001 "%s.rally_point_tgt_vec,%d", buf, j);
6002 }
6003
6004 /* The start of a vector has no number. */
6005 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
6006 buf);
6007 for (j = 1; j < rally_point_max_length; j++) {
6008 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
6009 buf, j);
6010 }
6011 }
6012
6013 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
6014 "%s.cma_enabled", buf);
6015 if (pcity->cm_parameter) {
6017 pcity->cm_parameter->minimal_surplus, O_LAST,
6018 "%s.cma_minimal_surplus", buf);
6020 pcity->cm_parameter->factor, O_LAST,
6021 "%s.cma_factor", buf);
6022 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
6023 "%s.max_growth", buf);
6024 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
6025 "%s.require_happy", buf);
6026 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
6027 "%s.allow_disorder", buf);
6029 pcity->cm_parameter->allow_specialists,
6030 "%s.allow_specialists", buf);
6031 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
6032 "%s.happy_factor", buf);
6033 } else {
6034 int zeros[O_LAST];
6035
6036 memset(zeros, 0, sizeof(zeros));
6038 "%s.cma_minimal_surplus", buf);
6040 "%s.cma_factor", buf);
6041 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
6042 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
6043 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
6044 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
6045 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
6046 }
6047
6048 i++;
6050
6051 i = 0;
6053 worker_task_list_iterate(pcity->task_reqs, ptask) {
6054 int nat_x, nat_y;
6055
6057 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
6058 plrno, i);
6059 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
6060 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
6062 "player%d.task%d.activity",
6063 plrno, i);
6064 if (ptask->tgt != NULL) {
6066 "player%d.task%d.target",
6067 plrno, i);
6068 } else {
6069 secfile_insert_str(saving->file, "-",
6070 "player%d.task%d.target",
6071 plrno, i);
6072 }
6073 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
6074
6075 i++;
6078}
6079
6080/************************************************************************/
6084 struct player *plr)
6085{
6086 int nunits, i, plrno = player_number(plr);
6087 size_t orders_max_length;
6088
6089 /* Check status and return if not OK (sg_success FALSE). */
6090 sg_check_ret();
6091
6093 "player%d.nunits", plrno),
6094 "%s", secfile_error());
6095 if (!plr->is_alive && nunits > 0) {
6096 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6097 nunits = 0; /* Some old savegames may be buggy. */
6098 }
6099
6101 "player%d.orders_max_length",
6102 plrno);
6103
6104 for (i = 0; i < nunits; i++) {
6105 struct unit *punit;
6106 struct city *pcity;
6107 const char *name;
6108 char buf[32];
6109 struct unit_type *type;
6110 struct tile *ptile;
6111
6112 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6113
6114 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
6116 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
6117
6118 /* Create a dummy unit. */
6119 punit = unit_virtual_create(plr, NULL, type, 0);
6122 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6123 }
6124
6127
6129 unit_list_prepend(pcity->units_supported, punit);
6130 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6131 log_sg("%s: bad home city %d.", buf, punit->homecity);
6133 }
6134
6135 ptile = unit_tile(punit);
6136
6137 /* allocate the unit's contribution to fog of war */
6140 /* NOTE: There used to be some map_set_known calls here. These were
6141 * unneeded since unfogging the tile when the unit sees it will
6142 * automatically reveal that tile. */
6143
6146 }
6147}
6148
6149/************************************************************************/
6153 struct player *plr, struct unit *punit,
6155 const char *unitstr)
6156{
6157 enum unit_activity activity;
6158 int nat_x, nat_y;
6159 struct extra_type *pextra = NULL;
6160 struct tile *ptile;
6161 int extra_id;
6162 int ei;
6163 const char *facing_str;
6164 int natnbr;
6165 int unconverted;
6166 const char *str;
6167 enum gen_action action;
6168
6170 unitstr), FALSE, "%s", secfile_error());
6172 FALSE, "%s", secfile_error());
6174 FALSE, "%s", secfile_error());
6175
6176 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6177 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6178 unitstr, nat_x, nat_y);
6179 unit_tile_set(punit, ptile);
6180
6183 "%s.facing", unitstr);
6184 if (facing_str[0] != 'x') {
6185 /* We don't touch punit->facing if savegame does not contain that
6186 * information. Initial orientation set by unit_virtual_create()
6187 * is as good as any. */
6188 enum direction8 facing = char2dir(facing_str[0]);
6189
6190 if (direction8_is_valid(facing)) {
6191 punit->facing = facing;
6192 } else {
6193 log_error("Illegal unit orientation '%s'", facing_str);
6194 }
6195 }
6196
6197 /* If savegame has unit nationality, it doesn't hurt to
6198 * internally set it even if nationality rules are disabled. */
6200 player_number(plr),
6201 "%s.nationality", unitstr);
6202
6204 if (punit->nationality == NULL) {
6205 punit->nationality = plr;
6206 }
6207
6209 "%s.homecity", unitstr), FALSE,
6210 "%s", secfile_error());
6212 "%s.moves", unitstr), FALSE,
6213 "%s", secfile_error());
6215 "%s.fuel", unitstr), FALSE,
6216 "%s", secfile_error());
6218 "%s.activity", unitstr), FALSE,
6219 "%s", secfile_error());
6220 activity = unit_activity_by_name(loading->activities.order[ei],
6223 "%s.action", unitstr), FALSE,
6224 "%s", secfile_error());
6225 if (ei == -1) {
6227 } else if (ei >= 0 && ei < loading->action.size) {
6228 action = loading->action.order[ei];
6229 } else {
6230 log_sg("Invalid action id for unit %d", punit->id);
6232 }
6233
6236 "%s.born", unitstr);
6239 "%s.current_form_turn", unitstr);
6240
6242 "%s.activity_tgt", unitstr);
6243
6244 if (extra_id != -2) {
6245 if (extra_id >= 0 && extra_id < loading->extra.size) {
6246 pextra = loading->extra.order[extra_id];
6247 set_unit_activity_targeted(punit, activity, pextra, action);
6248 } else if (activity == ACTIVITY_IRRIGATE) {
6252 punit);
6253 if (tgt != NULL) {
6255 } else {
6257 }
6258 } else if (activity == ACTIVITY_MINE) {
6260 EC_MINE,
6262 punit);
6263 if (tgt != NULL) {
6265 } else {
6267 }
6268 } else {
6269 set_unit_activity(punit, activity, action);
6270 }
6271 } else {
6273 } /* activity_tgt == NULL */
6274
6276 "%s.activity_count", unitstr), FALSE,
6277 "%s", secfile_error());
6278
6281 "%s.changed_from", unitstr);
6282
6284 "%s.changed_from_tgt", unitstr), FALSE,
6285 "%s", secfile_error());
6286
6287 if (extra_id >= 0 && extra_id < loading->extra.size) {
6288 punit->changed_from_target = loading->extra.order[extra_id];
6289 } else {
6291 }
6292
6295 "%s.changed_from_count", unitstr);
6296
6297 /* Special case: for a long time, we accidentally incremented
6298 * activity_count while a unit was sentried, so it could increase
6299 * without bound (bug #20641) and be saved in old savefiles.
6300 * We zero it to prevent potential trouble overflowing the range
6301 * in network packets, etc. */
6302 if (activity == ACTIVITY_SENTRY) {
6303 punit->activity_count = 0;
6304 }
6307 }
6308
6309 punit->veteran
6310 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6311 {
6312 /* Protect against change in veteran system in ruleset */
6313 const int levels = utype_veteran_levels(unit_type_get(punit));
6314
6315 if (punit->veteran >= levels) {
6316 fc_assert(levels >= 1);
6317 punit->veteran = levels - 1;
6318 }
6319 }
6322 "%s.done_moving", unitstr);
6325 "%s.battlegroup", unitstr);
6326
6328 "%s.go", unitstr)) {
6329 int gnat_x, gnat_y;
6330
6332 "%s.goto_x", unitstr), FALSE,
6333 "%s", secfile_error());
6335 "%s.goto_y", unitstr), FALSE,
6336 "%s", secfile_error());
6337
6339 } else {
6340 punit->goto_tile = NULL;
6341
6342 if (punit->activity == ACTIVITY_GOTO) {
6343 /* goto_tile should never be NULL with ACTIVITY_GOTO */
6344 sg_regr(3020200, "Unit %d on goto without goto_tile. Aborting goto.",
6345 punit->id);
6347 }
6348
6349 /* These variables are not used but needed for saving the unit table.
6350 * Load them to prevent unused variables errors. */
6351 secfile_entry_ignore(loading->file, "%s.goto_x", unitstr);
6352 secfile_entry_ignore(loading->file, "%s.goto_y", unitstr);
6353 }
6354
6355 /* Load AI data of the unit. */
6356 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6357
6360 "%s.server_side_agent",
6361 unitstr);
6362 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6363 /* Look up what server side agent the unconverted number represents. */
6364 punit->ssa_controller = loading->ssa.order[unconverted];
6365 } else {
6366 log_sg("Invalid server side agent %d for unit %d",
6367 unconverted, punit->id);
6368
6370 }
6371
6373 "%s.hp", unitstr), FALSE,
6374 "%s", secfile_error());
6375
6377 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6379 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6380 punit->moved
6381 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6384 "%s.paradropped", unitstr);
6385 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6386 if (str[0] != '\0') {
6388 }
6389
6390 /* The transport status (punit->transported_by) is loaded in
6391 * sg_player_units_transport(). */
6392
6393 /* Initialize upkeep values: these are hopefully initialized
6394 * elsewhere before use (specifically, in city_support(); but
6395 * fixme: check whether always correctly initialized?).
6396 * Below is mainly for units which don't have homecity --
6397 * otherwise these don't get initialized (and AI calculations
6398 * etc may use junk values). */
6402
6404 "%s.action_decision", unitstr),
6405 FALSE, "%s", secfile_error());
6406
6407 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6408 /* Look up what action decision want the unconverted number
6409 * represents. */
6410 punit->action_decision_want = loading->act_dec.order[unconverted];
6411 } else {
6412 log_sg("Invalid action decision want for unit %d", punit->id);
6413
6415 }
6416
6418 /* Load the tile to act against. */
6419 int adwt_x, adwt_y;
6420
6421 if (secfile_lookup_int(loading->file, &adwt_x,
6422 "%s.action_decision_tile_x", unitstr)
6424 "%s.action_decision_tile_y", unitstr)) {
6426 adwt_x, adwt_y);
6427 } else {
6430 log_sg("Bad action_decision_tile for unit %d", punit->id);
6431 }
6432 } else {
6433 secfile_entry_ignore(loading->file, "%s.action_decision_tile_x", unitstr);
6434 secfile_entry_ignore(loading->file, "%s.action_decision_tile_y", unitstr);
6435
6437 }
6438
6440
6441 /* Load the unit orders */
6442 {
6443 int len = secfile_lookup_int_default(loading->file, 0,
6444 "%s.orders_length", unitstr);
6445
6446 if (len > 0) {
6447 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6448 int j;
6449
6450 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6454 "%s.orders_index", unitstr);
6457 "%s.orders_repeat", unitstr);
6460 "%s.orders_vigilant", unitstr);
6461
6464 "%s.orders_list", unitstr);
6467 "%s.dir_list", unitstr);
6470 "%s.activity_list", unitstr);
6471
6473
6474 for (j = 0; j < len; j++) {
6475 struct unit_order *order = &punit->orders.list[j];
6477 int order_sub_tgt;
6478
6479 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6480 || act_unitstr[j] == '\0') {
6481 log_sg("Invalid unit orders.");
6483 break;
6484 }
6485 order->order = char2order(orders_unitstr[j]);
6486 order->dir = char2dir(dir_unitstr[j]);
6487 order->activity = char2activity(act_unitstr[j]);
6488
6490 "%s.action_vec,%d",
6491 unitstr, j);
6492
6493 if (unconverted == -1) {
6494 order->action = ACTION_NONE;
6495 } else if (unconverted >= 0 && unconverted < loading->action.size) {
6496 /* Look up what action id the unconverted number represents. */
6497 order->action = loading->action.order[unconverted];
6498 } else {
6499 if (order->order == ORDER_PERFORM_ACTION) {
6500 sg_regr(3020000, "Invalid action id in order for unit %d", punit->id);
6501 }
6502
6503 order->action = ACTION_NONE;
6504 }
6505
6506 if (order->order == ORDER_LAST
6507 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6508 || (order->order == ORDER_ACTION_MOVE
6509 && !direction8_is_valid(order->dir))
6510 || (order->order == ORDER_PERFORM_ACTION
6511 && !action_id_exists(order->action))
6512 || (order->order == ORDER_ACTIVITY
6513 && (order->activity == ACTIVITY_LAST
6514 || !action_id_exists(order->action)))) {
6515 /* An invalid order. Just drop the orders for this unit. */
6517 punit->orders.list = NULL;
6518 punit->orders.length = 0;
6520 punit->goto_tile = NULL;
6521 break;
6522 }
6523
6525 "%s.tgt_vec,%d",
6526 unitstr, j);
6528 "%s.sub_tgt_vec,%d",
6529 unitstr, j);
6530
6531 if (order->order == ORDER_PERFORM_ACTION) {
6532 /* Validate sub target */
6533 switch (action_id_get_sub_target_kind(order->action)) {
6534 case ASTK_BUILDING:
6535 /* Sub target is a building. */
6536 if (order_sub_tgt < 0
6537 || order_sub_tgt >= loading->improvement.size
6538 || !loading->improvement.order[order_sub_tgt]) {
6539 /* Sub target is invalid. */
6540 log_sg("Cannot find building %d for %s to %s",
6543 order->sub_target = B_LAST;
6544 } else {
6545 struct impr_type *pimprove
6546 = improvement_by_rule_name(loading->improvement.order[order_sub_tgt]);
6547
6548 if (pimprove != NULL) {
6549 order->sub_target = improvement_index(pimprove);
6550 }
6551 }
6552 break;
6553 case ASTK_TECH:
6554 /* Sub target is a technology. */
6555 {
6556 bool failure = order_sub_tgt < 0
6557 || order_sub_tgt >= loading->technology.size
6558 || !loading->technology.order[order_sub_tgt];
6559 struct advance *padvance = NULL;
6560
6561 if (!failure) {
6562 padvance = advance_by_rule_name(loading->technology.order[order_sub_tgt]);
6563 }
6564 if (padvance == NULL) {
6565 /* Target tech is invalid. */
6566 log_sg("Cannot find tech %d for %s to steal",
6568 order->sub_target = A_NONE;
6569 } else {
6571 }
6572 }
6573 break;
6574 case ASTK_EXTRA:
6576 /* These take an extra. */
6578 break;
6579 case ASTK_NONE:
6580 /* None of these can take a sub target. */
6582 "Specified sub target for action %d unsupported.",
6583 order->action);
6584 order->sub_target = NO_TARGET;
6585 break;
6586 case ASTK_COUNT:
6588 "Bad action action %d.",
6589 order->action);
6590 order->sub_target = NO_TARGET;
6591 break;
6592 }
6593 }
6594
6595 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6596 enum unit_activity act;
6597
6599 || !loading->extra.order[order_sub_tgt]) {
6600 if (order_sub_tgt != EXTRA_NONE) {
6601 log_sg("Cannot find extra %d for %s to build",
6603 }
6604
6605 order->sub_target = EXTRA_NONE;
6606 } else {
6607 order->sub_target = extra_index(loading->extra.order[order_sub_tgt]);
6608 }
6609
6610 /* An action or an activity may require an extra target. */
6611 if (action_wants_extra) {
6612 act = action_id_get_activity(order->action);
6613 } else {
6614 act = order->activity;
6615 }
6616
6617 if (unit_activity_is_valid(act)
6619 && order->sub_target == EXTRA_NONE) {
6620 /* Missing required action extra target. */
6622 punit->orders.list = NULL;
6623 punit->orders.length = 0;
6625 punit->goto_tile = NULL;
6626 break;
6627 }
6628 } else if (order->order != ORDER_PERFORM_ACTION) {
6629 if (order_sub_tgt != -1) {
6630 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6631 order_sub_tgt, -1, order->order);
6632 }
6633 order->sub_target = NO_TARGET;
6634 }
6635 }
6636
6637 for (; j < orders_max_length; j++) {
6639 "%s.action_vec,%d", unitstr, j);
6641 "%s.tgt_vec,%d", unitstr, j);
6643 "%s.sub_tgt_vec,%d", unitstr, j);
6644 }
6645 } else {
6646 int j;
6647
6649
6650 /* Never nullify goto_tile for a unit that is in active goto. */
6651 if (punit->activity != ACTIVITY_GOTO) {
6652 punit->goto_tile = NULL;
6653 }
6654
6655 punit->orders.list = NULL;
6656 punit->orders.length = 0;
6657
6658 secfile_entry_ignore(loading->file, "%s.orders_index", unitstr);
6659 secfile_entry_ignore(loading->file, "%s.orders_repeat", unitstr);
6660 secfile_entry_ignore(loading->file, "%s.orders_vigilant", unitstr);
6661 secfile_entry_ignore(loading->file, "%s.orders_list", unitstr);
6662 secfile_entry_ignore(loading->file, "%s.dir_list", unitstr);
6663 secfile_entry_ignore(loading->file, "%s.activity_list", unitstr);
6664 secfile_entry_ignore(loading->file, "%s.action_vec", unitstr);
6665 secfile_entry_ignore(loading->file, "%s.tgt_vec", unitstr);
6666 secfile_entry_ignore(loading->file, "%s.sub_tgt_vec", unitstr);
6667
6668 for (j = 1; j < orders_max_length; j++) {
6670 "%s.action_vec,%d", unitstr, j);
6672 "%s.tgt_vec,%d", unitstr, j);
6674 "%s.sub_tgt_vec,%d", unitstr, j);
6675 }
6676 }
6677 }
6678
6679 return TRUE;
6680}
6681
6682/************************************************************************/
6687 struct player *plr)
6688{
6689 int nunits, i, plrno = player_number(plr);
6690
6691 /* Check status and return if not OK (sg_success FALSE). */
6692 sg_check_ret();
6693
6694 /* Recheck the number of units for the player. This is a copied from
6695 * sg_load_player_units(). */
6697 "player%d.nunits", plrno),
6698 "%s", secfile_error());
6699 if (!plr->is_alive && nunits > 0) {
6700 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6701 nunits = 0; /* Some old savegames may be buggy. */
6702 }
6703
6704 for (i = 0; i < nunits; i++) {
6705 int id_unit, id_trans;
6706 struct unit *punit, *ptrans;
6707
6709 "player%d.u%d.id",
6710 plrno, i);
6712 fc_assert_action(punit != NULL, continue);
6713
6715 "player%d.u%d.transported_by",
6716 plrno, i);
6717 if (id_trans == -1) {
6718 /* Not transported. */
6719 continue;
6720 }
6721
6723 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6724
6725 if (ptrans) {
6726#ifndef FREECIV_NDEBUG
6727 bool load_success =
6728#endif
6730
6731 fc_assert_action(load_success, continue);
6732 }
6733 }
6734}
6735
6736/************************************************************************/
6740 struct player *plr)
6741{
6742 int i = 0;
6743 int longest_order = 0;
6744 int plrno = player_number(plr);
6745
6746 /* Check status and return if not OK (sg_success FALSE). */
6747 sg_check_ret();
6748
6750 "player%d.nunits", plrno);
6751
6752 /* Find the longest unit order so different order length won't break
6753 * storing units in the tabular format. */
6755 if (punit->has_orders) {
6756 if (longest_order < punit->orders.length) {
6758 }
6759 }
6761
6763 "player%d.orders_max_length", plrno);
6764
6766 char buf[32];
6767 char dirbuf[2] = " ";
6768 int nat_x, nat_y;
6769 int last_order, j;
6770
6771 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6772 dirbuf[0] = dir2char(punit->facing);
6773 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6774
6776 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6777 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6778
6779 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6782 "%s.nationality", buf);
6783 }
6784 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6785 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6786 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6788 "%s.type_by_name", buf);
6789
6790 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6792 "%s.activity_count", buf);
6793 if (punit->action == ACTION_NONE) {
6794 secfile_insert_int(saving->file, -1, "%s.action", buf);
6795 } else {
6796 secfile_insert_int(saving->file, punit->action, "%s.action", buf);
6797 }
6798 if (punit->activity_target == NULL) {
6799 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6800 } else {
6802 "%s.activity_tgt", buf);
6803 }
6804
6806 "%s.changed_from", buf);
6808 "%s.changed_from_count", buf);
6809 if (punit->changed_from_target == NULL) {
6810 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6811 } else {
6813 "%s.changed_from_tgt", buf);
6814 }
6815
6817 "%s.done_moving", buf);
6818 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6819 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6821 "%s.born", buf);
6823 "%s.current_form_turn", buf);
6825 "%s.battlegroup", buf);
6826
6827 if (punit->goto_tile) {
6829 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6830 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6831 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6832 } else {
6833 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6834 /* Set this values to allow saving it as table. */
6835 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6836 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6837 }
6838
6840 "%s.server_side_agent", buf);
6841
6842 /* Save AI data of the unit. */
6843 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6844
6846 "%s.ord_map", buf);
6848 "%s.ord_city", buf);
6849 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6851 "%s.paradropped", buf);
6853 ? unit_transport_get(punit)->id : -1,
6854 "%s.transported_by", buf);
6855 if (punit->carrying != NULL) {
6857 "%s.carrying", buf);
6858 } else {
6859 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6860 }
6861
6863 "%s.action_decision", buf);
6864
6865 /* Stored as tile rather than direction to make sure the target tile is
6866 * sane. */
6871 "%s.action_decision_tile_x", buf);
6873 "%s.action_decision_tile_y", buf);
6874 } else {
6875 /* Dummy values to get tabular format. */
6876 secfile_insert_int(saving->file, -1,
6877 "%s.action_decision_tile_x", buf);
6878 secfile_insert_int(saving->file, -1,
6879 "%s.action_decision_tile_y", buf);
6880 }
6881
6883 "%s.stay", buf);
6884
6885 if (punit->has_orders) {
6886 int len = punit->orders.length;
6887 char orders_buf[len + 1], dir_buf[len + 1];
6888 char act_buf[len + 1];
6889 int action_buf[len];
6890 int tgt_vec[len];
6891 int sub_tgt_vec[len];
6892
6893 last_order = len;
6894
6895 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6897 "%s.orders_index", buf);
6899 "%s.orders_repeat", buf);
6901 "%s.orders_vigilant", buf);
6902
6903 for (j = 0; j < len; j++) {
6905 dir_buf[j] = '?';
6906 act_buf[j] = '?';
6907 tgt_vec[j] = NO_TARGET;
6908 sub_tgt_vec[j] = -1;
6909 action_buf[j] = -1;
6910 switch (punit->orders.list[j].order) {
6911 case ORDER_MOVE:
6912 case ORDER_ACTION_MOVE:
6913 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6914 break;
6915 case ORDER_ACTIVITY:
6919 break;
6922 tgt_vec[j] = punit->orders.list[j].target;
6924 break;
6925 case ORDER_FULL_MP:
6926 case ORDER_LAST:
6927 break;
6928 }
6929
6930 if (action_buf[j] == ACTION_NONE) {
6931 action_buf[j] = -1;
6932 }
6933 }
6934 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6935
6936 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6937 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6938 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6939
6941 "%s.action_vec", buf);
6942 /* Fill in dummy values for order targets so the registry will save
6943 * the unit table in a tabular format. */
6944 for (j = last_order; j < longest_order; j++) {
6945 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6946 }
6947
6949 "%s.tgt_vec", buf);
6950 /* Fill in dummy values for order targets so the registry will save
6951 * the unit table in a tabular format. */
6952 for (j = last_order; j < longest_order; j++) {
6953 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6954 }
6955
6957 "%s.sub_tgt_vec", buf);
6958 /* Fill in dummy values for order targets so the registry will save
6959 * the unit table in a tabular format. */
6960 for (j = last_order; j < longest_order; j++) {
6961 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6962 }
6963 } else {
6964
6965 /* Put all the same fields into the savegame - otherwise the
6966 * registry code can't correctly use a tabular format and the
6967 * savegame will be bigger. */
6968 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6969 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6970 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6971 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6972 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6973 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6974 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6975
6976 /* Fill in dummy values for order targets so the registry will save
6977 * the unit table in a tabular format. */
6978
6979 /* The start of a vector has no number. */
6980 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6981 for (j = 1; j < longest_order; j++) {
6982 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6983 }
6984
6985 /* The start of a vector has no number. */
6986 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6987 for (j = 1; j < longest_order; j++) {
6988 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6989 }
6990
6991 /* The start of a vector has no number. */
6992 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6993 for (j = 1; j < longest_order; j++) {
6994 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6995 }
6996 }
6997
6998 i++;
7000}
7001
7002/************************************************************************/
7006 struct player *plr)
7007{
7008 int plrno = player_number(plr);
7009
7010 /* Check status and return if not OK (sg_success FALSE). */
7011 sg_check_ret();
7012
7013 /* Toss any existing attribute_block (should not exist) */
7014 if (plr->attribute_block.data) {
7016 plr->attribute_block.data = NULL;
7017 }
7018
7019 /* This is a big heap of opaque data for the client, check everything! */
7021 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
7022
7023 if (0 > plr->attribute_block.length) {
7024 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
7025 plr->attribute_block.length);
7026 plr->attribute_block.length = 0;
7027 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
7028 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
7030 plr->attribute_block.length = 0;
7031 } else if (0 < plr->attribute_block.length) {
7032 int part_nr, parts;
7033 int quoted_length;
7034 char *quoted;
7035#ifndef FREECIV_NDEBUG
7036 size_t actual_length;
7037#endif
7038
7041 "player%d.attribute_v2_block_length_quoted",
7042 plrno), "%s", secfile_error());
7045 "player%d.attribute_v2_block_parts", plrno),
7046 "%s", secfile_error());
7047
7049 quoted[0] = '\0';
7051 for (part_nr = 0; part_nr < parts; part_nr++) {
7052 const char *current =
7054 "player%d.attribute_v2_block_data.part%d",
7055 plrno, part_nr);
7056 if (!current) {
7057 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
7058 break;
7059 }
7060 log_debug("attribute_v2_block_length_quoted=%d"
7061 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
7062 quoted_length, strlen(quoted), strlen(current));
7063 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
7064 strcat(quoted, current);
7065 }
7067 "attribute_v2_block_length_quoted=%d"
7068 " actual=" SIZE_T_PRINTF,
7070
7071#ifndef FREECIV_NDEBUG
7073#endif
7075 plr->attribute_block.data,
7076 plr->attribute_block.length);
7078 free(quoted);
7079 }
7080}
7081
7082/************************************************************************/
7086 struct player *plr)
7087{
7088 int plrno = player_number(plr);
7089
7090 /* Check status and return if not OK (sg_success FALSE). */
7091 sg_check_ret();
7092
7093 /* This is a big heap of opaque data from the client. Although the binary
7094 * format is not user editable, keep the lines short enough for debugging,
7095 * and hope that data compression will keep the file a reasonable size.
7096 * Note that the "quoted" format is a multiple of 3.
7097 */
7098#define PART_SIZE (3*256)
7099#define PART_ADJUST (3)
7100 if (plr->attribute_block.data) {
7101 char part[PART_SIZE + PART_ADJUST];
7102 int parts;
7103 int current_part_nr;
7105 plr->attribute_block.length);
7106 char *quoted_at = strchr(quoted, ':');
7107 size_t bytes_left = strlen(quoted);
7108 size_t bytes_at_colon = 1 + (quoted_at - quoted);
7110
7112 "player%d.attribute_v2_block_length", plrno);
7114 "player%d.attribute_v2_block_length_quoted", plrno);
7115
7116 /* Try to wring some compression efficiencies out of the "quoted" format.
7117 * The first line has a variable length decimal, mis-aligning triples.
7118 */
7119 if ((bytes_left - bytes_adjust) > PART_SIZE) {
7120 /* first line can be longer */
7121 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
7122 } else {
7123 parts = 1;
7124 }
7125
7127 "player%d.attribute_v2_block_parts", plrno);
7128
7129 if (parts > 1) {
7131
7132 /* first line can be longer */
7134 part[size_of_current_part] = '\0';
7136 "player%d.attribute_v2_block_data.part%d",
7137 plrno, 0);
7140 current_part_nr = 1;
7141 } else {
7142 quoted_at = quoted;
7143 current_part_nr = 0;
7144 }
7145
7148
7150 part[size_of_current_part] = '\0';
7152 "player%d.attribute_v2_block_data.part%d",
7153 plrno,
7157 }
7158 fc_assert(bytes_left == 0);
7159 free(quoted);
7160 }
7161#undef PART_ADJUST
7162#undef PART_SIZE
7163}
7164
7165/************************************************************************/
7169 struct player *plr)
7170{
7171 int plrno = player_number(plr);
7172 int total_ncities
7174 "player%d.dc_total", plrno);
7175 int i;
7176 bool someone_alive = FALSE;
7177
7178 /* Check status and return if not OK (sg_success FALSE). */
7179 sg_check_ret();
7180
7183 if (pteam_member->is_alive) {
7185 break;
7186 }
7188
7189 if (!someone_alive) {
7190 /* Reveal all for completely dead teams. */
7192 }
7193 }
7194
7195 if (-1 == total_ncities
7196 || !game.info.fogofwar
7198 "game.save_private_map")) {
7199 /* We have:
7200 * - a dead player;
7201 * - fogged cities are not saved for any reason;
7202 * - a savegame with fog of war turned off;
7203 * - or game.save_private_map is not set to FALSE in the scenario /
7204 * savegame. The players private knowledge is set to be what they could
7205 * see without fog of war. */
7206 whole_map_iterate(&(wld.map), ptile) {
7207 if (map_is_known(ptile, plr)) {
7208 struct city *pcity = tile_city(ptile);
7209
7210 update_player_tile_last_seen(plr, ptile);
7211 update_player_tile_knowledge(plr, ptile);
7212
7213 if (NULL != pcity) {
7214 update_dumb_city(plr, pcity);
7215 }
7216 }
7218
7219 /* Nothing more to do; */
7220 return;
7221 }
7222
7223 /* Load player map (terrain). */
7224 LOAD_MAP_CHAR(ch, ptile,
7225 map_get_player_tile(ptile, plr)->terrain
7226 = char2terrain(ch), loading->file,
7227 "player%d.map_t%04d", plrno);
7228
7229 /* Load player map (extras). */
7230 halfbyte_iterate_extras(j, loading->extra.size) {
7231 LOAD_MAP_CHAR(ch, ptile,
7233 ch, loading->extra.order + 4 * j),
7234 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7236
7237 whole_map_iterate(&(wld.map), ptile) {
7238 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7239 bool regr_warn = FALSE;
7240
7242 int pres_id = extra_number(pres);
7243
7244 if (BV_ISSET(plrtile->extras, pres_id)) {
7245 if (plrtile->terrain == nullptr) {
7246 if (!regr_warn) {
7247 sg_regr(3030000, "FoW tile (%d, %d) has extras, though it's on unknown.",
7248 TILE_XY(ptile));
7249 regr_warn = TRUE;
7250 }
7251 BV_CLR(plrtile->extras, pres_id);
7252 } else {
7253 plrtile->resource = pres;
7254 if (!terrain_has_resource(plrtile->terrain, pres)) {
7255 BV_CLR(plrtile->extras, pres_id);
7256 }
7257 }
7258 }
7261
7263 /* Load player map (border). */
7264 int x, y;
7265
7266 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7267 const char *buffer
7268 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7269 plrno, y);
7270 const char *buffer2
7271 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7272 plrno, y);
7273 const char *ptr = buffer;
7274 const char *ptr2 = buffer2;
7275
7276 sg_failure_ret(NULL != buffer,
7277 "Savegame corrupt - map line %d not found.", y);
7278 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7279 char token[TOKEN_SIZE];
7280 char token2[TOKEN_SIZE];
7281 int number;
7282 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7283
7284 scanin(&ptr, ",", token, sizeof(token));
7285 sg_failure_ret('\0' != token[0],
7286 "Savegame corrupt - map size not correct.");
7287 if (strcmp(token, "-") == 0) {
7288 map_get_player_tile(ptile, plr)->owner = NULL;
7289 } else {
7290 sg_failure_ret(str_to_int(token, &number),
7291 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7292 token, x, y);
7293 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7294 }
7295
7296 scanin(&ptr2, ",", token2, sizeof(token2));
7297 sg_failure_ret('\0' != token2[0],
7298 "Savegame corrupt - map size not correct.");
7299 if (strcmp(token2, "-") == 0) {
7300 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7301 } else {
7303 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7304 token, x, y);
7305 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7306 }
7307 }
7308 }
7309 }
7310
7311 /* Load player map (update time). */
7312 for (i = 0; i < 4; i++) {
7313 /* put 4-bit segments of 16-bit "updated" field */
7314 if (i == 0) {
7315 LOAD_MAP_CHAR(ch, ptile,
7316 map_get_player_tile(ptile, plr)->last_updated
7317 = ascii_hex2bin(ch, i),
7318 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7319 } else {
7320 LOAD_MAP_CHAR(ch, ptile,
7321 map_get_player_tile(ptile, plr)->last_updated
7322 |= ascii_hex2bin(ch, i),
7323 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7324 }
7325 }
7326
7327 /* Load player map known cities. */
7328 for (i = 0; i < total_ncities; i++) {
7329 struct vision_site *pdcity;
7330 char buf[32];
7331 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7332
7336 pdcity);
7338 } else {
7339 /* Error loading the data. */
7340 log_sg("Skipping seen city %d for player %d.", i, plrno);
7341 if (pdcity != NULL) {
7343 }
7344 }
7345 }
7346
7347 /* Repair inconsistent player maps. */
7348 whole_map_iterate(&(wld.map), ptile) {
7349 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7350 struct city *pcity = tile_city(ptile);
7351
7352 update_player_tile_knowledge(plr, ptile);
7353 reality_check_city(plr, ptile);
7354
7355 if (NULL != pcity) {
7356 update_dumb_city(plr, pcity);
7357 }
7358 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7359 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7360 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7361
7362 plrtile->owner = tile_owner(ptile);
7363 }
7365}
7366
7367/************************************************************************/
7371 struct player *plr,
7372 struct vision_site *pdcity,
7373 const char *citystr)
7374{
7375 const char *str;
7376 int i, id, size;
7377 citizens city_size;
7378 int nat_x, nat_y;
7379 const char *stylename;
7380 enum capital_type cap;
7381 const char *vname;
7382
7384 citystr),
7385 FALSE, "%s", secfile_error());
7387 citystr),
7388 FALSE, "%s", secfile_error());
7389 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7390 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7391 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7392
7393 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7394 citystr),
7395 FALSE, "%s", secfile_error());
7396 pdcity->owner = player_by_number(id);
7397 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7398 "%s has invalid owner (%d); skipping.", citystr, id);
7399
7400 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.original",
7401 citystr),
7402 FALSE, "%s", secfile_error());
7403 if (id >= 0) {
7404 pdcity->original = player_by_number(id);
7405 sg_warn_ret_val(NULL != pdcity->original, FALSE,
7406 "%s has invalid original owner (%d); skipping.", citystr, id);
7407 } else {
7408 pdcity->original = nullptr;
7409 }
7410
7412 "%s.id", citystr),
7413 FALSE, "%s", secfile_error());
7415 "%s has invalid id (%d); skipping.", citystr, id);
7416
7418 "%s.size", citystr),
7419 FALSE, "%s", secfile_error());
7420 city_size = (citizens)size; /* set the correct type */
7421 sg_warn_ret_val(size == (int)city_size, FALSE,
7422 "Invalid city size: %d; set to %d.", size, city_size);
7423 vision_site_size_set(pdcity, city_size);
7424
7425 /* Initialise list of improvements */
7426 BV_CLR_ALL(pdcity->improvements);
7427 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7429 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7430 "Invalid length of '%s.improvements' ("
7431 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7432 citystr, strlen(str), loading->improvement.size);
7433 for (i = 0; i < loading->improvement.size; i++) {
7434 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7435 "Undefined value '%c' within '%s.improvements'.",
7436 str[i], citystr)
7437
7438 if (str[i] == '1') {
7439 struct impr_type *pimprove =
7440 improvement_by_rule_name(loading->improvement.order[i]);
7441 if (pimprove) {
7442 BV_SET(pdcity->improvements, improvement_index(pimprove));
7443 }
7444 }
7445 }
7446
7448 "%s.name", citystr);
7449
7450 if (vname != NULL) {
7451 pdcity->name = fc_strdup(vname);
7452 }
7453
7455 "%s.occupied", citystr);
7457 "%s.walls", citystr);
7459 "%s.happy", citystr);
7461 "%s.unhappy", citystr);
7463 "%s.style", citystr);
7464 if (stylename != NULL) {
7466 } else {
7467 pdcity->style = 0;
7468 }
7469 if (pdcity->style < 0) {
7470 pdcity->style = 0;
7471 }
7472
7473 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7474 "%s.city_image", citystr);
7475
7477 "%s.capital", citystr),
7479
7481 pdcity->capital = cap;
7482 } else {
7483 pdcity->capital = CAPITAL_NOT;
7484 }
7485
7486 return TRUE;
7487}
7488
7489/************************************************************************/
7493 struct player *plr)
7494{
7495 int i, plrno = player_number(plr);
7496
7497 /* Check status and return if not OK (sg_success FALSE). */
7498 sg_check_ret();
7499
7501 /* The player can see all, there's no reason to save the private map. */
7502 return;
7503 }
7504
7505 /* Save the map (terrain). */
7506 SAVE_MAP_CHAR(ptile,
7508 saving->file, "player%d.map_t%04d", plrno);
7509
7511 /* Save the map (borders). */
7512 int x, y;
7513
7514 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7516
7517 line[0] = '\0';
7518 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7519 char token[TOKEN_SIZE];
7520 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7521 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7522
7523 if (plrtile == NULL || plrtile->owner == NULL) {
7524 strcpy(token, "-");
7525 } else {
7526 fc_snprintf(token, sizeof(token), "%d",
7527 player_number(plrtile->owner));
7528 }
7529 strcat(line, token);
7530 if (x < MAP_NATIVE_WIDTH) {
7531 strcat(line, ",");
7532 }
7533 }
7534 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7535 plrno, y);
7536 }
7537
7538 for (y = 0; y < MAP_NATIVE_HEIGHT; y++) {
7540
7541 line[0] = '\0';
7542 for (x = 0; x < MAP_NATIVE_WIDTH; x++) {
7543 char token[TOKEN_SIZE];
7544 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7545 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7546
7547 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7548 strcpy(token, "-");
7549 } else {
7550 fc_snprintf(token, sizeof(token), "%d",
7551 player_number(plrtile->extras_owner));
7552 }
7553 strcat(line, token);
7554 if (x < MAP_NATIVE_WIDTH) {
7555 strcat(line, ",");
7556 }
7557 }
7558 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7559 plrno, y);
7560 }
7561 }
7562
7563 /* Save the map (extras). */
7565 int mod[4];
7566 int l;
7567
7568 for (l = 0; l < 4; l++) {
7569 if (4 * j + 1 > game.control.num_extra_types) {
7570 mod[l] = -1;
7571 } else {
7572 mod[l] = 4 * j + l;
7573 }
7574 }
7575
7576 SAVE_MAP_CHAR(ptile,
7578 map_get_player_tile(ptile, plr)->resource,
7579 mod),
7580 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7582
7583 /* Save the map (update time). */
7584 for (i = 0; i < 4; i++) {
7585 /* put 4-bit segments of 16-bit "updated" field */
7586 SAVE_MAP_CHAR(ptile,
7588 map_get_player_tile(ptile, plr)->last_updated, i),
7589 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7590 }
7591
7592 /* Save known cities. */
7593 i = 0;
7594 whole_map_iterate(&(wld.map), ptile) {
7595 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7596 char impr_buf[B_LAST + 1];
7597 char buf[32];
7598
7599 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7600
7601 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7602 int nat_x, nat_y;
7603
7605 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7606 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7607
7608 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7610 "%s.owner", buf);
7611 if (pdcity->original != nullptr) {
7613 "%s.original", buf);
7614 } else {
7615 secfile_insert_int(saving->file, -1, "%s.original", buf);
7616 }
7617
7619 "%s.size", buf);
7620 secfile_insert_bool(saving->file, pdcity->occupied,
7621 "%s.occupied", buf);
7622 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7623 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7624 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7626 "%s.style", buf);
7627 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7629 "%s.capital", buf);
7630
7631 /* Save improvement list as bitvector. Note that improvement order
7632 * is saved in savefile.improvement.order. */
7633 improvement_iterate(pimprove) {
7634 impr_buf[improvement_index(pimprove)]
7635 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7636 ? '1' : '0';
7638 impr_buf[improvement_count()] = '\0';
7640 "Invalid size of the improvement vector (%s.improvements: "
7641 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7642 buf, strlen(impr_buf), sizeof(impr_buf));
7643 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7644 if (pdcity->name != NULL) {
7645 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7646 }
7647
7648 i++;
7649 }
7651
7652 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7653}
7654
7655/* =======================================================================
7656 * Load / save the researches.
7657 * ======================================================================= */
7658
7659/************************************************************************/
7663{
7664 struct research *presearch;
7665 int count;
7666 int number;
7667 const char *str;
7668 int i, j;
7669 int *vlist_research;
7670
7672 /* Check status and return if not OK (sg_success FALSE). */
7673 sg_check_ret();
7674
7675 /* Initialize all researches. */
7679
7680 /* May be unsaved (e.g. scenario case). */
7681 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7682 for (i = 0; i < count; i++) {
7684 "research.r%d.number", i),
7685 "%s", secfile_error());
7686 presearch = research_by_number(number);
7688 "Invalid research number %d in 'research.r%d.number'",
7689 number, i);
7690
7691 presearch->tech_goal = technology_load(loading->file,
7692 "research.r%d.goal", i);
7694 &presearch->future_tech,
7695 "research.r%d.futuretech", i),
7696 "%s", secfile_error());
7698 &presearch->bulbs_researched,
7699 "research.r%d.bulbs", i),
7700 "%s", secfile_error());
7702 &presearch->bulbs_researching_saved,
7703 "research.r%d.bulbs_before", i),
7704 "%s", secfile_error());
7705 presearch->researching_saved = technology_load(loading->file,
7706 "research.r%d.saved", i);
7707 presearch->researching = technology_load(loading->file,
7708 "research.r%d.now", i);
7710 &presearch->free_bulbs,
7711 "research.r%d.free_bulbs", i),
7712 "%s", secfile_error());
7713
7714 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7715 sg_failure_ret(str != NULL, "%s", secfile_error());
7716 sg_failure_ret(strlen(str) == loading->technology.size,
7717 "Invalid length of 'research.r%d.done' ("
7718 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7719 i, strlen(str), loading->technology.size);
7720 for (j = 0; j < loading->technology.size; j++) {
7721 sg_failure_ret(str[j] == '1' || str[j] == '0',
7722 "Undefined value '%c' within 'research.r%d.done'.",
7723 str[j], i);
7724
7725 if (str[j] == '1') {
7726 struct advance *padvance
7727 = advance_by_rule_name(loading->technology.order[j]);
7728
7729 if (padvance) {
7731 TECH_KNOWN);
7732 }
7733 }
7734 }
7735
7737 size_t count_res;
7738 int tn;
7739
7741 "research.r%d.vbs", i);
7742
7743 for (tn = 0; tn < count_res; tn++) {
7744 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7745
7746 if (padvance != NULL) {
7747 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7748 = vlist_research[tn];
7749 }
7750 }
7751 }
7752 }
7753
7754 /* In case of tech_leakage, we can update research only after all the
7755 * researches have been loaded */
7759}
7760
7761/************************************************************************/
7765{
7766 char invs[A_LAST];
7767 int i = 0;
7768 int *vlist_research;
7769
7771 /* Check status and return if not OK (sg_success FALSE). */
7772 sg_check_ret();
7773
7774 if (saving->save_players) {
7777 "research.r%d.number", i);
7778 technology_save(saving->file, "research.r%d.goal",
7779 i, presearch->tech_goal);
7780 secfile_insert_int(saving->file, presearch->future_tech,
7781 "research.r%d.futuretech", i);
7782 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7783 "research.r%d.bulbs_before", i);
7787 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7791 "research.r%d.vbs", i);
7792 if (vlist_research) {
7794 }
7795 }
7796 technology_save(saving->file, "research.r%d.saved",
7797 i, presearch->researching_saved);
7798 secfile_insert_int(saving->file, presearch->bulbs_researched,
7799 "research.r%d.bulbs", i);
7800 technology_save(saving->file, "research.r%d.now",
7801 i, presearch->researching);
7802 secfile_insert_int(saving->file, presearch->free_bulbs,
7803 "research.r%d.free_bulbs", i);
7804 /* Save technology lists as bytevector. Note that technology order is
7805 * saved in savefile.technology.order */
7806 advance_index_iterate(A_NONE, tech_id) {
7807 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7809 == TECH_KNOWN ? '1' : '0');
7812 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7813 i++;
7815 secfile_insert_int(saving->file, i, "research.count");
7816 }
7817}
7818
7819/* =======================================================================
7820 * Load / save the event cache. Should be the last thing to do.
7821 * ======================================================================= */
7822
7823/************************************************************************/
7827{
7828 /* Check status and return if not OK (sg_success FALSE). */
7829 sg_check_ret();
7830
7831 event_cache_load(loading->file, "event_cache");
7832}
7833
7834/************************************************************************/
7838{
7839 /* Check status and return if not OK (sg_success FALSE). */
7840 sg_check_ret();
7841
7842 if (saving->scenario) {
7843 /* Do _not_ save events in a scenario. */
7844 return;
7845 }
7846
7847 event_cache_save(saving->file, "event_cache");
7848}
7849
7850/* =======================================================================
7851 * Load / save the open treaties
7852 * ======================================================================= */
7853
7854/************************************************************************/
7858{
7859 int tidx;
7860 const char *plr0;
7861
7862 /* Check status and return if not OK (sg_success FALSE). */
7863 sg_check_ret();
7864
7865 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7866 "treaty%d.plr0", tidx)) != NULL ;
7867 tidx++) {
7868 const char *plr1;
7869 const char *ct;
7870 int cidx;
7871 struct player *p0, *p1;
7872
7873 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7874
7875 p0 = player_by_name(plr0);
7876 p1 = player_by_name(plr1);
7877
7878 if (p0 == NULL || p1 == NULL) {
7879 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7880 } else {
7881 struct treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7882
7885
7886 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7887 "treaty%d.clause%d.type",
7888 tidx, cidx)) != NULL ;
7889 cidx++ ) {
7891 const char *plrx;
7892
7893 if (!clause_type_is_valid(type)) {
7894 log_error("Invalid clause type \"%s\"", ct);
7895 } else {
7896 struct player *pgiver = NULL;
7897
7898 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7899 tidx, cidx);
7900
7901 if (!fc_strcasecmp(plrx, plr0)) {
7902 pgiver = p0;
7903 } else if (!fc_strcasecmp(plrx, plr1)) {
7904 pgiver = p1;
7905 } else {
7906 log_error("Clause giver %s is not participant of the treaty"
7907 "between %s and %s", plrx, plr0, plr1);
7908 }
7909
7910 if (pgiver != NULL) {
7911 int value;
7912
7913 value = secfile_lookup_int_default(loading->file, 0,
7914 "treaty%d.clause%d.value",
7915 tidx, cidx);
7916
7917 add_clause(ptreaty, pgiver, type, value, NULL);
7918 }
7919 }
7920 }
7921
7922 /* These must be after clauses have been added so that acceptance
7923 * does not get cleared by what seems like changes to the treaty. */
7925 "treaty%d.accept0", tidx);
7927 "treaty%d.accept1", tidx);
7928 }
7929 }
7930}
7931
7932typedef struct {
7933 int tidx;
7936
7937/************************************************************************/
7940static void treaty_save(struct treaty *ptr, void *data_in)
7941{
7942 char tpath[512];
7943 int cidx = 0;
7945
7946 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7947
7948 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7949 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7950 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7951 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7952
7954 char cpath[512];
7955
7956 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7957
7958 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7959 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7960 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7962}
7963
7964/************************************************************************/
7968{
7969 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7970
7972}
7973
7974/* =======================================================================
7975 * Load / save the history report
7976 * ======================================================================= */
7977
7978/************************************************************************/
7982{
7984 int turn;
7985
7986 /* Check status and return if not OK (sg_success FALSE). */
7987 sg_check_ret();
7988
7989 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7990
7991 if (turn != -2) {
7992 hist->turn = turn;
7993 }
7994
7995 if (turn + 1 >= game.info.turn) {
7996 const char *str;
7997
7998 str = secfile_lookup_str(loading->file, "history.title");
7999 sg_failure_ret(str != NULL, "%s", secfile_error());
8000 sz_strlcpy(hist->title, str);
8001 str = secfile_lookup_str(loading->file, "history.body");
8002 sg_failure_ret(str != NULL, "%s", secfile_error());
8003 sz_strlcpy(hist->body, str);
8004 }
8005}
8006
8007/************************************************************************/
8010static void sg_save_history(struct savedata *saving)
8011{
8013
8014 secfile_insert_int(saving->file, hist->turn, "history.turn");
8015
8016 if (hist->turn + 1 >= game.info.turn) {
8017 secfile_insert_str(saving->file, hist->title, "history.title");
8018 secfile_insert_str(saving->file, hist->body, "history.body");
8019 }
8020}
8021
8022/* =======================================================================
8023 * Load / save the mapimg definitions.
8024 * ======================================================================= */
8025
8026/************************************************************************/
8029static void sg_load_mapimg(struct loaddata *loading)
8030{
8031 int mapdef_count, i;
8032
8033 /* Check status and return if not OK (sg_success FALSE). */
8034 sg_check_ret();
8035
8036 /* Clear all defined map images. */
8037 while (mapimg_count() > 0) {
8038 mapimg_delete(0);
8039 }
8040
8042 "mapimg.count");
8043 log_verbose("Saved map image definitions: %d.", mapdef_count);
8044
8045 if (0 >= mapdef_count) {
8046 return;
8047 }
8048
8049 for (i = 0; i < mapdef_count; i++) {
8050 const char *p;
8051
8052 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
8053 if (NULL == p) {
8054 log_verbose("[Mapimg %4d] Missing definition.", i);
8055 continue;
8056 }
8057
8058 if (!mapimg_define(p, FALSE)) {
8059 log_error("Invalid map image definition %4d: %s.", i, p);
8060 }
8061
8062 log_verbose("Mapimg %4d loaded.", i);
8063 }
8064}
8065
8066/************************************************************************/
8069static void sg_save_mapimg(struct savedata *saving)
8070{
8071 /* Check status and return if not OK (sg_success FALSE). */
8072 sg_check_ret();
8073
8074 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
8075 if (mapimg_count() > 0) {
8076 int i;
8077
8078 for (i = 0; i < mapimg_count(); i++) {
8079 char buf[MAX_LEN_MAPDEF];
8080
8081 mapimg_id2str(i, buf, sizeof(buf));
8082 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
8083 }
8084 }
8085}
8086
8087/* =======================================================================
8088 * Sanity checks for loading / saving a game.
8089 * ======================================================================= */
8090
8091/************************************************************************/
8095{
8096 int players;
8097
8098 /* Check status and return if not OK (sg_success FALSE). */
8099 sg_check_ret();
8100
8101 if (game.info.is_new_game) {
8102 /* Nothing to do for new games (or not started scenarios). */
8103 return;
8104 }
8105
8106 /* Old savegames may have maxplayers lower than current player count,
8107 * fix. */
8108 players = normal_player_count();
8109 if (game.server.max_players < players) {
8110 log_verbose("Max players lower than current players, fixing");
8111 game.server.max_players = players;
8112 }
8113
8114 /* Fix ferrying sanity */
8115 players_iterate(pplayer) {
8116 unit_list_iterate_safe(pplayer->units, punit) {
8119 log_sg("Removing %s unferried %s in %s at (%d, %d)",
8125 }
8128
8129 /* Fix stacking issues. We don't rely on the savegame preserving
8130 * alliance invariants (old savegames often did not) so if there are any
8131 * unallied units on the same tile we just bounce them. */
8132 players_iterate(pplayer) {
8134 resolve_unit_stacks(pplayer, aplayer, TRUE);
8137
8138 /* Recalculate the potential buildings for each city. Has caused some
8139 * problems with game random state.
8140 * This also changes the game state if you save the game directly after
8141 * loading it and compare the results. */
8142 players_iterate(pplayer) {
8143 /* Building advisor needs data phase open in order to work */
8144 adv_data_phase_init(pplayer, FALSE);
8145 building_advisor(pplayer);
8146 /* Close data phase again so it can be opened again when game starts. */
8147 adv_data_phase_done(pplayer);
8149
8150 /* Prevent a buggy or intentionally crafted save game from crashing
8151 * Freeciv. See hrm Bug #887748 */
8152 players_iterate(pplayer) {
8153 city_list_iterate(pplayer->cities, pcity) {
8154 worker_task_list_iterate(pcity->task_reqs, ptask) {
8155 if (!worker_task_is_sane(ptask)) {
8156 log_error("[city id: %d] Bad worker task %d.",
8157 pcity->id, ptask->act);
8158 worker_task_list_remove(pcity->task_reqs, ptask);
8159 free(ptask);
8160 ptask = NULL;
8161 }
8165
8166 /* Check worked tiles map */
8167#ifdef FREECIV_DEBUG
8168 if (loading->worked_tiles != NULL) {
8169 /* check the entire map for unused worked tiles */
8170 whole_map_iterate(&(wld.map), ptile) {
8171 if (loading->worked_tiles[ptile->index] != -1) {
8172 log_error("[city id: %d] Unused worked tile at (%d, %d).",
8173 loading->worked_tiles[ptile->index], TILE_XY(ptile));
8174 }
8176 }
8177#endif /* FREECIV_DEBUG */
8178
8179 /* Check researching technologies and goals. */
8181 if (presearch->researching != A_UNSET
8182 && !is_future_tech(presearch->researching)
8183 && (valid_advance_by_number(presearch->researching) == NULL
8185 != TECH_PREREQS_KNOWN))) {
8186 log_sg(_("%s had invalid researching technology."),
8188 presearch->researching = A_UNSET;
8189 }
8190 if (presearch->tech_goal != A_UNSET
8191 && !is_future_tech(presearch->tech_goal)
8192 && (valid_advance_by_number(presearch->tech_goal) == NULL
8195 == TECH_KNOWN))) {
8196 log_sg(_("%s had invalid technology goal."),
8198 presearch->tech_goal = A_UNSET;
8199 }
8200
8203
8204 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8205 players_iterate(pplayer) {
8206 int unique_count[U_LAST];
8207
8208 memset(unique_count, 0, sizeof(unique_count));
8209
8210 unit_list_iterate(pplayer->units, punit) {
8213
8216 log_sg(_("%s has multiple units of type %s though it should be possible "
8217 "to have only one."),
8219 }
8222
8223 players_iterate(pplayer) {
8224 unit_list_iterate_safe(pplayer->units, punit) {
8225 if (punit->has_orders
8227 punit->orders.list)) {
8228 log_sg("Invalid unit orders for unit %d.", punit->id);
8230 }
8233
8234 /* Check max rates (rules may have changed since saving) */
8235 players_iterate(pplayer) {
8238
8239 if (0 == strlen(server.game_identifier)
8240 || !is_base64url(server.game_identifier)) {
8241 /* This uses fc_rand(), so random state has to be initialized before. */
8242 randomize_base64url_string(server.game_identifier,
8243 sizeof(server.game_identifier));
8244 }
8245
8246 /* Restore game random state, just in case various initialization code
8247 * inexplicably altered the previously existing state. */
8248 if (!game.info.is_new_game) {
8249 fc_rand_set_state(loading->rstate);
8250 }
8251
8252 /* At the end do the default sanity checks. */
8253 sanity_check();
8254}
8255
8256/************************************************************************/
8260{
8261 /* Check status and return if not OK (sg_success FALSE). */
8262 sg_check_ret();
8263}
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:3455
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2870
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1180
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3382
void destroy_city_virtual(struct city *pcity)
Definition city.c:3541
int city_style_by_rule_name(const char *s)
Definition city.c:1738
#define cities_iterate_end
Definition city.h:514
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
#define cities_iterate(pcity)
Definition city.h:509
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:83
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
#define output_type_iterate(output)
Definition city.h:842
#define FREE_WORKED_TILES
Definition city.h:879
#define MAX_CITY_SIZE
Definition city.h:103
#define city_list_iterate_end
Definition city.h:507
#define I_NEVER
Definition city.h:244
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:227
#define city_tile_iterate_end
Definition city.h:235
#define output_type_iterate_end
Definition city.h:848
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c: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:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:108
struct treaty * ptreaty
Definition diplodlg_g.h:28
void treaty_add(struct treaty *ptreaty)
Definition diptreaty.c:377
void init_treaty(struct treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
bool add_clause(struct treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:396
#define clause_list_iterate_end
Definition diptreaty.h:73
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:71
int int id
Definition editgui_g.h:28
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1128
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
#define extra_type_iterate(_p)
Definition extras.h:315
#define extra_type_iterate_end
Definition extras.h:321
#define is_extra_caused_by(e, c)
Definition extras.h:203
#define extra_index(_e_)
Definition extras.h:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
static char * ruleset
Definition fc_manual.c:163
#define NO_TARGET
Definition fc_types.h: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:3212
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:2461
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2411
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3258
void shuffle_players(void)
Definition plrhand.c:2386
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:3245
void fit_nationset_to_players(void)
Definition plrhand.c:2667
#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:229
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:239
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:150
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:251
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:201
#define sg_check_ret(...)
Definition savecompat.h:150
#define sg_warn(condition, message,...)
Definition savecompat.h:160
#define hex_chars
Definition savecompat.h:205
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
#define sg_regr(fixversion, message,...)
Definition savecompat.h:193
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:146
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:171
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:434
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:8010
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1198
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2754
static void sg_save_map_altitude(struct savedata *saving)
Definition savegame3.c:3019
static void unit_ordering_apply(void)
Definition savegame3.c:1079
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3711
static struct loaddata * loaddata_new(struct section_file *file)
Definition savegame3.c:584
static void worklist_save(struct section_file *file, const struct worklist *pwl, int max_length, const char *path,...)
Definition savegame3.c:1012
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3591
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3250
bool sg_success
Definition savecompat.c: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:2813
static enum unit_orders char2order(char order)
Definition savegame3.c:710
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:918
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:3082
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3552
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:154
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4167
#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:7940
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5674
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5626
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5044
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2918
static bool sg_load_player_unit(struct loaddata *loading, struct player *plr, struct unit *punit, int orders_max_length, const char *unitstr)
Definition savegame3.c:6152
static char activity2char(int activity)
Definition savegame3.c:823
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:679
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1335
static enum unit_activity char2activity(char activity)
Definition savegame3.c:874
static void unit_ordering_calc(void)
Definition savegame3.c:1050
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2663
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6083
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1250
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2434
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3195
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7662
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3508
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:175
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2040
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2393
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1774
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6686
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7981
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7967
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3372
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7764
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:2472
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2498
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2087
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:698
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4228
static char order2char(enum unit_orders order)
Definition savegame3.c:737
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7857
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2586
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1133
#define PART_SIZE
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6739
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2242
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1165
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1262
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7492
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:5163
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1227
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8259
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:8029
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7005
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:7085
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2063
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2873
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:7168
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2958
static void worklist_load(struct section_file *file, int wlist_max_length, struct worklist *pwl, const char *path,...)
Definition savegame3.c:966
static void sg_save_mapimg(struct savedata *saving)
Definition savegame3.c:8069
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:7370
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2701
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3108
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:623
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3972
#define PART_ADJUST
static void sg_load_map_altitude(struct loaddata *loading)
Definition savegame3.c:2986
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1298
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7837
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:3050
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:8094
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7826
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:1100
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2262
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4718
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2483
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2679
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3648
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:2548
bool game_was_started(void)
Definition srv_main.c:356
void identity_number_reserve(int id)
Definition srv_main.c:2076
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:2353
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:48
int great_wonder_owners[B_LAST]
bool global_advances[A_LAST]
enum ai_level skill_level
enum phase_mode_type phase_mode
char version[MAX_LEN_NAME]
char alt_dir[MAX_LEN_NAME]
char description[MAX_LEN_CONTENT]
char datafile[MAX_LEN_NAME]
char authors[MAX_LEN_PACKET/3]
Definition goto.c:52
enum ai_level skill_level
Definition player.h:116
struct ai_trait * traits
Definition player.h:126
enum barbarian_type barbarian_type
Definition player.h:122
int science_cost
Definition player.h:119
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:124
int expand
Definition player.h:118
int fuzzy
Definition player.h:117
enum diplstate_type type
Definition player.h:199
int infra_points
Definition player.h:67
int units_killed
Definition player.h:105
int landarea
Definition player.h:94
int population
Definition player.h:96
int pollution
Definition player.h:99
int wonders
Definition player.h:91
int settledarea
Definition player.h:95
int units_used
Definition player.h:108
int specialists[SP_MAX]
Definition player.h:90
int units_lost
Definition player.h:106
int angry
Definition player.h:89
int techout
Definition player.h:93
int units
Definition player.h:98
int units_built
Definition player.h:104
int content
Definition player.h:87
int happy
Definition player.h:86
int spaceship
Definition player.h:103
int culture
Definition player.h:109
int unhappy
Definition player.h:88
int cities
Definition player.h:97
int literacy
Definition player.h:100
int techs
Definition player.h:92
struct player * extras_owner
Definition maphand.h:35
short last_updated
Definition maphand.h:44
struct player * owner
Definition maphand.h:34
struct extra_type * resource
Definition maphand.h:32
struct city_list * cities
Definition player.h:281
int bulbs_last_turn
Definition player.h:351
struct player_ai ai_common
Definition player.h:288
bv_plr_flags flags
Definition player.h:292
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:7934
struct player * plr1
Definition diptreaty.h:82
struct clause_list * clauses
Definition diptreaty.h:84
bool accept1
Definition diptreaty.h:83
struct player * plr0
Definition diptreaty.h:82
bool accept0
Definition diptreaty.h:83
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int length
Definition unit.h:198
int upkeep[O_LAST]
Definition unit.h:150
bool has_orders
Definition unit.h:196
enum action_decision action_decision_want
Definition unit.h:205
int battlegroup
Definition unit.h:194
enum unit_activity activity
Definition unit.h:159
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
enum gen_action action
Definition unit.h:160
int ord_city
Definition unit.h:245
struct unit::@83 orders
bool moved
Definition unit.h:176
int ord_map
Definition unit.h:244
int index
Definition unit.h:198
struct vision * vision
Definition unit.h:247
bool vigilant
Definition unit.h:200
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
struct extra_type * changed_from_target
Definition unit.h:173
int current_form_turn
Definition unit.h:211
bool stay
Definition unit.h:208
enum direction8 facing
Definition unit.h:144
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:142
struct extra_type * activity_target
Definition unit.h:167
int activity_count
Definition unit.h:165
struct unit_order * list
Definition unit.h:201
enum unit_activity changed_from
Definition unit.h:171
struct unit_adv * adv
Definition unit.h:239
struct player * nationality
Definition unit.h:146
bool repeat
Definition unit.h:199
int homecity
Definition unit.h:148
bool paradropped
Definition unit.h:177
bool done_moving
Definition unit.h:184
int birth_turn
Definition unit.h:210
struct goods_type * carrying
Definition unit.h:189
struct tile * goto_tile
Definition unit.h:157
struct tile * action_decision_tile
Definition unit.h:206
int veteran
Definition unit.h:154
int changed_from_count
Definition unit.h:172
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
int city_style(struct city *pcity)
Definition style.c:241
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
struct nation_style * style_by_number(int id)
Definition style.c:88
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define sz_strlcpy(dest, src)
Definition support.h:195
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
int team_index(const struct team *pteam)
Definition team.c: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:1094
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:407
#define BATTLEGROUP_NONE
Definition unit.h:193
unit_orders
Definition unit.h:38
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#define unit_owner(_pu)
Definition unit.h:406
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1406
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5016
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1230
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1063
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c: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