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