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 2.3.0. It is defined by the mandatory option '+version2'. The main load
17 function checks if this option is present. If not, the old (pre-2.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 functions are savegame2_load() and savegame2_save(). Within
26 former function the savegame version is tested and the requested savegame version is
27 loaded.
28
29 - The real work is done by savegame2_load_real() and savegame2_save_real().
30 This function call all submodules (settings, players, etc.)
31
32 - The remaining part of this file is split into several sections:
33 * helper functions
34 * save / load functions for all submodules (and their subsubmodules)
35
36 - If possible, all functions for load / save submodules should exit in
37 pairs named sg_load_<submodule> and sg_save_<submodule>. If one is not
38 needed please add a comment why.
39
40 - The submodules can be further divided as:
41 sg_load_<submodule>_<subsubmodule>
42
43 - If needed (due to static variables in the *.c files) these functions
44 can be located in the corresponding source files (as done for the settings
45 and the event_cache).
46
47 Creating a savegame:
48
49 (nothing at the moment)
50
51 Loading a savegame:
52
53 - The status of the process is saved within the static variable
54 'sg_success'. This variable is set to TRUE within savegame2_load_real().
55 If you encounter an error use sg_failure_*() to set it to FALSE and
56 return an error message. Furthermore, sg_check_* should be used at the
57 start of each (submodule) function to return if previous functions failed.
58
59 - While the loading process dependencies between different modules exits.
60 They can be handled within the struct loaddata *loading which is used as
61 first argument for all sg_load_*() function. Please indicate the
62 dependencies within the definition of this struct.
63
64 */
65
66 #ifdef HAVE_CONFIG_H
67 #include <fc_config.h>
68 #endif
69
70 #include <ctype.h>
71 #include <stdarg.h>
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75
76 /* utility */
77 #include "bitvector.h"
78 #include "fcintl.h"
79 #include "idex.h"
80 #include "log.h"
81 #include "mem.h"
82 #include "rand.h"
83 #include "registry.h"
84 #include "shared.h"
85 #include "support.h" /* bool type */
86 #include "timing.h"
87
88 /* common */
89 #include "achievements.h"
90 #include "ai.h"
91 #include "bitvector.h"
92 #include "capability.h"
93 #include "citizens.h"
94 #include "city.h"
95 #include "game.h"
96 #include "government.h"
97 #include "map.h"
98 #include "mapimg.h"
99 #include "movement.h"
100 #include "multipliers.h"
101 #include "packets.h"
102 #include "research.h"
103 #include "rgbcolor.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 "ruleset.h"
121 #include "sanitycheck.h"
122 #include "savecompat.h"
123 #include "savegame.h"
124 #include "score.h"
125 #include "settings.h"
126 #include "spacerace.h"
127 #include "srv_main.h"
128 #include "stdinhand.h"
129 #include "techtools.h"
130 #include "unittools.h"
131
132 /* server/advisors */
133 #include "advdata.h"
134 #include "advbuilding.h"
135 #include "infracache.h"
136
137 /* server/generator */
138 #include "mapgen.h"
139 #include "utilities.h"
140
141 /* server/scripting */
142 #include "script_server.h"
143
144 /* ai */
145 #include "aitraits.h"
146 #include "difficulty.h"
147
148 #include "savegame2.h"
149
150 extern bool sg_success;
151
152 #ifdef FREECIV_TESTMATIC
153 #define SAVE_DUMMY_TURN_CHANGE_TIME 1
154 #endif
155
156 /*
157 * This loops over the entire map to save data. It collects all the data of
158 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
159 *
160 * Parameters:
161 * ptile: current tile within the line (used by GET_XY_CHAR)
162 * GET_XY_CHAR: macro returning the map character for each position
163 * secfile: a secfile struct
164 * secpath, ...: path as used for sprintf() with arguments; the last item
165 * will be the the y coordinate
166 * Example:
167 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
168 */
169 #define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
170 { \
171 char _line[game.map.xsize + 1]; \
172 int _nat_x, _nat_y; \
173 \
174 for (_nat_y = 0; _nat_y < game.map.ysize; _nat_y++) { \
175 for (_nat_x = 0; _nat_x < game.map.xsize; _nat_x++) { \
176 struct tile *ptile = native_pos_to_tile(_nat_x, _nat_y); \
177 fc_assert_action(ptile != NULL, continue); \
178 _line[_nat_x] = (GET_XY_CHAR); \
179 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
180 "Trying to write invalid map data at position " \
181 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
182 secpath, _line[_nat_x], _line[_nat_x]); \
183 } \
184 _line[game.map.xsize] = '\0'; \
185 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
186 } \
187 }
188
189 /*
190 * This loops over the entire map to load data. It inputs a line of data
191 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
192 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
193 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
194 * macro but definable by the caller.
195 *
196 * Parameters:
197 * ch: a variable to hold a char (data for a single position,
198 * used by SET_XY_CHAR)
199 * ptile: current tile within the line (used by SET_XY_CHAR)
200 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
201 * secfile: a secfile struct
202 * secpath, ...: path as used for sprintf() with arguments; the last item
203 * will be the the y coordinate
204 * Example:
205 * LOAD_MAP_CHAR(ch, ptile,
206 * map_get_player_tile(ptile, plr)->terrain
207 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
208 *
209 * Note: some (but not all) of the code this is replacing used to skip over
210 * lines that did not exist. This allowed for backward-compatibility.
211 * We could add another parameter that specified whether it was OK to
212 * skip the data, but there's not really much advantage to exiting
213 * early in this case. Instead, we let any map data type to be empty,
214 * and just print an informative warning message about it.
215 */
216 #define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
217 { \
218 int _nat_x, _nat_y; \
219 bool _printed_warning = FALSE; \
220 for (_nat_y = 0; _nat_y < game.map.ysize; _nat_y++) { \
221 const char *_line = secfile_lookup_str(secfile, secpath, \
222 ## __VA_ARGS__, _nat_y); \
223 if (NULL == _line) { \
224 char buf[64]; \
225 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
226 log_verbose("Line not found='%s'", buf); \
227 _printed_warning = TRUE; \
228 continue; \
229 } else if (strlen(_line) != game.map.xsize) { \
230 char buf[64]; \
231 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
232 log_verbose("Line too short (expected %d got %lu)='%s'", \
233 game.map.xsize, (unsigned long) strlen(_line), buf); \
234 _printed_warning = TRUE; \
235 continue; \
236 } \
237 for (_nat_x = 0; _nat_x < game.map.xsize; _nat_x++) { \
238 const char ch = _line[_nat_x]; \
239 struct tile *ptile = native_pos_to_tile(_nat_x, _nat_y); \
240 (SET_XY_CHAR); \
241 } \
242 } \
243 if (_printed_warning) { \
244 /* TRANS: Minor error message. */ \
245 log_sg(_("Saved game contains incomplete map data. This can" \
246 " happen with old saved games, or it may indicate an" \
247 " invalid saved game file. Proceed at your own risk.")); \
248 } \
249 }
250
251 /* Iterate on the extras half-bytes */
252 #define halfbyte_iterate_extras(e, num_extras_types) \
253 { \
254 int e; \
255 for(e = 0; 4 * e < (num_extras_types); e++) {
256
257 #define halfbyte_iterate_extras_end \
258 } \
259 }
260
261 /* Iterate on the specials half-bytes */
262 #define halfbyte_iterate_special(s, num_specials_types) \
263 { \
264 enum tile_special_type s; \
265 for(s = 0; 4 * s < (num_specials_types); s++) {
266
267 #define halfbyte_iterate_special_end \
268 } \
269 }
270
271 /* Iterate on the bases half-bytes */
272 #define halfbyte_iterate_bases(b, num_bases_types) \
273 { \
274 int b; \
275 for(b = 0; 4 * b < (num_bases_types); b++) {
276
277 #define halfbyte_iterate_bases_end \
278 } \
279 }
280
281 /* Iterate on the roads half-bytes */
282 #define halfbyte_iterate_roads(r, num_roads_types) \
283 { \
284 int r; \
285 for(r = 0; 4 * r < (num_roads_types); r++) {
286
287 #define halfbyte_iterate_roads_end \
288 } \
289 }
290
291 struct savedata {
292 struct section_file *file;
293 char secfile_options[512];
294
295 /* set by the caller */
296 const char *save_reason;
297 bool scenario;
298
299 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
300 bool save_players;
301 };
302
303 #define TOKEN_SIZE 10
304
305 #define log_worker log_verbose
306
307 static const char savefile_options_default[] =
308 " +version2";
309 /* The following savefile option are added if needed:
310 * - specials
311 * - riversoverlay
312 * See also calls to sg_save_savefile_options(). */
313
314 static const char num_chars[] =
315 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
316
317 static void savegame2_load_real(struct section_file *file);
318 static void savegame2_save_real(struct section_file *file,
319 const char *save_reason,
320 bool scenario);
321 static struct loaddata *loaddata_new(struct section_file *file);
322 static void loaddata_destroy(struct loaddata *loading);
323
324 static struct savedata *savedata_new(struct section_file *file,
325 const char *save_reason,
326 bool scenario);
327 static void savedata_destroy(struct savedata *saving);
328
329 static enum unit_orders char2order(char order);
330 static char order2char(enum unit_orders order);
331 static enum direction8 char2dir(char dir);
332 static char dir2char(enum direction8 dir);
333 static char activity2char(enum unit_activity activity);
334 static enum unit_activity char2activity(char activity);
335 static char *quote_block(const void *const data, int length);
336 static int unquote_block(const char *const quoted_, void *dest,
337 int dest_length);
338 static void worklist_load(struct section_file *file, struct worklist *pwl,
339 const char *path, ...);
340 static void worklist_save(struct section_file *file,
341 const struct worklist *pwl,
342 int max_length, const char *path, ...);
343 static void unit_ordering_calc(void);
344 static void unit_ordering_apply(void);
345 static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx);
346 static char sg_extras_get(bv_extras extras, const int *idx);
347 static void sg_special_set(struct tile *ptile, bv_extras *extras, char ch,
348 const enum tile_special_type *idx,
349 bool rivers_overlay);
350 static void sg_bases_set(bv_extras *extras, char ch, struct base_type **idx);
351 static void sg_roads_set(bv_extras *extras, char ch, struct road_type **idx);
352 static struct resource *char2resource(char c);
353 static char resource2char(const struct resource *presource);
354 static char num2char(unsigned int num);
355 static int char2num(char ch);
356 static struct terrain *char2terrain(char ch);
357 static char terrain2char(const struct terrain *pterrain);
358 static Tech_type_id technology_load(struct section_file *file,
359 const char* path, int plrno);
360 static void technology_save(struct section_file *file,
361 const char* path, int plrno, Tech_type_id tech);
362
363 static void sg_load_ruleset(struct loaddata *loading);
364 static void sg_load_savefile(struct loaddata *loading);
365 static void sg_save_savefile(struct savedata *saving);
366 static void sg_save_savefile_options(struct savedata *saving,
367 const char *option);
368
369 static void sg_load_game(struct loaddata *loading);
370 static void sg_save_game(struct savedata *saving);
371
372 static void sg_load_ruledata(struct loaddata *loading);
373 static void sg_save_ruledata(struct savedata *saving);
374
375 static void sg_load_random(struct loaddata *loading);
376 static void sg_save_random(struct savedata *saving);
377
378 static void sg_load_script(struct loaddata *loading);
379 static void sg_save_script(struct savedata *saving);
380
381 static void sg_load_scenario(struct loaddata *loading);
382 static void sg_save_scenario(struct savedata *saving);
383
384 static void sg_load_settings(struct loaddata *loading);
385 static void sg_save_settings(struct savedata *saving);
386
387 static void sg_load_map(struct loaddata *loading);
388 static void sg_save_map(struct savedata *saving);
389 static void sg_load_map_tiles(struct loaddata *loading);
390 static void sg_save_map_tiles(struct savedata *saving);
391 static void sg_load_map_tiles_extras(struct loaddata *loading);
392 static void sg_save_map_tiles_extras(struct savedata *saving);
393 static void sg_load_map_tiles_bases(struct loaddata *loading);
394 static void sg_load_map_tiles_roads(struct loaddata *loading);
395 static void sg_load_map_tiles_specials(struct loaddata *loading,
396 bool rivers_overlay);
397 static void sg_load_map_tiles_resources(struct loaddata *loading);
398 static void sg_save_map_tiles_resources(struct savedata *saving);
399
400 static void sg_load_map_startpos(struct loaddata *loading);
401 static void sg_save_map_startpos(struct savedata *saving);
402 static void sg_load_map_owner(struct loaddata *loading);
403 static void sg_save_map_owner(struct savedata *saving);
404 static void sg_load_map_worked(struct loaddata *loading);
405 static void sg_save_map_worked(struct savedata *saving);
406 static void sg_load_map_known(struct loaddata *loading);
407 static void sg_save_map_known(struct savedata *saving);
408
409 static void sg_load_players_basic(struct loaddata *loading);
410 static void sg_load_players(struct loaddata *loading);
411 static void sg_load_player_main(struct loaddata *loading,
412 struct player *plr);
413 static void sg_load_player_cities(struct loaddata *loading,
414 struct player *plr);
415 static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
416 struct city *pcity, const char *citystr);
417 static void sg_load_player_city_citizens(struct loaddata *loading,
418 struct player *plr,
419 struct city *pcity,
420 const char *citystr);
421 static void sg_load_player_units(struct loaddata *loading,
422 struct player *plr);
423 static bool sg_load_player_unit(struct loaddata *loading,
424 struct player *plr, struct unit *punit,
425 const char *unitstr);
426 static void sg_load_player_units_transport(struct loaddata *loading,
427 struct player *plr);
428 static void sg_load_player_attributes(struct loaddata *loading,
429 struct player *plr);
430 static void sg_load_player_vision(struct loaddata *loading,
431 struct player *plr);
432 static bool sg_load_player_vision_city(struct loaddata *loading,
433 struct player *plr,
434 struct vision_site *pdcity,
435 const char *citystr);
436 static void sg_save_players(struct savedata *saving);
437 static void sg_save_player_main(struct savedata *saving,
438 struct player *plr);
439 static void sg_save_player_cities(struct savedata *saving,
440 struct player *plr);
441 static void sg_save_player_units(struct savedata *saving,
442 struct player *plr);
443 static void sg_save_player_attributes(struct savedata *saving,
444 struct player *plr);
445 static void sg_save_player_vision(struct savedata *saving,
446 struct player *plr);
447
448 static void sg_load_researches(struct loaddata *loading);
449 static void sg_save_researches(struct savedata *saving);
450
451 static void sg_load_event_cache(struct loaddata *loading);
452 static void sg_save_event_cache(struct savedata *saving);
453
454 static void sg_save_treaties(struct savedata *saving);
455
456 static void sg_load_treaties(struct loaddata *loading);
457
458 static void sg_load_history(struct loaddata *loading);
459 static void sg_save_history(struct savedata *saving);
460
461 static void sg_load_mapimg(struct loaddata *loading);
462 static void sg_save_mapimg(struct savedata *saving);
463
464 static void sg_load_sanitycheck(struct loaddata *loading);
465 static void sg_save_sanitycheck(struct savedata *saving);
466
467
468 /****************************************************************************
469 Main entry point for loading a game.
470 Called only in ./server/stdinhand.c:load_command().
471 The entire ruleset is always sent afterwards->
472 ****************************************************************************/
savegame2_load(struct section_file * file)473 void savegame2_load(struct section_file *file)
474 {
475 const char *savefile_options;
476
477 fc_assert_ret(file != NULL);
478
479 #ifdef DEBUG_TIMERS
480 struct timer *loadtimer = timer_new(TIMER_CPU, TIMER_DEBUG);
481 timer_start(loadtimer);
482 #endif
483
484 savefile_options = secfile_lookup_str(file, "savefile.options");
485
486 if (!savefile_options) {
487 log_error("Missing savefile options. Can not load the savegame.");
488 return;
489 }
490
491 if (!has_capabilities("+version2", savefile_options)) {
492 /* load old format (freeciv 2.2.x) */
493 log_verbose("loading savefile in old format ...");
494 secfile_allow_digital_boolean(file, TRUE);
495 legacy_game_load(file);
496 } else {
497 /* load new format (freeciv 2.2.99 and newer) */
498 log_verbose("loading savefile in new format ...");
499 savegame2_load_real(file);
500 }
501
502 players_iterate(pplayer) {
503 unit_list_iterate(pplayer->units, punit) {
504 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
505 } unit_list_iterate_end;
506
507 city_list_iterate(pplayer->cities, pcity) {
508 CALL_PLR_AI_FUNC(city_got, pplayer, pplayer, pcity);
509 } city_list_iterate_end;
510 } players_iterate_end;
511
512 #ifdef DEBUG_TIMERS
513 timer_stop(loadtimer);
514 log_debug("Loading secfile in %.3f seconds.", timer_read_seconds(loadtimer));
515 timer_destroy(loadtimer);
516 #endif /* DEBUG_TIMERS */
517 }
518
519 /****************************************************************************
520 Main entry point for saving a game.
521 Called only in ./server/srv_main.c:save_game().
522 ****************************************************************************/
savegame2_save(struct section_file * file,const char * save_reason,bool scenario)523 void savegame2_save(struct section_file *file, const char *save_reason,
524 bool scenario)
525 {
526 fc_assert_ret(file != NULL);
527
528 #ifdef DEBUG_TIMERS
529 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG);
530 timer_start(savetimer);
531 #endif
532
533 log_verbose("saving game in new format ...");
534 savegame2_save_real(file, save_reason, scenario);
535
536 #ifdef DEBUG_TIMERS
537 timer_stop(savetimer);
538 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
539 timer_destroy(savetimer);
540 #endif /* DEBUG_TIMERS */
541 }
542
543 /* =======================================================================
544 * Basic load / save functions.
545 * ======================================================================= */
546
547 /****************************************************************************
548 Really loading the savegame.
549 ****************************************************************************/
savegame2_load_real(struct section_file * file)550 static void savegame2_load_real(struct section_file *file)
551 {
552 struct loaddata *loading;
553 bool was_send_city_suppressed, was_send_tile_suppressed;
554
555 /* initialise loading */
556 was_send_city_suppressed = send_city_suppression(TRUE);
557 was_send_tile_suppressed = send_tile_suppression(TRUE);
558 loading = loaddata_new(file);
559 sg_success = TRUE;
560
561 /* Load the savegame data. */
562 /* Set up correct ruleset */
563 sg_load_ruleset(loading);
564 /* [compat] */
565 sg_load_compat(loading);
566 /* [savefile] */
567 sg_load_savefile(loading);
568 /* [game] */
569 sg_load_game(loading);
570 /* [scenario] */
571 sg_load_scenario(loading);
572 /* [random] */
573 sg_load_random(loading);
574 /* [settings] */
575 sg_load_settings(loading);
576 /* [ruledata] */
577 sg_load_ruledata(loading);
578 /* [players] (basic data) */
579 sg_load_players_basic(loading);
580 /* [map]; needs width and height loaded by [settings] */
581 sg_load_map(loading);
582 /* [research] */
583 sg_load_researches(loading);
584 /* [player<i>] */
585 sg_load_players(loading);
586 /* [event_cache] */
587 sg_load_event_cache(loading);
588 /* [treaties] */
589 sg_load_treaties(loading);
590 /* [history] */
591 sg_load_history(loading);
592 /* [mapimg] */
593 sg_load_mapimg(loading);
594 /* [script] -- must come last as may reference game objects */
595 sg_load_script(loading);
596
597 /* Sanity checks for the loaded game. */
598 sg_load_sanitycheck(loading);
599
600 /* deinitialise loading */
601 loaddata_destroy(loading);
602 send_tile_suppression(was_send_tile_suppressed);
603 send_city_suppression(was_send_city_suppressed);
604
605 if (!sg_success) {
606 log_error("Failure loading savegame!");
607 /* Try to get the server back to a vaguely sane state */
608 server_game_free();
609 server_game_init();
610 load_rulesets(NULL, TRUE, FALSE);
611 }
612 }
613
614 /****************************************************************************
615 Really save the game to a file.
616 ****************************************************************************/
savegame2_save_real(struct section_file * file,const char * save_reason,bool scenario)617 static void savegame2_save_real(struct section_file *file,
618 const char *save_reason,
619 bool scenario)
620 {
621 struct savedata *saving;
622
623 /* initialise loading */
624 saving = savedata_new(file, save_reason, scenario);
625 sg_success = TRUE;
626
627 /* [scenario] */
628 /* This should be first section so scanning through all scenarios just for
629 * names and descriptions would go faster. */
630 sg_save_scenario(saving);
631 /* [savefile] */
632 sg_save_savefile(saving);
633 /* [game] */
634 sg_save_game(saving);
635 /* [random] */
636 sg_save_random(saving);
637 /* [script] */
638 sg_save_script(saving);
639 /* [settings] */
640 sg_save_settings(saving);
641 /* [ruledata] */
642 sg_save_ruledata(saving);
643 /* [map] */
644 sg_save_map(saving);
645 /* [player<i>] */
646 sg_save_players(saving);
647 /* [research] */
648 sg_save_researches(saving);
649 /* [event_cache] */
650 sg_save_event_cache(saving);
651 /* [treaty<i>] */
652 sg_save_treaties(saving);
653 /* [history] */
654 sg_save_history(saving);
655 /* [mapimg] */
656 sg_save_mapimg(saving);
657
658 /* Sanity checks for the saved game. */
659 sg_save_sanitycheck(saving);
660
661 /* deinitialise saving */
662 savedata_destroy(saving);
663
664 if (!sg_success) {
665 log_error("Failure saving savegame!");
666 }
667 }
668
669 /****************************************************************************
670 Create new loaddata item for given section file.
671 ****************************************************************************/
loaddata_new(struct section_file * file)672 static struct loaddata *loaddata_new(struct section_file *file)
673 {
674 struct loaddata *loading = calloc(1, sizeof(*loading));
675 loading->file = file;
676 loading->secfile_options = NULL;
677
678 loading->improvement.order = NULL;
679 loading->improvement.size = -1;
680 loading->technology.order = NULL;
681 loading->technology.size = -1;
682 loading->trait.order = NULL;
683 loading->trait.size = -1;
684 loading->extra.order = NULL;
685 loading->extra.size = -1;
686 loading->multiplier.order = NULL;
687 loading->multiplier.size = -1;
688 loading->special.order = NULL;
689 loading->special.size = -1;
690 loading->base.order = NULL;
691 loading->base.size = -1;
692 loading->road.order = NULL;
693 loading->road.size = -1;
694 loading->specialist.order = NULL;
695 loading->specialist.size = -1;
696 loading->ds_t.order = NULL;
697 loading->ds_t.size = -1;
698
699 loading->server_state = S_S_INITIAL;
700 loading->rstate = fc_rand_state();
701 loading->worked_tiles = NULL;
702
703 return loading;
704 }
705
706 /****************************************************************************
707 Free resources allocated for loaddata item.
708 ****************************************************************************/
loaddata_destroy(struct loaddata * loading)709 static void loaddata_destroy(struct loaddata *loading)
710 {
711 if (loading->improvement.order != NULL) {
712 free(loading->improvement.order);
713 }
714
715 if (loading->technology.order != NULL) {
716 free(loading->technology.order);
717 }
718
719 if (loading->trait.order != NULL) {
720 free(loading->trait.order);
721 }
722
723 if (loading->extra.order != NULL) {
724 free(loading->extra.order);
725 }
726
727 if (loading->multiplier.order != NULL) {
728 free(loading->multiplier.order);
729 }
730
731 if (loading->special.order != NULL) {
732 free(loading->special.order);
733 }
734
735 if (loading->base.order != NULL) {
736 free(loading->base.order);
737 }
738
739 if (loading->road.order != NULL) {
740 free(loading->road.order);
741 }
742
743 if (loading->specialist.order != NULL) {
744 free(loading->specialist.order);
745 }
746
747 if (loading->ds_t.order != NULL) {
748 free(loading->ds_t.order);
749 }
750
751 if (loading->worked_tiles != NULL) {
752 free(loading->worked_tiles);
753 }
754
755 free(loading);
756 }
757
758 /****************************************************************************
759 Create new savedata item for given file.
760 ****************************************************************************/
savedata_new(struct section_file * file,const char * save_reason,bool scenario)761 static struct savedata *savedata_new(struct section_file *file,
762 const char *save_reason,
763 bool scenario)
764 {
765 struct savedata *saving = calloc(1, sizeof(*saving));
766 saving->file = file;
767 saving->secfile_options[0] = '\0';
768
769 saving->save_reason = save_reason;
770 saving->scenario = scenario;
771
772 saving->save_players = FALSE;
773
774 return saving;
775 }
776
777 /****************************************************************************
778 Free resources allocated for savedata item
779 ****************************************************************************/
savedata_destroy(struct savedata * saving)780 static void savedata_destroy(struct savedata *saving)
781 {
782 free(saving);
783 }
784
785 /* =======================================================================
786 * Helper functions.
787 * ======================================================================= */
788
789 /****************************************************************************
790 Returns an order for a character identifier. See also order2char.
791 ****************************************************************************/
char2order(char order)792 static enum unit_orders char2order(char order)
793 {
794 switch (order) {
795 case 'm':
796 case 'M':
797 return ORDER_MOVE;
798 case 'w':
799 case 'W':
800 return ORDER_FULL_MP;
801 case 'b':
802 case 'B':
803 return ORDER_BUILD_CITY;
804 case 'a':
805 case 'A':
806 return ORDER_ACTIVITY;
807 case 'd':
808 case 'D':
809 return ORDER_DISBAND;
810 case 'u':
811 case 'U':
812 return ORDER_BUILD_WONDER;
813 case 't':
814 case 'T':
815 return ORDER_TRADE_ROUTE;
816 case 'h':
817 case 'H':
818 return ORDER_HOMECITY;
819 case 'x':
820 case 'X':
821 return ORDER_ACTION_MOVE;
822 }
823
824 /* This can happen if the savegame is invalid. */
825 return ORDER_LAST;
826 }
827
828 /****************************************************************************
829 Returns a character identifier for an order. See also char2order.
830 ****************************************************************************/
order2char(enum unit_orders order)831 static char order2char(enum unit_orders order)
832 {
833 switch (order) {
834 case ORDER_MOVE:
835 return 'm';
836 case ORDER_FULL_MP:
837 return 'w';
838 case ORDER_ACTIVITY:
839 return 'a';
840 case ORDER_BUILD_CITY:
841 return 'b';
842 case ORDER_DISBAND:
843 return 'd';
844 case ORDER_BUILD_WONDER:
845 return 'u';
846 case ORDER_TRADE_ROUTE:
847 return 't';
848 case ORDER_HOMECITY:
849 return 'h';
850 case ORDER_ACTION_MOVE:
851 return 'x';
852 case ORDER_LAST:
853 break;
854 }
855
856 fc_assert(FALSE);
857 return '?';
858 }
859
860 /****************************************************************************
861 Returns a direction for a character identifier. See also dir2char.
862 ****************************************************************************/
char2dir(char dir)863 static enum direction8 char2dir(char dir)
864 {
865 /* Numberpad values for the directions. */
866 switch (dir) {
867 case '1':
868 return DIR8_SOUTHWEST;
869 case '2':
870 return DIR8_SOUTH;
871 case '3':
872 return DIR8_SOUTHEAST;
873 case '4':
874 return DIR8_WEST;
875 case '6':
876 return DIR8_EAST;
877 case '7':
878 return DIR8_NORTHWEST;
879 case '8':
880 return DIR8_NORTH;
881 case '9':
882 return DIR8_NORTHEAST;
883 }
884
885 /* This can happen if the savegame is invalid. */
886 return direction8_invalid();
887 }
888
889 /****************************************************************************
890 Returns a character identifier for a direction. See also char2dir.
891 ****************************************************************************/
dir2char(enum direction8 dir)892 static char dir2char(enum direction8 dir)
893 {
894 /* Numberpad values for the directions. */
895 switch (dir) {
896 case DIR8_NORTH:
897 return '8';
898 case DIR8_SOUTH:
899 return '2';
900 case DIR8_EAST:
901 return '6';
902 case DIR8_WEST:
903 return '4';
904 case DIR8_NORTHEAST:
905 return '9';
906 case DIR8_NORTHWEST:
907 return '7';
908 case DIR8_SOUTHEAST:
909 return '3';
910 case DIR8_SOUTHWEST:
911 return '1';
912 }
913
914 fc_assert(FALSE);
915 return '?';
916 }
917
918 /****************************************************************************
919 Returns a character identifier for an activity. See also char2activity.
920 ****************************************************************************/
activity2char(enum unit_activity activity)921 static char activity2char(enum unit_activity activity)
922 {
923 switch (activity) {
924 case ACTIVITY_IDLE:
925 return 'w';
926 case ACTIVITY_POLLUTION:
927 return 'p';
928 case ACTIVITY_OLD_ROAD:
929 return 'r';
930 case ACTIVITY_MINE:
931 return 'm';
932 case ACTIVITY_IRRIGATE:
933 return 'i';
934 case ACTIVITY_FORTIFIED:
935 return 'f';
936 case ACTIVITY_FORTRESS:
937 return 't';
938 case ACTIVITY_SENTRY:
939 return 's';
940 case ACTIVITY_OLD_RAILROAD:
941 return 'l';
942 case ACTIVITY_PILLAGE:
943 return 'e';
944 case ACTIVITY_GOTO:
945 return 'g';
946 case ACTIVITY_EXPLORE:
947 return 'x';
948 case ACTIVITY_TRANSFORM:
949 return 'o';
950 case ACTIVITY_AIRBASE:
951 return 'a';
952 case ACTIVITY_FORTIFYING:
953 return 'y';
954 case ACTIVITY_FALLOUT:
955 return 'u';
956 case ACTIVITY_BASE:
957 return 'b';
958 case ACTIVITY_GEN_ROAD:
959 return 'R';
960 case ACTIVITY_CONVERT:
961 return 'c';
962 case ACTIVITY_UNKNOWN:
963 case ACTIVITY_PATROL_UNUSED:
964 return '?';
965 case ACTIVITY_LAST:
966 break;
967 }
968
969 fc_assert(FALSE);
970 return '?';
971 }
972
973 /****************************************************************************
974 Returns an activity for a character identifier. See also activity2char.
975 ****************************************************************************/
char2activity(char activity)976 static enum unit_activity char2activity(char activity)
977 {
978 enum unit_activity a;
979
980 for (a = 0; a < ACTIVITY_LAST; a++) {
981 char achar = activity2char(a);
982
983 if (activity == achar) {
984 return a;
985 }
986 }
987
988 /* This can happen if the savegame is invalid. */
989 return ACTIVITY_LAST;
990 }
991
992 /****************************************************************************
993 Quote the memory block denoted by data and length so it consists only of
994 " a-f0-9:". The returned string has to be freed by the caller using free().
995 ****************************************************************************/
quote_block(const void * const data,int length)996 static char *quote_block(const void *const data, int length)
997 {
998 char *buffer = fc_malloc(length * 3 + 10);
999 size_t offset;
1000 int i;
1001
1002 sprintf(buffer, "%d:", length);
1003 offset = strlen(buffer);
1004
1005 for (i = 0; i < length; i++) {
1006 sprintf(buffer + offset, "%02x ", ((unsigned char *) data)[i]);
1007 offset += 3;
1008 }
1009 return buffer;
1010 }
1011
1012 /****************************************************************************
1013 Unquote a string. The unquoted data is written into dest. If the unquoted
1014 data will be larger than dest_length the function aborts. It returns the
1015 actual length of the unquoted block.
1016 ****************************************************************************/
unquote_block(const char * const quoted_,void * dest,int dest_length)1017 static int unquote_block(const char *const quoted_, void *dest,
1018 int dest_length)
1019 {
1020 int i, length, parsed, tmp;
1021 char *endptr;
1022 const char *quoted = quoted_;
1023
1024 parsed = sscanf(quoted, "%d", &length);
1025 fc_assert_ret_val(1 == parsed, 0);
1026
1027 if (length > dest_length) {
1028 return 0;
1029 }
1030 quoted = strchr(quoted, ':');
1031 fc_assert_ret_val(quoted != NULL, 0);
1032 quoted++;
1033
1034 for (i = 0; i < length; i++) {
1035 tmp = strtol(quoted, &endptr, 16);
1036 fc_assert_ret_val((endptr - quoted) == 2, 0);
1037 fc_assert_ret_val(*endptr == ' ', 0);
1038 fc_assert_ret_val((tmp & 0xff) == tmp, 0);
1039 ((unsigned char *) dest)[i] = tmp;
1040 quoted += 3;
1041 }
1042 return length;
1043 }
1044
1045 /****************************************************************************
1046 Load the worklist elements specified by path to the worklist pointed to
1047 by 'pwl'. 'pwl' should be a pointer to an existing worklist.
1048 ****************************************************************************/
worklist_load(struct section_file * file,struct worklist * pwl,const char * path,...)1049 static void worklist_load(struct section_file *file, struct worklist *pwl,
1050 const char *path, ...)
1051 {
1052 int i;
1053 const char *kind;
1054 const char *name;
1055 char path_str[1024];
1056 va_list ap;
1057
1058 /* The first part of the registry path is taken from the varargs to the
1059 * function. */
1060 va_start(ap, path);
1061 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1062 va_end(ap);
1063
1064 worklist_init(pwl);
1065 pwl->length = secfile_lookup_int_default(file, 0,
1066 "%s.wl_length", path_str);
1067
1068 for (i = 0; i < pwl->length; i++) {
1069 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
1070
1071 /* We lookup the production value by name. An invalid entry isn't a
1072 * fatal error; we just truncate the worklist. */
1073 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
1074 path_str, i);
1075 pwl->entries[i] = universal_by_rule_name(kind, name);
1076 if (pwl->entries[i].kind == universals_n_invalid()) {
1077 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
1078 name);
1079 pwl->length = i;
1080 break;
1081 }
1082 }
1083 }
1084
1085 /****************************************************************************
1086 Save the worklist elements specified by path from the worklist pointed to
1087 by 'pwl'. 'pwl' should be a pointer to an existing worklist.
1088 ****************************************************************************/
worklist_save(struct section_file * file,const struct worklist * pwl,int max_length,const char * path,...)1089 static void worklist_save(struct section_file *file,
1090 const struct worklist *pwl,
1091 int max_length, const char *path, ...)
1092 {
1093 char path_str[1024];
1094 int i;
1095 va_list ap;
1096
1097 /* The first part of the registry path is taken from the varargs to the
1098 * function. */
1099 va_start(ap, path);
1100 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1101 va_end(ap);
1102
1103 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1104
1105 for (i = 0; i < pwl->length; i++) {
1106 const struct universal *entry = pwl->entries + i;
1107 secfile_insert_str(file, universal_type_rule_name(entry),
1108 "%s.wl_kind%d", path_str, i);
1109 secfile_insert_str(file, universal_rule_name(entry),
1110 "%s.wl_value%d", path_str, i);
1111 }
1112
1113 fc_assert_ret(max_length <= MAX_LEN_WORKLIST);
1114
1115 /* We want to keep savegame in tabular format, so each line has to be
1116 * of equal length. Fill table up to maximum worklist size. */
1117 for (i = pwl->length ; i < max_length; i++) {
1118 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1119 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1120 }
1121 }
1122
1123 /****************************************************************************
1124 Assign values to ord_city and ord_map for each unit, so the values can be
1125 saved.
1126 ****************************************************************************/
unit_ordering_calc(void)1127 static void unit_ordering_calc(void)
1128 {
1129 int j;
1130
1131 players_iterate(pplayer) {
1132 /* to avoid junk values for unsupported units: */
1133 unit_list_iterate(pplayer->units, punit) {
1134 punit->server.ord_city = 0;
1135 } unit_list_iterate_end;
1136 city_list_iterate(pplayer->cities, pcity) {
1137 j = 0;
1138 unit_list_iterate(pcity->units_supported, punit) {
1139 punit->server.ord_city = j++;
1140 } unit_list_iterate_end;
1141 } city_list_iterate_end;
1142 } players_iterate_end;
1143
1144 whole_map_iterate(ptile) {
1145 j = 0;
1146 unit_list_iterate(ptile->units, punit) {
1147 punit->server.ord_map = j++;
1148 } unit_list_iterate_end;
1149 } whole_map_iterate_end;
1150 }
1151
1152 /****************************************************************************
1153 For each city and tile, sort unit lists according to ord_city and ord_map
1154 values.
1155 ****************************************************************************/
unit_ordering_apply(void)1156 static void unit_ordering_apply(void)
1157 {
1158 players_iterate(pplayer) {
1159 city_list_iterate(pplayer->cities, pcity) {
1160 unit_list_sort_ord_city(pcity->units_supported);
1161 }
1162 city_list_iterate_end;
1163 } players_iterate_end;
1164
1165 whole_map_iterate(ptile) {
1166 unit_list_sort_ord_map(ptile->units);
1167 } whole_map_iterate_end;
1168 }
1169
1170 /****************************************************************************
1171 Helper function for loading extras from a savegame.
1172
1173 'ch' gives the character loaded from the savegame. Extras are packed
1174 in four to a character in hex notation. 'index' is a mapping of
1175 savegame bit -> base bit.
1176 ****************************************************************************/
sg_extras_set(bv_extras * extras,char ch,struct extra_type ** idx)1177 static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx)
1178 {
1179 int i, bin;
1180 const char *pch = strchr(hex_chars, ch);
1181
1182 if (!pch || ch == '\0') {
1183 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1184 bin = 0;
1185 } else {
1186 bin = pch - hex_chars;
1187 }
1188
1189 for (i = 0; i < 4; i++) {
1190 struct extra_type *pextra = idx[i];
1191
1192 if (pextra == NULL) {
1193 continue;
1194 }
1195 if ((bin & (1 << i))
1196 && (game.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1197 BV_SET(*extras, extra_index(pextra));
1198 }
1199 }
1200 }
1201
1202 /****************************************************************************
1203 Helper function for saving extras into a savegame.
1204
1205 Extras are packed in four to a character in hex notation. 'index'
1206 specifies which set of extras are included in this character.
1207 ****************************************************************************/
sg_extras_get(bv_extras extras,const int * idx)1208 static char sg_extras_get(bv_extras extras, const int *idx)
1209 {
1210 int i, bin = 0;
1211
1212 for (i = 0; i < 4; i++) {
1213 int extra = idx[i];
1214
1215 if (extra < 0) {
1216 break;
1217 }
1218
1219 if (BV_ISSET(extras, extra)) {
1220 bin |= (1 << i);
1221 }
1222 }
1223
1224 return hex_chars[bin];
1225 }
1226
1227 /****************************************************************************
1228 Complicated helper function for loading specials from a savegame.
1229
1230 'ch' gives the character loaded from the savegame. Specials are packed
1231 in four to a character in hex notation. 'index' is a mapping of
1232 savegame bit -> special bit. S_LAST is used to mark unused savegame bits.
1233 ****************************************************************************/
sg_special_set(struct tile * ptile,bv_extras * extras,char ch,const enum tile_special_type * idx,bool rivers_overlay)1234 static void sg_special_set(struct tile *ptile, bv_extras *extras, char ch,
1235 const enum tile_special_type *idx,
1236 bool rivers_overlay)
1237 {
1238 int i, bin;
1239 const char *pch = strchr(hex_chars, ch);
1240
1241 if (!pch || ch == '\0') {
1242 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1243 bin = 0;
1244 } else {
1245 bin = pch - hex_chars;
1246 }
1247
1248 for (i = 0; i < 4; i++) {
1249 enum tile_special_type sp = idx[i];
1250
1251 if (sp == S_LAST) {
1252 continue;
1253 }
1254 if (rivers_overlay && sp != S_OLD_RIVER) {
1255 continue;
1256 }
1257
1258 if (sp == S_HUT && !game.map.server.have_huts) {
1259 /* It would be logical to have this in the saving side -
1260 * really not saving the huts in the first place, BUT
1261 * 1) They have been saved by older versions, so we
1262 * have to deal with such savegames.
1263 * 2) This makes scenario author less likely to lose
1264 * one's work completely after carefully placing huts
1265 * and then saving with 'have_huts' disabled. */
1266 continue;
1267 }
1268
1269 if (bin & (1 << i)) {
1270 if (sp == S_OLD_ROAD) {
1271 struct road_type *proad;
1272
1273 proad = road_by_compat_special(ROCO_ROAD);
1274 if (proad) {
1275 BV_SET(*extras, extra_index(road_extra_get(proad)));
1276 }
1277 } else if (sp == S_OLD_RAILROAD) {
1278 struct road_type *proad;
1279
1280 proad = road_by_compat_special(ROCO_RAILROAD);
1281 if (proad) {
1282 BV_SET(*extras, extra_index(road_extra_get(proad)));
1283 }
1284 } else if (sp == S_OLD_RIVER) {
1285 struct road_type *proad;
1286
1287 proad = road_by_compat_special(ROCO_RIVER);
1288 if (proad) {
1289 BV_SET(*extras, extra_index(road_extra_get(proad)));
1290 }
1291 } else {
1292 struct extra_type *pextra = NULL;
1293 enum extra_cause cause = EC_COUNT;
1294
1295 /* Converting from old hardcoded specials to as sensible extra as we can */
1296 switch (sp) {
1297 case S_IRRIGATION:
1298 case S_FARMLAND:
1299 /* If old savegame has both irrigation and farmland, EC_IRRIGATION
1300 * gets applied twice, which hopefully has the correct result. */
1301 cause = EC_IRRIGATION;
1302 break;
1303 case S_MINE:
1304 cause = EC_MINE;
1305 break;
1306 case S_POLLUTION:
1307 cause = EC_POLLUTION;
1308 break;
1309 case S_HUT:
1310 cause = EC_HUT;
1311 break;
1312 case S_FALLOUT:
1313 cause = EC_FALLOUT;
1314 break;
1315 default:
1316 pextra = extra_type_by_rule_name(special_rule_name(sp));
1317 break;
1318 }
1319
1320 if (cause != EC_COUNT) {
1321 struct tile *vtile = tile_virtual_new(ptile);
1322
1323 /* Do not let the extras already set to the real tile mess with setup
1324 * of the player tiles if that's what we're doing. */
1325 vtile->extras = *extras;
1326
1327 /* It's ok not to know which player or which unit originally built the extra -
1328 * in the rules used when specials were saved these could not have made any
1329 * difference. */
1330 pextra = next_extra_for_tile(vtile, cause, NULL, NULL);
1331
1332 tile_virtual_destroy(vtile);
1333 }
1334
1335 if (pextra) {
1336 BV_SET(*extras, extra_index(pextra));
1337 }
1338 }
1339 }
1340 }
1341 }
1342
1343 /****************************************************************************
1344 Helper function for loading bases from a savegame.
1345
1346 'ch' gives the character loaded from the savegame. Bases are packed
1347 in four to a character in hex notation. 'index' is a mapping of
1348 savegame bit -> base bit.
1349 ****************************************************************************/
sg_bases_set(bv_extras * extras,char ch,struct base_type ** idx)1350 static void sg_bases_set(bv_extras *extras, char ch, struct base_type **idx)
1351 {
1352 int i, bin;
1353 const char *pch = strchr(hex_chars, ch);
1354
1355 if (!pch || ch == '\0') {
1356 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1357 bin = 0;
1358 } else {
1359 bin = pch - hex_chars;
1360 }
1361
1362 for (i = 0; i < 4; i++) {
1363 struct base_type *pbase = idx[i];
1364
1365 if (pbase == NULL) {
1366 continue;
1367 }
1368 if (bin & (1 << i)) {
1369 BV_SET(*extras, extra_index(base_extra_get(pbase)));
1370 }
1371 }
1372 }
1373
1374 /****************************************************************************
1375 Helper function for loading roads from a savegame.
1376
1377 'ch' gives the character loaded from the savegame. Roads are packed
1378 in four to a character in hex notation. 'index' is a mapping of
1379 savegame bit -> road bit.
1380 ****************************************************************************/
sg_roads_set(bv_extras * extras,char ch,struct road_type ** idx)1381 static void sg_roads_set(bv_extras *extras, char ch, struct road_type **idx)
1382 {
1383 int i, bin;
1384 const char *pch = strchr(hex_chars, ch);
1385
1386 if (!pch || ch == '\0') {
1387 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1388 bin = 0;
1389 } else {
1390 bin = pch - hex_chars;
1391 }
1392
1393 for (i = 0; i < 4; i++) {
1394 struct road_type *proad = idx[i];
1395
1396 if (proad == NULL) {
1397 continue;
1398 }
1399 if (bin & (1 << i)) {
1400 BV_SET(*extras, extra_index(road_extra_get(proad)));
1401 }
1402 }
1403 }
1404
1405 /****************************************************************************
1406 Return the resource for the given identifier.
1407 ****************************************************************************/
char2resource(char c)1408 static struct resource *char2resource(char c)
1409 {
1410 /* speed common values */
1411 if (c == RESOURCE_NULL_IDENTIFIER
1412 || c == RESOURCE_NONE_IDENTIFIER) {
1413 return NULL;
1414 }
1415 return resource_by_identifier(c);
1416 }
1417
1418 /****************************************************************************
1419 Return the identifier for the given resource.
1420 ****************************************************************************/
resource2char(const struct resource * presource)1421 static char resource2char(const struct resource *presource)
1422 {
1423 return presource ? presource->identifier : RESOURCE_NONE_IDENTIFIER;
1424 }
1425
1426 /****************************************************************************
1427 Converts number in to single character. This works to values up to ~70.
1428 ****************************************************************************/
num2char(unsigned int num)1429 static char num2char(unsigned int num)
1430 {
1431 if (num >= strlen(num_chars)) {
1432 return '?';
1433 }
1434
1435 return num_chars[num];
1436 }
1437
1438 /****************************************************************************
1439 Converts single character into numerical value. This is not hex conversion.
1440 ****************************************************************************/
char2num(char ch)1441 static int char2num(char ch)
1442 {
1443 const char *pch;
1444
1445 pch = strchr(num_chars, ch);
1446
1447 sg_failure_ret_val(NULL != pch, 0,
1448 "Unknown ascii value for num: '%c' %d", ch, ch);
1449
1450 return pch - num_chars;
1451 }
1452
1453 /****************************************************************************
1454 Dereferences the terrain character. See terrains[].identifier
1455 example: char2terrain('a') => T_ARCTIC
1456 ****************************************************************************/
char2terrain(char ch)1457 static struct terrain *char2terrain(char ch)
1458 {
1459 /* terrain_by_identifier plus fatal error */
1460 if (ch == TERRAIN_UNKNOWN_IDENTIFIER) {
1461 return T_UNKNOWN;
1462 }
1463 terrain_type_iterate(pterrain) {
1464 if (pterrain->identifier_load == ch) {
1465 return pterrain;
1466 }
1467 } terrain_type_iterate_end;
1468
1469 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1470
1471 exit(EXIT_FAILURE);
1472
1473 RETURN_VALUE_AFTER_EXIT(NULL);
1474 }
1475
1476 /****************************************************************************
1477 References the terrain character. See terrains[].identifier
1478 example: terrain2char(T_ARCTIC) => 'a'
1479 ****************************************************************************/
terrain2char(const struct terrain * pterrain)1480 static char terrain2char(const struct terrain *pterrain)
1481 {
1482 if (pterrain == T_UNKNOWN) {
1483 return TERRAIN_UNKNOWN_IDENTIFIER;
1484 } else {
1485 return pterrain->identifier;
1486 }
1487 }
1488
1489 /*****************************************************************************
1490 Load technology from path_name and if doesn't exist (because savegame
1491 is too old) load from path.
1492 *****************************************************************************/
technology_load(struct section_file * file,const char * path,int plrno)1493 static Tech_type_id technology_load(struct section_file *file,
1494 const char* path, int plrno)
1495 {
1496 char path_with_name[128];
1497 const char* name;
1498 struct advance *padvance;
1499
1500 fc_snprintf(path_with_name, sizeof(path_with_name),
1501 "%s_name", path);
1502
1503 name = secfile_lookup_str(file, path_with_name, plrno);
1504
1505 if (!name || name[0] == '\0') {
1506 /* used by researching_saved */
1507 return A_UNKNOWN;
1508 }
1509 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1510 return A_FUTURE;
1511 }
1512 if (fc_strcasecmp(name, "A_NONE") == 0) {
1513 return A_NONE;
1514 }
1515 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1516 return A_UNSET;
1517 }
1518
1519 padvance = advance_by_rule_name(name);
1520 sg_failure_ret_val(NULL != padvance, A_NONE,
1521 "%s: unknown technology \"%s\".", path_with_name, name);
1522
1523 return advance_number(padvance);
1524 }
1525
1526 /*****************************************************************************
1527 Save technology in secfile entry called path_name.
1528 *****************************************************************************/
technology_save(struct section_file * file,const char * path,int plrno,Tech_type_id tech)1529 static void technology_save(struct section_file *file,
1530 const char* path, int plrno, Tech_type_id tech)
1531 {
1532 char path_with_name[128];
1533 const char* name;
1534
1535 fc_snprintf(path_with_name, sizeof(path_with_name),
1536 "%s_name", path);
1537
1538 switch (tech) {
1539 case A_UNKNOWN: /* used by researching_saved */
1540 name = "";
1541 break;
1542 case A_NONE:
1543 name = "A_NONE";
1544 break;
1545 case A_UNSET:
1546 name = "A_UNSET";
1547 break;
1548 case A_FUTURE:
1549 name = "A_FUTURE";
1550 break;
1551 default:
1552 name = advance_rule_name(advance_by_number(tech));
1553 break;
1554 }
1555
1556 secfile_insert_str(file, name, path_with_name, plrno);
1557 }
1558
1559 /* =======================================================================
1560 * Load / save savefile data.
1561 * ======================================================================= */
1562
1563 /****************************************************************************
1564 Set up correct ruleset for the savegame
1565 ****************************************************************************/
sg_load_ruleset(struct loaddata * loading)1566 static void sg_load_ruleset(struct loaddata *loading)
1567 {
1568 const char *ruleset = secfile_lookup_str_default(loading->file,
1569 GAME_DEFAULT_RULESETDIR,
1570 "savefile.rulesetdir");
1571
1572 /* Load ruleset. */
1573 sz_strlcpy(game.server.rulesetdir, ruleset);
1574 if (!strcmp("default", game.server.rulesetdir)) {
1575 int version;
1576
1577 version = secfile_lookup_int_default(loading->file, -1, "savefile.version");
1578 if (version >= 30) {
1579 /* Here 'default' really means current default.
1580 * Saving happens with real ruleset name, so savegames containing this
1581 * are special scenarios. */
1582 sz_strlcpy(game.server.rulesetdir, GAME_DEFAULT_RULESETDIR);
1583 } else {
1584 /* 'default' is the old name of the classic ruleset */
1585 sz_strlcpy(game.server.rulesetdir, "classic");
1586 }
1587 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1588 ruleset, game.server.rulesetdir);
1589 }
1590 if (!load_rulesets(NULL, TRUE, FALSE)) {
1591 /* Failed to load correct ruleset */
1592 sg_failure_ret(FALSE, _("Failed to load ruleset '%s' needed for savegame."),
1593 ruleset);
1594 }
1595 }
1596
1597 /****************************************************************************
1598 Load '[savefile]'.
1599 ****************************************************************************/
sg_load_savefile(struct loaddata * loading)1600 static void sg_load_savefile(struct loaddata *loading)
1601 {
1602 int i;
1603 const char *terr_name;
1604
1605 /* Check status and return if not OK (sg_success != TRUE). */
1606 sg_check_ret();
1607
1608 /* Load savefile options. */
1609 loading->secfile_options
1610 = secfile_lookup_str(loading->file, "savefile.options");
1611
1612 /* We don't need these entries, but read them anyway to avoid
1613 * warnings about unread secfile entries. */
1614 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1615 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1616
1617 /* In case of savegame2.c saves, missing entry means savegame older than support
1618 * for saving last_updated by turn. So this must default to TRUE. */
1619 game.server.last_updated_year = secfile_lookup_bool_default(loading->file, TRUE,
1620 "savefile.last_updated_as_year");
1621
1622 /* Load improvements. */
1623 loading->improvement.size
1624 = secfile_lookup_int_default(loading->file, 0,
1625 "savefile.improvement_size");
1626 if (loading->improvement.size) {
1627 loading->improvement.order
1628 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1629 "savefile.improvement_vector");
1630 sg_failure_ret(loading->improvement.size != 0,
1631 "Failed to load improvement order: %s",
1632 secfile_error());
1633 }
1634
1635 /* Load technologies. */
1636 loading->technology.size
1637 = secfile_lookup_int_default(loading->file, 0,
1638 "savefile.technology_size");
1639 if (loading->technology.size) {
1640 loading->technology.order
1641 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1642 "savefile.technology_vector");
1643 sg_failure_ret(loading->technology.size != 0,
1644 "Failed to load technology order: %s",
1645 secfile_error());
1646 }
1647
1648 /* Load traits. */
1649 loading->trait.size
1650 = secfile_lookup_int_default(loading->file, 0,
1651 "savefile.trait_size");
1652 if (loading->trait.size) {
1653 loading->trait.order
1654 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1655 "savefile.trait_vector");
1656 sg_failure_ret(loading->trait.size != 0,
1657 "Failed to load trait order: %s",
1658 secfile_error());
1659 }
1660
1661 /* Load extras. */
1662 loading->extra.size
1663 = secfile_lookup_int_default(loading->file, 0,
1664 "savefile.extras_size");
1665 if (loading->extra.size) {
1666 const char **modname;
1667 size_t nmod;
1668 int j;
1669
1670 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1671 "savefile.extras_vector");
1672 sg_failure_ret(loading->extra.size != 0,
1673 "Failed to load extras order: %s",
1674 secfile_error());
1675 sg_failure_ret(!(game.control.num_extra_types < loading->extra.size),
1676 "Number of extras defined by the ruleset (= %d) are "
1677 "lower than the number in the savefile (= %d).",
1678 game.control.num_extra_types, (int)loading->extra.size);
1679 /* make sure that the size of the array is divisible by 4 */
1680 nmod = 4 * ((loading->extra.size + 3) / 4);
1681 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1682 for (j = 0; j < loading->extra.size; j++) {
1683 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1684 }
1685 free(modname);
1686 for (; j < nmod; j++) {
1687 loading->extra.order[j] = NULL;
1688 }
1689 }
1690
1691 /* Load multipliers. */
1692 loading->multiplier.size
1693 = secfile_lookup_int_default(loading->file, 0,
1694 "savefile.multipliers_size");
1695 if (loading->multiplier.size) {
1696 const char **modname;
1697 int j;
1698
1699 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1700 "savefile.multipliers_vector");
1701 sg_failure_ret(loading->multiplier.size != 0,
1702 "Failed to load multipliers order: %s",
1703 secfile_error());
1704 /* It's OK for the set of multipliers in the savefile to differ
1705 * from those in the ruleset. */
1706 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1707 sizeof(*loading->multiplier.order));
1708 for (j = 0; j < loading->multiplier.size; j++) {
1709 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1710 if (!loading->multiplier.order[j]) {
1711 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1712 "discarding", modname[j]);
1713 }
1714 }
1715 free(modname);
1716 }
1717
1718 /* Load specials. */
1719 loading->special.size
1720 = secfile_lookup_int_default(loading->file, 0,
1721 "savefile.specials_size");
1722 if (loading->special.size) {
1723 const char **modname;
1724 size_t nmod;
1725 enum tile_special_type j;
1726
1727 modname = secfile_lookup_str_vec(loading->file, &loading->special.size,
1728 "savefile.specials_vector");
1729 sg_failure_ret(loading->special.size != 0,
1730 "Failed to load specials order: %s",
1731 secfile_error());
1732 /* make sure that the size of the array is divisible by 4 */
1733 /* Allocating extra 4 slots, just a couple of bytes,
1734 * in case of special.size being divisible by 4 already is intentional.
1735 * Added complexity would cost those couple of bytes in code size alone,
1736 * and we actually need at least one slot immediately after last valid
1737 * one. That's where S_LAST is (or was in version that saved the game)
1738 * and in some cases S_LAST gets written to savegame, at least as
1739 * activity target special when activity targets some base or road
1740 * instead. By having current S_LAST in that index allows us to map
1741 * that old S_LAST to current S_LAST, just like any real special within
1742 * special.size gets mapped. */
1743 nmod = loading->special.size + (4 - (loading->special.size % 4));
1744 loading->special.order = fc_calloc(nmod,
1745 sizeof(*loading->special.order));
1746 for (j = 0; j < loading->special.size; j++) {
1747 if (!strcasecmp("Road", modname[j])) {
1748 loading->special.order[j] = S_OLD_ROAD;
1749 } else if (!strcasecmp("Railroad", modname[j])) {
1750 loading->special.order[j] = S_OLD_RAILROAD;
1751 } else if (!strcasecmp("River", modname[j])) {
1752 loading->special.order[j] = S_OLD_RIVER;
1753 } else {
1754 loading->special.order[j] = special_by_rule_name(modname[j]);
1755 }
1756 }
1757 free(modname);
1758 for (; j < nmod; j++) {
1759 loading->special.order[j] = S_LAST;
1760 }
1761 }
1762
1763 /* Load bases. */
1764 loading->base.size
1765 = secfile_lookup_int_default(loading->file, 0,
1766 "savefile.bases_size");
1767 if (loading->base.size) {
1768 const char **modname;
1769 size_t nmod;
1770 int j;
1771
1772 modname = secfile_lookup_str_vec(loading->file, &loading->base.size,
1773 "savefile.bases_vector");
1774 sg_failure_ret(loading->base.size != 0,
1775 "Failed to load bases order: %s",
1776 secfile_error());
1777 /* make sure that the size of the array is divisible by 4 */
1778 nmod = 4 * ((loading->base.size + 3) / 4);
1779 loading->base.order = fc_calloc(nmod, sizeof(*loading->base.order));
1780 for (j = 0; j < loading->base.size; j++) {
1781 struct extra_type *pextra = extra_type_by_rule_name(modname[j]);
1782
1783 sg_failure_ret(pextra != NULL
1784 || game.control.num_base_types >= loading->base.size,
1785 "Unknown base type %s in savefile.",
1786 modname[j]);
1787
1788 if (pextra != NULL) {
1789 loading->base.order[j] = extra_base_get(pextra);
1790 } else {
1791 loading->base.order[j] = NULL;
1792 }
1793 }
1794 free(modname);
1795 for (; j < nmod; j++) {
1796 loading->base.order[j] = NULL;
1797 }
1798 }
1799
1800 /* Load roads. */
1801 loading->road.size
1802 = secfile_lookup_int_default(loading->file, 0,
1803 "savefile.roads_size");
1804 if (loading->road.size) {
1805 const char **modname;
1806 size_t nmod;
1807 int j;
1808
1809 modname = secfile_lookup_str_vec(loading->file, &loading->road.size,
1810 "savefile.roads_vector");
1811 sg_failure_ret(loading->road.size != 0,
1812 "Failed to load roads order: %s",
1813 secfile_error());
1814 sg_failure_ret(!(game.control.num_road_types < loading->road.size),
1815 "Number of roads defined by the ruleset (= %d) are "
1816 "lower than the number in the savefile (= %d).",
1817 game.control.num_road_types, (int)loading->road.size);
1818 /* make sure that the size of the array is divisible by 4 */
1819 nmod = 4 * ((loading->road.size + 3) / 4);
1820 loading->road.order = fc_calloc(nmod, sizeof(*loading->road.order));
1821 for (j = 0; j < loading->road.size; j++) {
1822 struct extra_type *pextra = extra_type_by_rule_name(modname[j]);
1823
1824 if (pextra != NULL) {
1825 loading->road.order[j] = extra_road_get(pextra);
1826 } else {
1827 loading->road.order[j] = NULL;
1828 }
1829 }
1830 free(modname);
1831 for (; j < nmod; j++) {
1832 loading->road.order[j] = NULL;
1833 }
1834 }
1835
1836 /* Load specialists. */
1837 loading->specialist.size
1838 = secfile_lookup_int_default(loading->file, 0,
1839 "savefile.specialists_size");
1840 if (loading->specialist.size) {
1841 const char **modname;
1842 size_t nmod;
1843 int j;
1844
1845 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1846 "savefile.specialists_vector");
1847 sg_failure_ret(loading->specialist.size != 0,
1848 "Failed to load specialists order: %s",
1849 secfile_error());
1850 sg_failure_ret(!(game.control.num_specialist_types < loading->specialist.size),
1851 "Number of specialists defined by the ruleset (= %d) are "
1852 "lower than the number in the savefile (= %d).",
1853 game.control.num_specialist_types, (int)loading->specialist.size);
1854 /* make sure that the size of the array is divisible by 4 */
1855 /* That's not really needed with specialists at the moment, but done this way
1856 * for consistency with other types, and to be prepared for the time it needs
1857 * to be this way. */
1858 nmod = 4 * ((loading->specialist.size + 3) / 4);
1859 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1860 for (j = 0; j < loading->specialist.size; j++) {
1861 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1862 }
1863 free(modname);
1864 for (; j < nmod; j++) {
1865 loading->specialist.order[j] = NULL;
1866 }
1867 }
1868
1869 /* Load diplomatic state type order. */
1870 loading->ds_t.size
1871 = secfile_lookup_int_default(loading->file, 0,
1872 "savefile.diplstate_type_size");
1873
1874 sg_failure_ret(loading->ds_t.size > 0,
1875 "Failed to load diplomatic state type order: %s",
1876 secfile_error());
1877
1878 if (loading->ds_t.size) {
1879 const char **modname;
1880 int j;
1881
1882 modname = secfile_lookup_str_vec(loading->file, &loading->ds_t.size,
1883 "savefile.diplstate_type_vector");
1884
1885 loading->ds_t.order = fc_calloc(loading->ds_t.size,
1886 sizeof(*loading->ds_t.order));
1887
1888 for (j = 0; j < loading->ds_t.size; j++) {
1889 loading->ds_t.order[j] = diplstate_type_by_name(modname[j],
1890 fc_strcasecmp);
1891 }
1892
1893 free(modname);
1894 }
1895
1896 terrain_type_iterate(pterr) {
1897 pterr->identifier_load = '\0';
1898 } terrain_type_iterate_end;
1899
1900 i = 0;
1901 while ((terr_name = secfile_lookup_str_default(loading->file, NULL,
1902 "savefile.terrident%d.name", i)) != NULL) {
1903 struct terrain *pterr = terrain_by_rule_name(terr_name);
1904
1905 if (pterr != NULL) {
1906 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1907 "savefile.terrident%d.identifier", i);
1908
1909 pterr->identifier_load = *iptr;
1910 } else {
1911 log_error("Identifier for unknown terrain type %s.", terr_name);
1912 }
1913 i++;
1914 }
1915
1916 terrain_type_iterate(pterr) {
1917 terrain_type_iterate(pterr2) {
1918 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1919 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1920 "%s and %s share a saved identifier",
1921 terrain_rule_name(pterr), terrain_rule_name(pterr2));
1922 }
1923 } terrain_type_iterate_end;
1924 } terrain_type_iterate_end;
1925 }
1926
1927 /****************************************************************************
1928 Save '[savefile]'.
1929 ****************************************************************************/
sg_save_savefile(struct savedata * saving)1930 static void sg_save_savefile(struct savedata *saving)
1931 {
1932 int i;
1933
1934 /* Check status and return if not OK (sg_success != TRUE). */
1935 sg_check_ret();
1936
1937 /* Save savefile options. */
1938 sg_save_savefile_options(saving, savefile_options_default);
1939
1940 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1941
1942 /* Save reason of the savefile generation. */
1943 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1944
1945 /* Save as accurate freeciv revision information as possible */
1946 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1947
1948 /* Save rulesetdir at this point as this ruleset is required by this
1949 * savefile. */
1950 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1951
1952 if (game.control.version[0] != '\0') {
1953 /* Current ruleset has version information, save it.
1954 * This is never loaded, but exist in savegame file only for debugging purposes. */
1955 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1956 }
1957
1958 secfile_insert_bool(saving->file, game.server.last_updated_year,
1959 "savefile.last_updated_as_year");
1960
1961 /* Save improvement order in savegame, so we are not dependent on ruleset
1962 * order. If the game isn't started improvements aren't loaded so we can
1963 * not save the order. */
1964 secfile_insert_int(saving->file, improvement_count(),
1965 "savefile.improvement_size");
1966 if (improvement_count() > 0) {
1967 const char* buf[improvement_count()];
1968
1969 improvement_iterate(pimprove) {
1970 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1971 } improvement_iterate_end;
1972
1973 secfile_insert_str_vec(saving->file, buf, improvement_count(),
1974 "savefile.improvement_vector");
1975 }
1976
1977 /* Save technology order in savegame, so we are not dependent on ruleset
1978 * order. If the game isn't started advances aren't loaded so we can not
1979 * save the order. */
1980 secfile_insert_int(saving->file, game.control.num_tech_types,
1981 "savefile.technology_size");
1982 if (game.control.num_tech_types > 0) {
1983 const char* buf[game.control.num_tech_types];
1984
1985 buf[A_NONE] = "A_NONE";
1986 advance_iterate(A_FIRST, a) {
1987 buf[advance_index(a)] = advance_rule_name(a);
1988 } advance_iterate_end;
1989 secfile_insert_str_vec(saving->file, buf, game.control.num_tech_types,
1990 "savefile.technology_vector");
1991 }
1992
1993 /* Save activities order in the savegame. */
1994 secfile_insert_int(saving->file, ACTIVITY_LAST,
1995 "savefile.activities_size");
1996 if (ACTIVITY_LAST > 0) {
1997 const char **modname;
1998 int j;
1999
2000 i = 0;
2001
2002 modname = fc_calloc(ACTIVITY_LAST, sizeof(*modname));
2003
2004 for (j = 0; j < ACTIVITY_LAST; j++) {
2005 modname[i++] = unit_activity_name(j);
2006 }
2007
2008 secfile_insert_str_vec(saving->file, modname,
2009 ACTIVITY_LAST,
2010 "savefile.activities_vector");
2011 free(modname);
2012 }
2013
2014 /* Save specialists order in the savegame. */
2015 secfile_insert_int(saving->file, specialist_count(),
2016 "savefile.specialists_size");
2017 {
2018 const char **modname;
2019
2020 i = 0;
2021 modname = fc_calloc(specialist_count(), sizeof(*modname));
2022
2023 specialist_type_iterate(sp) {
2024 modname[i++] = specialist_rule_name(specialist_by_number(sp));
2025 } specialist_type_iterate_end;
2026
2027 secfile_insert_str_vec(saving->file, modname, specialist_count(),
2028 "savefile.specialists_vector");
2029
2030 free(modname);
2031 }
2032
2033 /* Save trait order in savegame. */
2034 secfile_insert_int(saving->file, TRAIT_COUNT,
2035 "savefile.trait_size");
2036 {
2037 const char **modname;
2038 enum trait tr;
2039 int j;
2040
2041 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
2042
2043 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
2044 modname[j] = trait_name(tr);
2045 }
2046
2047 secfile_insert_str_vec(saving->file, modname, TRAIT_COUNT,
2048 "savefile.trait_vector");
2049 free(modname);
2050 }
2051
2052 /* Save extras order in the savegame. */
2053 secfile_insert_int(saving->file, game.control.num_extra_types,
2054 "savefile.extras_size");
2055 if (game.control.num_extra_types > 0) {
2056 const char **modname;
2057
2058 i = 0;
2059 modname = fc_calloc(game.control.num_extra_types, sizeof(*modname));
2060
2061 extra_type_iterate(pextra) {
2062 modname[i++] = extra_rule_name(pextra);
2063 } extra_type_iterate_end;
2064
2065 secfile_insert_str_vec(saving->file, modname,
2066 game.control.num_extra_types,
2067 "savefile.extras_vector");
2068 free(modname);
2069 }
2070
2071 /* Save multipliers order in the savegame. */
2072 secfile_insert_int(saving->file, multiplier_count(),
2073 "savefile.multipliers_size");
2074 if (multiplier_count() > 0) {
2075 const char **modname;
2076
2077 i = 0;
2078 modname = fc_calloc(multiplier_count(), sizeof(*modname));
2079
2080 multipliers_iterate(pmul) {
2081 modname[multiplier_index(pmul)] = multiplier_rule_name(pmul);
2082 } multipliers_iterate_end;
2083
2084 secfile_insert_str_vec(saving->file, modname,
2085 multiplier_count(),
2086 "savefile.multipliers_vector");
2087 free(modname);
2088 }
2089
2090 /* Save diplstate type order in the savegame. */
2091 secfile_insert_int(saving->file, DS_LAST,
2092 "savefile.diplstate_type_size");
2093 if (DS_LAST > 0) {
2094 const char **modname;
2095 int j;
2096
2097 i = 0;
2098 modname = fc_calloc(DS_LAST, sizeof(*modname));
2099
2100 for (j = 0; j < DS_LAST; j++) {
2101 modname[i++] = diplstate_type_name(j);
2102 }
2103
2104 secfile_insert_str_vec(saving->file, modname,
2105 DS_LAST,
2106 "savefile.diplstate_type_vector");
2107 free(modname);
2108 }
2109
2110 /* Save city_option order in the savegame. */
2111 secfile_insert_int(saving->file, CITYO_LAST,
2112 "savefile.city_options_size");
2113 if (CITYO_LAST > 0) {
2114 const char **modname;
2115 int j;
2116
2117 i = 0;
2118 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
2119
2120 for (j = 0; j < CITYO_LAST; j++) {
2121 modname[i++] = city_options_name(j);
2122 }
2123
2124 secfile_insert_str_vec(saving->file, modname,
2125 CITYO_LAST,
2126 "savefile.city_options_vector");
2127 free(modname);
2128 }
2129
2130 /* Save terrain character mapping in the savegame. */
2131 i = 0;
2132 terrain_type_iterate(pterr) {
2133 char buf[2];
2134
2135 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2136 buf[0] = terrain_identifier(pterr);
2137 buf[1] = '\0';
2138 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2139 } terrain_type_iterate_end;
2140 }
2141
2142 /****************************************************************************
2143 Save options for this savegame. sg_load_savefile_options() is not defined.
2144 ****************************************************************************/
sg_save_savefile_options(struct savedata * saving,const char * option)2145 static void sg_save_savefile_options(struct savedata *saving,
2146 const char *option)
2147 {
2148 /* Check status and return if not OK (sg_success != TRUE). */
2149 sg_check_ret();
2150
2151 if (option == NULL) {
2152 /* no additional option */
2153 return;
2154 }
2155
2156 sz_strlcat(saving->secfile_options, option);
2157 secfile_replace_str(saving->file, saving->secfile_options,
2158 "savefile.options");
2159 }
2160
2161 /* =======================================================================
2162 * Load / save game status.
2163 * ======================================================================= */
2164
2165 /****************************************************************************
2166 Load '[ruledata]'.
2167 ****************************************************************************/
sg_load_ruledata(struct loaddata * loading)2168 static void sg_load_ruledata(struct loaddata *loading)
2169 {
2170 int i;
2171 const char *name;
2172
2173 /* Check status and return if not OK (sg_success != TRUE). */
2174 sg_check_ret();
2175
2176 for (i = 0;
2177 (name = secfile_lookup_str_default(loading->file, NULL,
2178 "ruledata.government%d.name", i));
2179 i++) {
2180 struct government *gov = government_by_rule_name(name);
2181
2182 if (gov != NULL) {
2183 gov->changed_to_times = secfile_lookup_int_default(loading->file, 0,
2184 "ruledata.government%d.changes", i);
2185 }
2186 }
2187 }
2188
2189 /****************************************************************************
2190 Load '[game]'.
2191 ****************************************************************************/
sg_load_game(struct loaddata * loading)2192 static void sg_load_game(struct loaddata *loading)
2193 {
2194 int game_version;
2195 const char *string;
2196 const char *level;
2197 int i;
2198
2199 /* Check status and return if not OK (sg_success != TRUE). */
2200 sg_check_ret();
2201
2202 /* Load version. */
2203 game_version
2204 = secfile_lookup_int_default(loading->file, 0, "game.version");
2205 /* We require at least version 2.2.99 */
2206 sg_failure_ret(20299 <= game_version, "Saved game is too old, at least "
2207 "version 2.2.99 required.");
2208
2209 /* Load server state. */
2210 string = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2211 "game.server_state");
2212 loading->server_state = server_states_by_name(string, strcmp);
2213 if (!server_states_is_valid(loading->server_state)) {
2214 /* Don't take any risk! */
2215 loading->server_state = S_S_INITIAL;
2216 }
2217
2218 string = secfile_lookup_str_default(loading->file,
2219 default_meta_patches_string(),
2220 "game.meta_patches");
2221 set_meta_patches_string(string);
2222 game.server.meta_info.user_message_set
2223 = secfile_lookup_bool_default(loading->file, FALSE,
2224 "game.meta_usermessage");
2225 if (game.server.meta_info.user_message_set) {
2226 string = secfile_lookup_str_default(loading->file,
2227 default_meta_message_string(),
2228 "game.meta_message");
2229 set_user_meta_message_string(string);
2230 }
2231
2232 if (0 == strcmp(DEFAULT_META_SERVER_ADDR, srvarg.metaserver_addr)) {
2233 /* Do not overwrite this if the user requested a specific metaserver
2234 * from the command line (option --Metaserver). */
2235 sz_strlcpy(srvarg.metaserver_addr,
2236 secfile_lookup_str_default(loading->file,
2237 DEFAULT_META_SERVER_ADDR,
2238 "game.meta_server"));
2239 }
2240
2241 if ('\0' == srvarg.serverid[0]) {
2242 /* Do not overwrite this if the user requested a specific metaserver
2243 * from the command line (option --serverid). */
2244 sz_strlcpy(srvarg.serverid,
2245 secfile_lookup_str_default(loading->file, "",
2246 "game.serverid"));
2247 }
2248 sz_strlcpy(server.game_identifier,
2249 secfile_lookup_str_default(loading->file, "", "game.id"));
2250 /* We are not checking game_identifier legality just yet.
2251 * That's done when we are sure that rand seed has been initialized,
2252 * so that we can generate new game_identifier, if needed.
2253 * See sq_load_sanitycheck(). */
2254
2255 level = secfile_lookup_str_default(loading->file, NULL,
2256 "game.level");
2257 if (level != NULL) {
2258 game.info.skill_level = ai_level_by_name(level, fc_strcasecmp);
2259 } else {
2260 game.info.skill_level = ai_level_invalid();
2261 }
2262
2263 if (!ai_level_is_valid(game.info.skill_level)) {
2264 game.info.skill_level
2265 = ai_level_convert(secfile_lookup_int_default(loading->file,
2266 GAME_HARDCODED_DEFAULT_SKILL_LEVEL,
2267 "game.skill_level"));
2268 }
2269 game.info.phase_mode
2270 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_PHASE_MODE,
2271 "game.phase_mode");
2272 game.server.phase_mode_stored
2273 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_PHASE_MODE,
2274 "game.phase_mode_stored");
2275 game.info.phase
2276 = secfile_lookup_int_default(loading->file, 0,
2277 "game.phase");
2278 game.server.scoreturn
2279 = secfile_lookup_int_default(loading->file,
2280 game.info.turn + GAME_DEFAULT_SCORETURN,
2281 "game.scoreturn");
2282
2283 game.server.timeoutint
2284 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINT,
2285 "game.timeoutint");
2286 game.server.timeoutintinc
2287 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINTINC,
2288 "game.timeoutintinc");
2289 game.server.timeoutinc
2290 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINC,
2291 "game.timeoutinc");
2292 game.server.timeoutincmult
2293 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINCMULT,
2294 "game.timeoutincmult");
2295 game.server.timeoutcounter
2296 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTCOUNTER,
2297 "game.timeoutcounter");
2298
2299 game.info.turn
2300 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2301 sg_failure_ret(secfile_lookup_int(loading->file, &game.info.year32,
2302 "game.year"), "%s", secfile_error());
2303 game.info.year16 = game.info.year32;
2304 game.info.year_0_hack
2305 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2306
2307 game.info.globalwarming
2308 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2309 game.info.heating
2310 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2311 game.info.warminglevel
2312 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2313
2314 game.info.nuclearwinter
2315 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2316 game.info.cooling
2317 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2318 game.info.coolinglevel
2319 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2320
2321 /* Global advances. */
2322 string = secfile_lookup_str_default(loading->file, NULL,
2323 "game.global_advances");
2324 if (string != NULL) {
2325 sg_failure_ret(strlen(string) == loading->technology.size,
2326 "Invalid length of 'game.global_advances' (%lu ~= %lu).",
2327 (unsigned long) strlen(string),
2328 (unsigned long) loading->technology.size);
2329 for (i = 0; i < loading->technology.size; i++) {
2330 sg_failure_ret(string[i] == '1' || string[i] == '0',
2331 "Undefined value '%c' within 'game.global_advances'.",
2332 string[i]);
2333 if (string[i] == '1') {
2334 struct advance *padvance =
2335 advance_by_rule_name(loading->technology.order[i]);
2336
2337 if (padvance != NULL) {
2338 game.info.global_advances[advance_number(padvance)] = TRUE;
2339 }
2340 }
2341 }
2342 }
2343
2344 game.info.is_new_game
2345 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2346
2347 game.server.turn_change_time
2348 = secfile_lookup_int_default(loading->file, 0, "game.last_turn_change_time") / 100;
2349 }
2350
2351 /****************************************************************************
2352 Save '[ruledata]'.
2353 ****************************************************************************/
sg_save_ruledata(struct savedata * saving)2354 static void sg_save_ruledata(struct savedata *saving)
2355 {
2356 int set_count = 0;
2357
2358 governments_iterate(pgov) {
2359 char path[256];
2360
2361 fc_snprintf(path, sizeof(path),
2362 "ruledata.government%d", set_count++);
2363
2364 secfile_insert_str(saving->file, government_rule_name(pgov),
2365 "%s.name", path);
2366 secfile_insert_int(saving->file, pgov->changed_to_times,
2367 "%s.changes", path);
2368 } governments_iterate_end;
2369 }
2370
2371 /****************************************************************************
2372 Save '[game]'.
2373 ****************************************************************************/
sg_save_game(struct savedata * saving)2374 static void sg_save_game(struct savedata *saving)
2375 {
2376 int game_version;
2377 const char *user_message;
2378 enum server_states srv_state;
2379 char global_advances[game.control.num_tech_types + 1];
2380 int i;
2381
2382 /* Check status and return if not OK (sg_success != TRUE). */
2383 sg_check_ret();
2384
2385 game_version = MAJOR_VERSION *10000 + MINOR_VERSION *100 + PATCH_VERSION;
2386 secfile_insert_int(saving->file, game_version, "game.version");
2387
2388 /* Game state: once the game is no longer a new game (ie, has been
2389 * started the first time), it should always be considered a running
2390 * game for savegame purposes. */
2391 if (saving->scenario && !game.scenario.players) {
2392 srv_state = S_S_INITIAL;
2393 } else {
2394 srv_state = game.info.is_new_game ? server_state() : S_S_RUNNING;
2395 }
2396 secfile_insert_str(saving->file, server_states_name(srv_state),
2397 "game.server_state");
2398
2399 secfile_insert_str(saving->file, get_meta_patches_string(),
2400 "game.meta_patches");
2401 secfile_insert_bool(saving->file, game.server.meta_info.user_message_set,
2402 "game.meta_usermessage");
2403 user_message = get_user_meta_message_string();
2404 if (user_message != NULL) {
2405 secfile_insert_str(saving->file, user_message, "game.meta_message");
2406 }
2407 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2408
2409 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2410 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2411
2412 secfile_insert_str(saving->file, ai_level_name(game.info.skill_level),
2413 "game.level");
2414 secfile_insert_int(saving->file, game.info.phase_mode,
2415 "game.phase_mode");
2416 secfile_insert_int(saving->file, game.server.phase_mode_stored,
2417 "game.phase_mode_stored");
2418 secfile_insert_int(saving->file, game.info.phase,
2419 "game.phase");
2420 secfile_insert_int(saving->file, game.server.scoreturn,
2421 "game.scoreturn");
2422
2423 secfile_insert_int(saving->file, game.server.timeoutint,
2424 "game.timeoutint");
2425 secfile_insert_int(saving->file, game.server.timeoutintinc,
2426 "game.timeoutintinc");
2427 secfile_insert_int(saving->file, game.server.timeoutinc,
2428 "game.timeoutinc");
2429 secfile_insert_int(saving->file, game.server.timeoutincmult,
2430 "game.timeoutincmult");
2431 secfile_insert_int(saving->file, game.server.timeoutcounter,
2432 "game.timeoutcounter");
2433
2434 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2435 secfile_insert_int(saving->file, game.info.year32, "game.year");
2436 secfile_insert_bool(saving->file, game.info.year_0_hack,
2437 "game.year_0_hack");
2438
2439 secfile_insert_int(saving->file, game.info.globalwarming,
2440 "game.globalwarming");
2441 secfile_insert_int(saving->file, game.info.heating,
2442 "game.heating");
2443 secfile_insert_int(saving->file, game.info.warminglevel,
2444 "game.warminglevel");
2445
2446 secfile_insert_int(saving->file, game.info.nuclearwinter,
2447 "game.nuclearwinter");
2448 secfile_insert_int(saving->file, game.info.cooling,
2449 "game.cooling");
2450 secfile_insert_int(saving->file, game.info.coolinglevel,
2451 "game.coolinglevel");
2452 /* For debugging purposes only.
2453 * Do not save it if it's 0 (not known);
2454 * this confuses people reading this 'document' less than
2455 * saving 0. */
2456 if (game.server.seed != 0) {
2457 secfile_insert_int(saving->file, game.server.seed,
2458 "game.random_seed");
2459 }
2460
2461 /* Global advances. */
2462 for (i = 0; i < game.control.num_tech_types; i++) {
2463 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2464 }
2465 global_advances[i] = '\0';
2466 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2467
2468 if (!game_was_started()) {
2469 saving->save_players = FALSE;
2470 } else {
2471 if (saving->scenario) {
2472 saving->save_players = game.scenario.players;
2473 } else {
2474 saving->save_players = TRUE;
2475 }
2476 #ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2477 secfile_insert_int(saving->file, game.server.turn_change_time * 100,
2478 "game.last_turn_change_time");
2479 #else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2480 secfile_insert_int(saving->file, game.info.turn * 10,
2481 "game.last_turn_change_time");
2482 #endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2483 }
2484 secfile_insert_bool(saving->file, saving->save_players,
2485 "game.save_players");
2486 }
2487
2488 /* =======================================================================
2489 * Load / save random status.
2490 * ======================================================================= */
2491
2492 /****************************************************************************
2493 Load '[random]'.
2494 ****************************************************************************/
sg_load_random(struct loaddata * loading)2495 static void sg_load_random(struct loaddata *loading)
2496 {
2497 /* Check status and return if not OK (sg_success != TRUE). */
2498 sg_check_ret();
2499
2500 if (secfile_lookup_bool_default(loading->file, FALSE, "random.save")) {
2501 const char *string;
2502 int i;
2503
2504 /* Since random state was previously saved, save it also when resaving.
2505 * This affects only pre-2.6 scenarios where scenario.save_random
2506 * is not defined.
2507 * - If this is 2.6 or later scenario -> it would have saved random.save = TRUE
2508 * only if scenario.save_random is already TRUE
2509 *
2510 * Do NOT touch this in case of regular savegame. They always have random.save
2511 * set, but if one starts to make scenario based on a savegame, we want
2512 * default scenario settings in the beginning (default save_random = FALSE).
2513 */
2514 if (game.scenario.is_scenario) {
2515 game.scenario.save_random = TRUE;
2516 }
2517
2518 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.j,
2519 "random.index_J"), "%s", secfile_error());
2520 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.k,
2521 "random.index_K"), "%s", secfile_error());
2522 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.x,
2523 "random.index_X"), "%s", secfile_error());
2524
2525 for (i = 0; i < 8; i++) {
2526 string = secfile_lookup_str(loading->file, "random.table%d",i);
2527 sg_failure_ret(NULL != string, "%s", secfile_error());
2528 sscanf(string, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2529 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2530 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2531 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2532 }
2533 loading->rstate.is_init = TRUE;
2534 fc_rand_set_state(loading->rstate);
2535 } else {
2536 /* No random values - mark the setting. */
2537 (void) secfile_entry_by_path(loading->file, "random.save");
2538
2539 /* We're loading a game without a seed (which is okay, if it's a scenario).
2540 * We need to generate the game seed now because it will be needed later
2541 * during the load. */
2542 init_game_seed();
2543 loading->rstate = fc_rand_state();
2544 }
2545 }
2546
2547 /****************************************************************************
2548 Save '[random]'.
2549 ****************************************************************************/
sg_save_random(struct savedata * saving)2550 static void sg_save_random(struct savedata *saving)
2551 {
2552 /* Check status and return if not OK (sg_success != TRUE). */
2553 sg_check_ret();
2554
2555 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2556 int i;
2557 RANDOM_STATE rstate = fc_rand_state();
2558
2559 secfile_insert_bool(saving->file, TRUE, "random.save");
2560 fc_assert(rstate.is_init);
2561
2562 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2563 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2564 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2565
2566 for (i = 0; i < 8; i++) {
2567 char vec[100];
2568
2569 fc_snprintf(vec, sizeof(vec),
2570 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2571 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2572 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2573 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2574 secfile_insert_str(saving->file, vec, "random.table%d", i);
2575 }
2576 } else {
2577 secfile_insert_bool(saving->file, FALSE, "random.save");
2578 }
2579 }
2580
2581 /* =======================================================================
2582 * Load / save lua script data.
2583 * ======================================================================= */
2584
2585 /****************************************************************************
2586 Load '[script]'.
2587 ****************************************************************************/
sg_load_script(struct loaddata * loading)2588 static void sg_load_script(struct loaddata *loading)
2589 {
2590 /* Check status and return if not OK (sg_success != TRUE). */
2591 sg_check_ret();
2592
2593 script_server_state_load(loading->file);
2594 }
2595
2596 /****************************************************************************
2597 Save '[script]'.
2598 ****************************************************************************/
sg_save_script(struct savedata * saving)2599 static void sg_save_script(struct savedata *saving)
2600 {
2601 /* Check status and return if not OK (sg_success != TRUE). */
2602 sg_check_ret();
2603
2604 script_server_state_save(saving->file);
2605 }
2606
2607 /* =======================================================================
2608 * Load / save scenario data.
2609 * ======================================================================= */
2610
2611 /****************************************************************************
2612 Load '[scenario]'.
2613 ****************************************************************************/
sg_load_scenario(struct loaddata * loading)2614 static void sg_load_scenario(struct loaddata *loading)
2615 {
2616 const char *buf;
2617 bool lake_flood_default;
2618
2619 /* Check status and return if not OK (sg_success != TRUE). */
2620 sg_check_ret();
2621
2622 if (NULL == secfile_section_lookup(loading->file, "scenario")) {
2623 game.scenario.is_scenario = FALSE;
2624
2625 return;
2626 }
2627
2628 /* Default is that when there's scenario section (which we already checked)
2629 * this is a scenario. Only if it explicitly says that it's not, we consider
2630 * this regular savegame */
2631 game.scenario.is_scenario = secfile_lookup_bool_default(loading->file, TRUE, "scenario.is_scenario");
2632
2633 if (!game.scenario.is_scenario) {
2634 return;
2635 }
2636
2637 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2638 if (buf[0] != '\0') {
2639 sz_strlcpy(game.scenario.name, buf);
2640 }
2641
2642 buf = secfile_lookup_str_default(loading->file, "",
2643 "scenario.authors");
2644 if (buf[0] != '\0') {
2645 sz_strlcpy(game.scenario.authors, buf);
2646 } else {
2647 game.scenario.authors[0] = '\0';
2648 }
2649
2650 buf = secfile_lookup_str_default(loading->file, "",
2651 "scenario.description");
2652 if (buf[0] != '\0') {
2653 sz_strlcpy(game.scenario_desc.description, buf);
2654 } else {
2655 game.scenario_desc.description[0] = '\0';
2656 }
2657
2658 game.scenario.save_random
2659 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2660 game.scenario.players
2661 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2662 game.scenario.startpos_nations
2663 = secfile_lookup_bool_default(loading->file, FALSE,
2664 "scenario.startpos_nations");
2665
2666 game.scenario.prevent_new_cities
2667 = secfile_lookup_bool_default(loading->file, FALSE,
2668 "scenario.prevent_new_cities");
2669 if (loading->version < 20599) {
2670 /* Lake flooding may break some old scenarios where rivers made out of
2671 * lake terrains, so play safe there */
2672 lake_flood_default = FALSE;
2673 } else {
2674 /* If lake flooding is a problem for a newer scenario, it could explicitly
2675 * disable it. */
2676 lake_flood_default = TRUE;
2677 }
2678 game.scenario.lake_flooding
2679 = secfile_lookup_bool_default(loading->file, lake_flood_default,
2680 "scenario.lake_flooding");
2681 game.scenario.handmade
2682 = secfile_lookup_bool_default(loading->file, FALSE,
2683 "scenario.handmade");
2684 game.scenario.allow_ai_type_fallback
2685 = secfile_lookup_bool_default(loading->file, FALSE,
2686 "scenario.allow_ai_type_fallback");
2687
2688 sg_failure_ret(loading->server_state == S_S_INITIAL
2689 || (loading->server_state == S_S_RUNNING
2690 && game.scenario.players == TRUE),
2691 "Invalid scenario definition (server state '%s' and "
2692 "players are %s).",
2693 server_states_name(loading->server_state),
2694 game.scenario.players ? "saved" : "not saved");
2695
2696 /* Remove all defined players. They are recreated with the skill level
2697 * defined by the scenario. */
2698 (void) aifill(0);
2699 }
2700
2701 /****************************************************************************
2702 Save '[scenario]'.
2703 ****************************************************************************/
sg_save_scenario(struct savedata * saving)2704 static void sg_save_scenario(struct savedata *saving)
2705 {
2706 struct entry *mod_entry;
2707 int game_version;
2708
2709 /* Check status and return if not OK (sg_success != TRUE). */
2710 sg_check_ret();
2711
2712 if (!saving->scenario || !game.scenario.is_scenario) {
2713 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2714 return;
2715 }
2716
2717 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2718
2719 game_version = MAJOR_VERSION * 10000 + MINOR_VERSION * 100 + PATCH_VERSION;
2720 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2721
2722 /* Name is mandatory to the level that is saved even if empty. */
2723 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2724 entry_str_set_gt_marking(mod_entry, TRUE);
2725
2726 /* Authors list is saved only if it exist */
2727 if (game.scenario.authors[0] != '\0') {
2728 mod_entry = secfile_insert_str(saving->file, game.scenario.authors,
2729 "scenario.authors");
2730 entry_str_set_gt_marking(mod_entry, TRUE);
2731 }
2732
2733 /* Description is saved only if it exist */
2734 if (game.scenario_desc.description[0] != '\0') {
2735 mod_entry = secfile_insert_str(saving->file, game.scenario_desc.description,
2736 "scenario.description");
2737 entry_str_set_gt_marking(mod_entry, TRUE);
2738 }
2739
2740 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2741 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2742 secfile_insert_bool(saving->file, game.scenario.startpos_nations,
2743 "scenario.startpos_nations");
2744 if (game.scenario.prevent_new_cities) {
2745 secfile_insert_bool(saving->file, game.scenario.prevent_new_cities,
2746 "scenario.prevent_new_cities");
2747 }
2748 secfile_insert_bool(saving->file, game.scenario.lake_flooding,
2749 "scenario.lake_flooding");
2750 if (game.scenario.handmade) {
2751 secfile_insert_bool(saving->file, game.scenario.handmade,
2752 "scenario.handmade");
2753 }
2754 if (game.scenario.allow_ai_type_fallback) {
2755 secfile_insert_bool(saving->file, game.scenario.allow_ai_type_fallback,
2756 "scenario.allow_ai_type_fallback");
2757 }
2758 }
2759
2760 /* =======================================================================
2761 * Load / save game settings.
2762 * ======================================================================= */
2763
2764 /****************************************************************************
2765 Load '[settings]'.
2766 ****************************************************************************/
sg_load_settings(struct loaddata * loading)2767 static void sg_load_settings(struct loaddata *loading)
2768 {
2769 /* Check status and return if not OK (sg_success != TRUE). */
2770 sg_check_ret();
2771
2772 settings_game_load(loading->file, "settings");
2773
2774 /* Save current status of fogofwar. */
2775 game.server.fogofwar_old = game.info.fogofwar;
2776
2777 /* Add all compatibility settings here. */
2778 }
2779
2780 /****************************************************************************
2781 Save [settings].
2782 ****************************************************************************/
sg_save_settings(struct savedata * saving)2783 static void sg_save_settings(struct savedata *saving)
2784 {
2785 enum map_generator real_generator = game.map.server.generator;
2786
2787 /* Check status and return if not OK (sg_success != TRUE). */
2788 sg_check_ret();
2789
2790 if (saving->scenario) {
2791 game.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2792 }
2793
2794 settings_game_save(saving->file, "settings");
2795 /* Restore real map generator. */
2796 game.map.server.generator = real_generator;
2797
2798 /* Add all compatibility settings here. */
2799 }
2800
2801 /* =======================================================================
2802 * Load / save the main map.
2803 * ======================================================================= */
2804
2805 /****************************************************************************
2806 Load '[map'].
2807 ****************************************************************************/
sg_load_map(struct loaddata * loading)2808 static void sg_load_map(struct loaddata *loading)
2809 {
2810 /* Check status and return if not OK (sg_success != TRUE). */
2811 sg_check_ret();
2812
2813 /* This defaults to TRUE even if map has not been generated. Also,
2814 * old versions have also explicitly saved TRUE even in pre-game.
2815 * We rely on that
2816 * 1) scenario maps have it explicity right.
2817 * 2) when map is actually generated, it re-initialize this to FALSE. */
2818 game.map.server.have_huts
2819 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2820
2821 if (S_S_INITIAL == loading->server_state
2822 && MAPGEN_SCENARIO == game.map.server.generator) {
2823 /* Generator MAPGEN_SCENARIO is used;
2824 * this map was done with the map editor. */
2825
2826 /* Load tiles. */
2827 sg_load_map_tiles(loading);
2828 sg_load_map_startpos(loading);
2829
2830 if (loading->version >= 30) {
2831 /* 2.6.0 or newer */
2832 sg_load_map_tiles_extras(loading);
2833 } else {
2834 sg_load_map_tiles_bases(loading);
2835 if (loading->version >= 20) {
2836 /* 2.5.0 or newer */
2837 sg_load_map_tiles_roads(loading);
2838 }
2839 if (has_capability("specials", loading->secfile_options)) {
2840 /* Load specials. */
2841 sg_load_map_tiles_specials(loading, FALSE);
2842 }
2843 }
2844
2845 /* have_resources TRUE only if set so by sg_load_map_tiles_resources() */
2846 game.scenario.have_resources = FALSE;
2847 if (has_capability("specials", loading->secfile_options)) {
2848 /* Load resources. */
2849 sg_load_map_tiles_resources(loading);
2850 } else if (has_capability("riversoverlay", loading->secfile_options)) {
2851 /* Load only rivers overlay. */
2852 sg_load_map_tiles_specials(loading, TRUE);
2853 }
2854
2855 /* Nothing more needed for a scenario. */
2856 return;
2857 }
2858
2859 if (S_S_INITIAL == loading->server_state) {
2860 /* Nothing more to do if it is not a scenario but in initial state. */
2861 return;
2862 }
2863
2864 sg_load_map_tiles(loading);
2865 sg_load_map_startpos(loading);
2866 if (loading->version >= 30) {
2867 /* 2.6.0 or newer */
2868 sg_load_map_tiles_extras(loading);
2869 } else {
2870 sg_load_map_tiles_bases(loading);
2871 if (loading->version >= 20) {
2872 /* 2.5.0 or newer */
2873 sg_load_map_tiles_roads(loading);
2874 }
2875 sg_load_map_tiles_specials(loading, FALSE);
2876 }
2877 sg_load_map_tiles_resources(loading);
2878 sg_load_map_known(loading);
2879 sg_load_map_owner(loading);
2880 sg_load_map_worked(loading);
2881 }
2882
2883 /****************************************************************************
2884 Save 'map'.
2885 ****************************************************************************/
sg_save_map(struct savedata * saving)2886 static void sg_save_map(struct savedata *saving)
2887 {
2888 /* Check status and return if not OK (sg_success != TRUE). */
2889 sg_check_ret();
2890
2891 if (map_is_empty()) {
2892 /* No map. */
2893 return;
2894 }
2895
2896 if (saving->scenario) {
2897 secfile_insert_bool(saving->file, game.map.server.have_huts, "map.have_huts");
2898 } else {
2899 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2900 }
2901
2902 /* For debugging purposes only.
2903 * Do not save it if it's 0 (not known);
2904 * this confuses people reading this 'document' less than
2905 * saving 0. */
2906 if (game.map.server.seed) {
2907 secfile_insert_int(saving->file, game.map.server.seed,
2908 "map.random_seed");
2909 }
2910
2911 sg_save_map_tiles(saving);
2912 sg_save_map_startpos(saving);
2913 sg_save_map_tiles_extras(saving);
2914 if (!saving->scenario || game.scenario.have_resources) {
2915 sg_save_savefile_options(saving, " specials");
2916 sg_save_map_tiles_resources(saving);
2917 }
2918
2919 sg_save_map_owner(saving);
2920 sg_save_map_worked(saving);
2921 sg_save_map_known(saving);
2922 }
2923
2924 /****************************************************************************
2925 Load tiles of the map.
2926 ****************************************************************************/
sg_load_map_tiles(struct loaddata * loading)2927 static void sg_load_map_tiles(struct loaddata *loading)
2928 {
2929 /* Check status and return if not OK (sg_success != TRUE). */
2930 sg_check_ret();
2931
2932 /* Initialize the map for the current topology. 'map.xsize' and
2933 * 'map.ysize' must be set. */
2934 map_init_topology();
2935
2936 /* Allocate map. */
2937 map_allocate();
2938
2939 /* get the terrain type */
2940 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2941 "map.t%04d");
2942 assign_continent_numbers();
2943
2944 /* Check for special tile sprites. */
2945 whole_map_iterate(ptile) {
2946 const char *spec_sprite;
2947 const char *label;
2948 int nat_x, nat_y;
2949
2950 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
2951 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2952 nat_x, nat_y);
2953 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2954 nat_x, nat_y);
2955 if (NULL != ptile->spec_sprite) {
2956 ptile->spec_sprite = fc_strdup(spec_sprite);
2957 }
2958 if (label != NULL) {
2959 tile_set_label(ptile, label);
2960 }
2961 } whole_map_iterate_end;
2962 }
2963
2964 /****************************************************************************
2965 Save all map tiles
2966 ****************************************************************************/
sg_save_map_tiles(struct savedata * saving)2967 static void sg_save_map_tiles(struct savedata *saving)
2968 {
2969 /* Check status and return if not OK (sg_success != TRUE). */
2970 sg_check_ret();
2971
2972 /* Save the terrain type. */
2973 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2974 "map.t%04d");
2975
2976 /* Save special tile sprites. */
2977 whole_map_iterate(ptile) {
2978 int nat_x, nat_y;
2979
2980 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
2981 if (ptile->spec_sprite) {
2982 secfile_insert_str(saving->file, ptile->spec_sprite,
2983 "map.spec_sprite_%d_%d", nat_x, nat_y);
2984 }
2985 if (ptile->label != NULL) {
2986 secfile_insert_str(saving->file, ptile->label,
2987 "map.label_%d_%d", nat_x, nat_y);
2988 }
2989 } whole_map_iterate_end;
2990 }
2991
2992 /****************************************************************************
2993 Load extras to map
2994 ****************************************************************************/
sg_load_map_tiles_extras(struct loaddata * loading)2995 static void sg_load_map_tiles_extras(struct loaddata *loading)
2996 {
2997 /* Check status and return if not OK (sg_success != TRUE). */
2998 sg_check_ret();
2999
3000 /* Load extras. */
3001 halfbyte_iterate_extras(j, loading->extra.size) {
3002 LOAD_MAP_CHAR(ch, ptile, sg_extras_set(&ptile->extras, ch, loading->extra.order + 4 * j),
3003 loading->file, "map.e%02d_%04d", j);
3004 } halfbyte_iterate_extras_end;
3005 }
3006
3007 /****************************************************************************
3008 Save information about extras on map
3009 ****************************************************************************/
sg_save_map_tiles_extras(struct savedata * saving)3010 static void sg_save_map_tiles_extras(struct savedata *saving)
3011 {
3012 /* Check status and return if not OK (sg_success != TRUE). */
3013 sg_check_ret();
3014
3015 /* Save extras. */
3016 halfbyte_iterate_extras(j, game.control.num_extra_types) {
3017 int mod[4];
3018 int l;
3019
3020 for (l = 0; l < 4; l++) {
3021 if (4 * j + 1 > game.control.num_extra_types) {
3022 mod[l] = -1;
3023 } else {
3024 mod[l] = 4 * j + l;
3025 }
3026 }
3027 SAVE_MAP_CHAR(ptile, sg_extras_get(ptile->extras, mod),
3028 saving->file, "map.e%02d_%04d", j);
3029 } halfbyte_iterate_extras_end;
3030 }
3031
3032 /****************************************************************************
3033 Load bases to map
3034 ****************************************************************************/
sg_load_map_tiles_bases(struct loaddata * loading)3035 static void sg_load_map_tiles_bases(struct loaddata *loading)
3036 {
3037 /* Check status and return if not OK (sg_success != TRUE). */
3038 sg_check_ret();
3039
3040 /* Load bases. */
3041 halfbyte_iterate_bases(j, loading->base.size) {
3042 LOAD_MAP_CHAR(ch, ptile, sg_bases_set(&ptile->extras, ch,
3043 loading->base.order + 4 * j),
3044 loading->file, "map.b%02d_%04d", j);
3045 } halfbyte_iterate_bases_end;
3046 }
3047
3048 /****************************************************************************
3049 Load roads to map
3050 ****************************************************************************/
sg_load_map_tiles_roads(struct loaddata * loading)3051 static void sg_load_map_tiles_roads(struct loaddata *loading)
3052 {
3053 /* Check status and return if not OK (sg_success != TRUE). */
3054 sg_check_ret();
3055
3056 /* Load roads. */
3057 halfbyte_iterate_roads(j, loading->road.size) {
3058 LOAD_MAP_CHAR(ch, ptile, sg_roads_set(&ptile->extras, ch,
3059 loading->road.order + 4 * j),
3060 loading->file, "map.r%02d_%04d", j);
3061 } halfbyte_iterate_roads_end;
3062 }
3063
3064 /****************************************************************************
3065 Load information about specials on map
3066 ****************************************************************************/
sg_load_map_tiles_specials(struct loaddata * loading,bool rivers_overlay)3067 static void sg_load_map_tiles_specials(struct loaddata *loading,
3068 bool rivers_overlay)
3069 {
3070 /* Check status and return if not OK (sg_success != TRUE). */
3071 sg_check_ret();
3072
3073 /* If 'rivers_overlay' is set to TRUE, load only the rivers overlay map
3074 * from the savegame file.
3075 *
3076 * A scenario may define the terrain of the map but not list the specials
3077 * on it (thus allowing users to control the placement of specials).
3078 * However rivers are a special case and must be included in the map along
3079 * with the scenario. Thus in those cases this function should be called
3080 * to load the river information separate from any other special data.
3081 *
3082 * This does not need to be called from map_load(), because map_load()
3083 * loads the rivers overlay along with the rest of the specials. Call this
3084 * only if you've already called map_load_tiles(), and want to load only
3085 * the rivers overlay but no other specials. Scenarios that encode things
3086 * this way should have the "riversoverlay" capability. */
3087 halfbyte_iterate_special(j, loading->special.size) {
3088 LOAD_MAP_CHAR(ch, ptile, sg_special_set(ptile, &ptile->extras, ch,
3089 loading->special.order + 4 * j,
3090 rivers_overlay),
3091 loading->file, "map.spe%02d_%04d", j);
3092 } halfbyte_iterate_special_end;
3093 }
3094
3095 /****************************************************************************
3096 Load information about resources on map.
3097 ****************************************************************************/
sg_load_map_tiles_resources(struct loaddata * loading)3098 static void sg_load_map_tiles_resources(struct loaddata *loading)
3099 {
3100 /* Check status and return if not OK (sg_success != TRUE). */
3101 sg_check_ret();
3102
3103 LOAD_MAP_CHAR(ch, ptile, ptile->resource = char2resource(ch),
3104 loading->file, "map.res%04d");
3105
3106 /* After the resources are loaded, indicate those currently valid. */
3107 whole_map_iterate(ptile) {
3108 if (NULL == ptile->resource || NULL == ptile->terrain) {
3109 continue;
3110 }
3111
3112 if (terrain_has_resource(ptile->terrain, ptile->resource)) {
3113 /* cannot use set_special() for internal values */
3114 ptile->resource_valid = TRUE;
3115 }
3116 } whole_map_iterate_end;
3117
3118 game.map.server.have_resources = TRUE;
3119 game.scenario.have_resources = TRUE;
3120 }
3121
3122 /****************************************************************************
3123 Save information about resources on map.
3124 ****************************************************************************/
sg_save_map_tiles_resources(struct savedata * saving)3125 static void sg_save_map_tiles_resources(struct savedata *saving)
3126 {
3127 /* Check status and return if not OK (sg_success != TRUE). */
3128 sg_check_ret();
3129
3130 SAVE_MAP_CHAR(ptile, resource2char(ptile->resource), saving->file,
3131 "map.res%04d");
3132 }
3133
3134 /****************************************************************************
3135 Load starting positions for the players from a savegame file. There should
3136 be at least enough for every player.
3137 ****************************************************************************/
sg_load_map_startpos(struct loaddata * loading)3138 static void sg_load_map_startpos(struct loaddata *loading)
3139 {
3140 struct nation_type *pnation;
3141 struct startpos *psp;
3142 struct tile *ptile;
3143 const char SEPARATOR = '#';
3144 const char *nation_names;
3145 int nat_x, nat_y;
3146 bool exclude;
3147 int i, startpos_count;
3148
3149 /* Check status and return if not OK (sg_success != TRUE). */
3150 sg_check_ret();
3151
3152 startpos_count
3153 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3154
3155 if (0 == startpos_count) {
3156 /* Nothing to do. */
3157 return;
3158 }
3159
3160 for (i = 0; i < startpos_count; i++) {
3161 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3162 || !secfile_lookup_int(loading->file, &nat_y,
3163 "map.startpos%d.y", i)) {
3164 log_sg("Warning: Undefined coordinates for startpos %d", i);
3165 continue;
3166 }
3167
3168 ptile = native_pos_to_tile(nat_x, nat_y);
3169 if (NULL == ptile) {
3170 log_error("Start position native coordinates (%d, %d) do not exist "
3171 "in this map. Skipping...", nat_x, nat_y);
3172 continue;
3173 }
3174
3175 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3176 "map.startpos%d.exclude", i);
3177
3178 psp = map_startpos_new(ptile);
3179
3180 nation_names = secfile_lookup_str(loading->file,
3181 "map.startpos%d.nations", i);
3182 if (NULL != nation_names && '\0' != nation_names[0]) {
3183 const size_t size = strlen(nation_names) + 1;
3184 char buf[size], *start, *end;
3185
3186 memcpy(buf, nation_names, size);
3187 for (start = buf - 1; NULL != start; start = end) {
3188 start++;
3189 if ((end = strchr(start, SEPARATOR))) {
3190 *end = '\0';
3191 }
3192
3193 pnation = nation_by_rule_name(start);
3194 if (NO_NATION_SELECTED != pnation) {
3195 if (exclude) {
3196 startpos_disallow(psp, pnation);
3197 } else {
3198 startpos_allow(psp, pnation);
3199 }
3200 } else {
3201 log_verbose("Missing nation \"%s\".", start);
3202 }
3203 }
3204 }
3205 }
3206
3207 if (0 < map_startpos_count()
3208 && loading->server_state == S_S_INITIAL
3209 && map_startpos_count() < game.server.max_players) {
3210 log_verbose("Number of starts (%d) are lower than rules.max_players "
3211 "(%d), lowering rules.max_players.",
3212 map_startpos_count(), game.server.max_players);
3213 game.server.max_players = map_startpos_count();
3214 }
3215
3216 /* Re-initialize nation availability in light of start positions.
3217 * This has to be after loading [scenario] and [map].startpos and
3218 * before we seek nations for players. */
3219 update_nations_with_startpos();
3220 }
3221
3222 /****************************************************************************
3223 Save the map start positions.
3224 ****************************************************************************/
sg_save_map_startpos(struct savedata * saving)3225 static void sg_save_map_startpos(struct savedata *saving)
3226 {
3227 struct tile *ptile;
3228 const char SEPARATOR = '#';
3229 int i = 0;
3230
3231 /* Check status and return if not OK (sg_success != TRUE). */
3232 sg_check_ret();
3233
3234 if (!game.server.save_options.save_starts) {
3235 return;
3236 }
3237
3238 secfile_insert_int(saving->file, map_startpos_count(),
3239 "map.startpos_count");
3240
3241 map_startpos_iterate(psp) {
3242 int nat_x, nat_y;
3243
3244 ptile = startpos_tile(psp);
3245
3246 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
3247 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3248 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3249
3250 secfile_insert_bool(saving->file, startpos_is_excluding(psp),
3251 "map.startpos%d.exclude", i);
3252 if (startpos_allows_all(psp)) {
3253 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3254 } else {
3255 const struct nation_hash *nations = startpos_raw_nations(psp);
3256 char nation_names[MAX_LEN_NAME * nation_hash_size(nations)];
3257
3258 nation_names[0] = '\0';
3259 nation_hash_iterate(nations, pnation) {
3260 if ('\0' == nation_names[0]) {
3261 fc_strlcpy(nation_names, nation_rule_name(pnation),
3262 sizeof(nation_names));
3263 } else {
3264 cat_snprintf(nation_names, sizeof(nation_names),
3265 "%c%s", SEPARATOR, nation_rule_name(pnation));
3266 }
3267 } nation_hash_iterate_end;
3268 secfile_insert_str(saving->file, nation_names,
3269 "map.startpos%d.nations", i);
3270 }
3271 i++;
3272 } map_startpos_iterate_end;
3273
3274 fc_assert(map_startpos_count() == i);
3275 }
3276
3277 /****************************************************************************
3278 Load tile owner information
3279 ****************************************************************************/
sg_load_map_owner(struct loaddata * loading)3280 static void sg_load_map_owner(struct loaddata *loading)
3281 {
3282 int x, y;
3283 struct player *owner = NULL;
3284 struct tile *claimer = NULL;
3285 struct player *eowner = NULL;
3286
3287 /* Check status and return if not OK (sg_success != TRUE). */
3288 sg_check_ret();
3289
3290 if (game.info.is_new_game) {
3291 /* No owner/source information for a new game / scenario. */
3292 return;
3293 }
3294
3295 /* Owner and ownership source are stored as plain numbers */
3296 for (y = 0; y < game.map.ysize; y++) {
3297 const char *buffer1 = secfile_lookup_str(loading->file,
3298 "map.owner%04d", y);
3299 const char *buffer2 = secfile_lookup_str(loading->file,
3300 "map.source%04d", y);
3301 const char *buffer3 = secfile_lookup_str(loading->file,
3302 "map.eowner%04d", y);
3303 const char *ptr1 = buffer1;
3304 const char *ptr2 = buffer2;
3305 const char *ptr3 = buffer3;
3306
3307 sg_failure_ret(buffer1 != NULL, "%s", secfile_error());
3308 sg_failure_ret(buffer2 != NULL, "%s", secfile_error());
3309 if (loading->version >= 30) {
3310 sg_failure_ret(buffer3 != NULL, "%s", secfile_error());
3311 }
3312
3313 for (x = 0; x < game.map.xsize; x++) {
3314 char token1[TOKEN_SIZE];
3315 char token2[TOKEN_SIZE];
3316 char token3[TOKEN_SIZE];
3317 int number;
3318 struct tile *ptile = native_pos_to_tile(x, y);
3319
3320 scanin(&ptr1, ",", token1, sizeof(token1));
3321 sg_failure_ret(token1[0] != '\0',
3322 "Map size not correct (map.owner%d).", y);
3323 if (strcmp(token1, "-") == 0) {
3324 owner = NULL;
3325 } else {
3326 sg_failure_ret(str_to_int(token1, &number),
3327 "Got map owner %s in (%d, %d).", token1, x, y);
3328 owner = player_by_number(number);
3329 }
3330
3331 scanin(&ptr2, ",", token2, sizeof(token2));
3332 sg_failure_ret(token2[0] != '\0',
3333 "Map size not correct (map.source%d).", y);
3334 if (strcmp(token2, "-") == 0) {
3335 claimer = NULL;
3336 } else {
3337 sg_failure_ret(str_to_int(token2, &number),
3338 "Got map source %s in (%d, %d).", token2, x, y);
3339 claimer = index_to_tile(number);
3340 }
3341
3342 if (loading->version >= 30) {
3343 scanin(&ptr3, ",", token3, sizeof(token3));
3344 sg_failure_ret(token3[0] != '\0',
3345 "Map size not correct (map.eowner%d).", y);
3346 if (strcmp(token3, "-") == 0) {
3347 eowner = NULL;
3348 } else {
3349 sg_failure_ret(str_to_int(token3, &number),
3350 "Got base owner %s in (%d, %d).", token3, x, y);
3351 eowner = player_by_number(number);
3352 }
3353 } else {
3354 eowner = owner;
3355 }
3356
3357 map_claim_ownership(ptile, owner, claimer, FALSE);
3358 tile_claim_bases(ptile, eowner);
3359 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3360 }
3361 }
3362 }
3363
3364 /****************************************************************************
3365 Save tile owner information
3366 ****************************************************************************/
sg_save_map_owner(struct savedata * saving)3367 static void sg_save_map_owner(struct savedata *saving)
3368 {
3369 int x, y;
3370
3371 /* Check status and return if not OK (sg_success != TRUE). */
3372 sg_check_ret();
3373
3374 if (saving->scenario && !saving->save_players) {
3375 /* Nothing to do for a scenario without saved players. */
3376 return;
3377 }
3378
3379 /* Store owner and ownership source as plain numbers. */
3380 for (y = 0; y < game.map.ysize; y++) {
3381 char line[game.map.xsize * TOKEN_SIZE];
3382
3383 line[0] = '\0';
3384 for (x = 0; x < game.map.xsize; x++) {
3385 char token[TOKEN_SIZE];
3386 struct tile *ptile = native_pos_to_tile(x, y);
3387
3388 if (!saving->save_players || tile_owner(ptile) == NULL) {
3389 strcpy(token, "-");
3390 } else {
3391 fc_snprintf(token, sizeof(token), "%d",
3392 player_number(tile_owner(ptile)));
3393 }
3394 strcat(line, token);
3395 if (x + 1 < game.map.xsize) {
3396 strcat(line, ",");
3397 }
3398 }
3399 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3400 }
3401
3402 for (y = 0; y < game.map.ysize; y++) {
3403 char line[game.map.xsize * TOKEN_SIZE];
3404
3405 line[0] = '\0';
3406 for (x = 0; x < game.map.xsize; x++) {
3407 char token[TOKEN_SIZE];
3408 struct tile *ptile = native_pos_to_tile(x, y);
3409
3410 if (ptile->claimer == NULL) {
3411 strcpy(token, "-");
3412 } else {
3413 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3414 }
3415 strcat(line, token);
3416 if (x + 1 < game.map.xsize) {
3417 strcat(line, ",");
3418 }
3419 }
3420 secfile_insert_str(saving->file, line, "map.source%04d", y);
3421 }
3422
3423 for (y = 0; y < game.map.ysize; y++) {
3424 char line[game.map.xsize * TOKEN_SIZE];
3425
3426 line[0] = '\0';
3427 for (x = 0; x < game.map.xsize; x++) {
3428 char token[TOKEN_SIZE];
3429 struct tile *ptile = native_pos_to_tile(x, y);
3430
3431 if (!saving->save_players || extra_owner(ptile) == NULL) {
3432 strcpy(token, "-");
3433 } else {
3434 fc_snprintf(token, sizeof(token), "%d",
3435 player_number(extra_owner(ptile)));
3436 }
3437 strcat(line, token);
3438 if (x + 1 < game.map.xsize) {
3439 strcat(line, ",");
3440 }
3441 }
3442 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3443 }
3444 }
3445
3446 /****************************************************************************
3447 Load worked tiles information
3448 ****************************************************************************/
sg_load_map_worked(struct loaddata * loading)3449 static void sg_load_map_worked(struct loaddata *loading)
3450 {
3451 int x, y;
3452
3453 /* Check status and return if not OK (sg_success != TRUE). */
3454 sg_check_ret();
3455
3456 sg_failure_ret(loading->worked_tiles == NULL,
3457 "City worked map not loaded!");
3458
3459 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3460 sizeof(*loading->worked_tiles));
3461
3462 for (y = 0; y < game.map.ysize; y++) {
3463 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3464 y);
3465 const char *ptr = buffer;
3466
3467 sg_failure_ret(NULL != buffer,
3468 "Savegame corrupt - map line %d not found.", y);
3469 for (x = 0; x < game.map.xsize; x++) {
3470 char token[TOKEN_SIZE];
3471 int number;
3472 struct tile *ptile = native_pos_to_tile(x, y);
3473
3474 scanin(&ptr, ",", token, sizeof(token));
3475 sg_failure_ret('\0' != token[0],
3476 "Savegame corrupt - map size not correct.");
3477 if (strcmp(token, "-") == 0) {
3478 number = -1;
3479 } else {
3480 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3481 "Savegame corrupt - got tile worked by city "
3482 "id=%s in (%d, %d).", token, x, y);
3483 }
3484
3485 loading->worked_tiles[ptile->index] = number;
3486 }
3487 }
3488 }
3489
3490 /****************************************************************************
3491 Save worked tiles information
3492 ****************************************************************************/
sg_save_map_worked(struct savedata * saving)3493 static void sg_save_map_worked(struct savedata *saving)
3494 {
3495 int x, y;
3496
3497 /* Check status and return if not OK (sg_success != TRUE). */
3498 sg_check_ret();
3499
3500 if (saving->scenario && !saving->save_players) {
3501 /* Nothing to do for a scenario without saved players. */
3502 return;
3503 }
3504
3505 /* additionally save the tiles worked by the cities */
3506 for (y = 0; y < game.map.ysize; y++) {
3507 char line[game.map.xsize * TOKEN_SIZE];
3508
3509 line[0] = '\0';
3510 for (x = 0; x < game.map.xsize; x++) {
3511 char token[TOKEN_SIZE];
3512 struct tile *ptile = native_pos_to_tile(x, y);
3513 struct city *pcity = tile_worked(ptile);
3514
3515 if (pcity == NULL) {
3516 strcpy(token, "-");
3517 } else {
3518 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3519 }
3520 strcat(line, token);
3521 if (x < game.map.xsize) {
3522 strcat(line, ",");
3523 }
3524 }
3525 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3526 }
3527 }
3528
3529 /****************************************************************************
3530 Load tile known status
3531 ****************************************************************************/
sg_load_map_known(struct loaddata * loading)3532 static void sg_load_map_known(struct loaddata *loading)
3533 {
3534 /* Check status and return if not OK (sg_success != TRUE). */
3535 sg_check_ret();
3536
3537 players_iterate(pplayer) {
3538 /* Allocate player private map here; it is needed in different modules
3539 * besides this one ((i.e. sg_load_player_*()). */
3540 player_map_init(pplayer);
3541 } players_iterate_end;
3542
3543 if (secfile_lookup_bool_default(loading->file, TRUE,
3544 "game.save_known")) {
3545 int lines = player_slot_max_used_number()/32 + 1, j, p, l, i;
3546 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3547
3548 for (l = 0; l < lines; l++) {
3549 for (j = 0; j < 8; j++) {
3550 for (i = 0; i < 4; i++) {
3551 /* Only bother trying to load the map for this halfbyte if at least
3552 * one of the corresponding player slots is in use. */
3553 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3554 LOAD_MAP_CHAR(ch, ptile,
3555 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3556 |= ascii_hex2bin(ch, j),
3557 loading->file, "map.k%02d_%04d", l * 8 + j);
3558 break;
3559 }
3560 }
3561 }
3562 }
3563
3564 players_iterate(pplayer) {
3565 dbv_clr_all(&pplayer->tile_known);
3566 } players_iterate_end;
3567
3568 /* HACK: we read the known data from hex into 32-bit integers, and
3569 * now we convert it to the known tile data of each player. */
3570 whole_map_iterate(ptile) {
3571 players_iterate(pplayer) {
3572 p = player_index(pplayer);
3573 l = player_index(pplayer) / 32;
3574
3575 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3576 map_set_known(ptile, pplayer);
3577 }
3578 } players_iterate_end;
3579 } whole_map_iterate_end;
3580
3581 FC_FREE(known);
3582 }
3583 }
3584
3585 /****************************************************************************
3586 Save tile known status for whole map and all players
3587 ****************************************************************************/
sg_save_map_known(struct savedata * saving)3588 static void sg_save_map_known(struct savedata *saving)
3589 {
3590 /* Check status and return if not OK (sg_success != TRUE). */
3591 sg_check_ret();
3592
3593 if (!saving->save_players) {
3594 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3595 return;
3596 } else {
3597 int lines = player_slot_max_used_number()/32 + 1;
3598
3599 secfile_insert_bool(saving->file, game.server.save_options.save_known,
3600 "game.save_known");
3601 if (game.server.save_options.save_known) {
3602 int j, p, l, i;
3603 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3604
3605 /* HACK: we convert the data into a 32-bit integer, and then save it as
3606 * hex. */
3607
3608 whole_map_iterate(ptile) {
3609 players_iterate(pplayer) {
3610 if (map_is_known(ptile, pplayer)) {
3611 p = player_index(pplayer);
3612 l = p / 32;
3613 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3614 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3615 }
3616 } players_iterate_end;
3617 } whole_map_iterate_end;
3618
3619 for (l = 0; l < lines; l++) {
3620 for (j = 0; j < 8; j++) {
3621 for (i = 0; i < 4; i++) {
3622 /* Only bother saving the map for this halfbyte if at least one
3623 * of the corresponding player slots is in use */
3624 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3625 /* put 4-bit segments of the 32-bit "known" field */
3626 SAVE_MAP_CHAR(ptile, bin2ascii_hex(known[l * MAP_INDEX_SIZE
3627 + tile_index(ptile)], j),
3628 saving->file, "map.k%02d_%04d", l * 8 + j);
3629 break;
3630 }
3631 }
3632 }
3633 }
3634
3635 FC_FREE(known);
3636 }
3637 }
3638 }
3639
3640 /* =======================================================================
3641 * Load / save player data.
3642 *
3643 * This is splitted into two parts as some data can only be loaded if the
3644 * number of players is known and the corresponding player slots are
3645 * defined.
3646 * ======================================================================= */
3647
3648 /****************************************************************************
3649 Load '[player]' (basic data).
3650 ****************************************************************************/
sg_load_players_basic(struct loaddata * loading)3651 static void sg_load_players_basic(struct loaddata *loading)
3652 {
3653 int i, k, nplayers;
3654 const char *string;
3655 bool shuffle_loaded = TRUE;
3656
3657 /* Check status and return if not OK (sg_success != TRUE). */
3658 sg_check_ret();
3659
3660 if (S_S_INITIAL == loading->server_state
3661 || game.info.is_new_game) {
3662 /* Nothing more to do. */
3663 return;
3664 }
3665
3666 /* Load destroyed wonders: */
3667 string = secfile_lookup_str(loading->file,
3668 "players.destroyed_wonders");
3669 sg_failure_ret(string != NULL, "%s", secfile_error());
3670 sg_failure_ret(strlen(string) == loading->improvement.size,
3671 "Invalid length for 'players.destroyed_wonders' "
3672 "(%lu ~= %lu)", (unsigned long) strlen(string),
3673 (unsigned long) loading->improvement.size);
3674 for (k = 0; k < loading->improvement.size; k++) {
3675 sg_failure_ret(string[k] == '1' || string[k] == '0',
3676 "Undefined value '%c' within "
3677 "'players.destroyed_wonders'.", string[k]);
3678
3679 if (string[k] == '1') {
3680 struct impr_type *pimprove =
3681 improvement_by_rule_name(loading->improvement.order[k]);
3682 if (pimprove) {
3683 game.info.great_wonder_owners[improvement_index(pimprove)]
3684 = WONDER_DESTROYED;
3685 }
3686 }
3687 }
3688
3689 server.identity_number
3690 = secfile_lookup_int_default(loading->file, server.identity_number,
3691 "players.identity_number_used");
3692
3693 /* First remove all defined players. */
3694 players_iterate(pplayer) {
3695 server_remove_player(pplayer);
3696 } players_iterate_end;
3697
3698 /* Now, load the players from the savefile. */
3699 player_slots_iterate(pslot) {
3700 struct player *pplayer;
3701 struct rgbcolor *prgbcolor = NULL;
3702 int pslot_id = player_slot_index(pslot);
3703
3704 if (NULL == secfile_section_lookup(loading->file, "player%d",
3705 pslot_id)) {
3706 continue;
3707 }
3708
3709 /* Get player AI type. */
3710 string = secfile_lookup_str(loading->file, "player%d.ai_type",
3711 player_slot_index(pslot));
3712 sg_failure_ret(string != NULL, "%s", secfile_error());
3713
3714 /* Get player color */
3715 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3716 pslot_id)) {
3717 if (loading->version >= 10 && game_was_started()) {
3718 /* 2.4.0 or later savegame. This is not an error in 2.3 savefiles,
3719 * as they predate the introduction of configurable player colors. */
3720 log_sg("Game has started, yet player %d has no color defined.",
3721 pslot_id);
3722 /* This will be fixed up later */
3723 } else {
3724 log_verbose("No color defined for player %d.", pslot_id);
3725 /* Colors will be assigned on game start, or at end of savefile
3726 * loading if game has already started */
3727 }
3728 }
3729
3730 /* Create player. */
3731 pplayer = server_create_player(player_slot_index(pslot), string,
3732 prgbcolor, game.scenario.allow_ai_type_fallback);
3733 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", string);
3734
3735 server_player_init(pplayer, FALSE, FALSE);
3736
3737 /* Free the color definition. */
3738 rgbcolor_destroy(prgbcolor);
3739
3740 /* Multipliers (policies) */
3741
3742 /* First initialise player values with ruleset defaults; this will
3743 * cover any in the ruleset not known when the savefile was created. */
3744 multipliers_iterate(pmul) {
3745 pplayer->multipliers[multiplier_index(pmul)]
3746 = pplayer->multipliers_target[multiplier_index(pmul)] = pmul->def;
3747 } multipliers_iterate_end;
3748
3749 /* Now override with any values from the savefile. */
3750 for (k = 0; k < loading->multiplier.size; k++) {
3751 const struct multiplier *pmul = loading->multiplier.order[k];
3752
3753 if (pmul) {
3754 Multiplier_type_id idx = multiplier_index(pmul);
3755 int val =
3756 secfile_lookup_int_default(loading->file, pmul->def,
3757 "player%d.multiplier%d.val",
3758 player_slot_index(pslot), k);
3759 int rval = (((CLIP(pmul->start, val, pmul->stop)
3760 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3761
3762 if (rval != val) {
3763 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3764 "was %d, clamped to %d", pslot_id,
3765 multiplier_rule_name(pmul), val, rval);
3766 }
3767 pplayer->multipliers[idx] = rval;
3768
3769 val =
3770 secfile_lookup_int_default(loading->file,
3771 pplayer->multipliers[idx],
3772 "player%d.multiplier%d.target",
3773 player_slot_index(pslot), k);
3774 rval = (((CLIP(pmul->start, val, pmul->stop)
3775 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3776
3777 if (rval != val) {
3778 log_verbose("Player %d had illegal value for multiplier_target "
3779 "\"%s\": was %d, clamped to %d", pslot_id,
3780 multiplier_rule_name(pmul), val, rval);
3781 }
3782 pplayer->multipliers_target[idx] = rval;
3783 } /* else silently discard multiplier not in current ruleset */
3784 }
3785 } player_slots_iterate_end;
3786
3787 /* check number of players */
3788 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3789 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3790 "(%d) from the loaded game does not match the number of "
3791 "players present (%d).", nplayers, player_count());
3792
3793 /* Load team informations. */
3794 players_iterate(pplayer) {
3795 int team;
3796 struct team_slot *tslot = NULL;
3797
3798 sg_failure_ret(secfile_lookup_int(loading->file, &team,
3799 "player%d.team_no",
3800 player_number(pplayer))
3801 && (tslot = team_slot_by_number(team)),
3802 "Invalid team definition for player %s (nb %d).",
3803 player_name(pplayer), player_number(pplayer));
3804 team_add_player(pplayer, team_new(tslot));
3805 } players_iterate_end;
3806
3807 /* Loading the shuffle list is quite complex. At the time of saving the
3808 * shuffle data is saved as
3809 * shuffled_player_<number> = player_slot_id
3810 * where number is an increasing number and player_slot_id is a number
3811 * between 0 and the maximum number of player slots. Now we have to create
3812 * a list
3813 * shuffler_players[number] = player_slot_id
3814 * where all player slot IDs are used exactly one time. The code below
3815 * handles this ... */
3816 if (secfile_lookup_int_default(loading->file, -1,
3817 "players.shuffled_player_%d", 0) >= 0) {
3818 int shuffled_players[player_slot_count()];
3819 bool shuffled_player_set[player_slot_count()];
3820
3821 player_slots_iterate(pslot) {
3822 int plrid = player_slot_index(pslot);
3823
3824 /* Array to save used numbers. */
3825 shuffled_player_set[plrid] = FALSE;
3826 /* List of all player IDs (needed for set_shuffled_players()). It is
3827 * initialised with the value -1 to indicate that no value is set. */
3828 shuffled_players[plrid] = -1;
3829 } player_slots_iterate_end;
3830
3831 /* Load shuffled player list. */
3832 for (i = 0; i < player_count(); i++){
3833 int shuffle
3834 = secfile_lookup_int_default(loading->file, -1,
3835 "players.shuffled_player_%d", i);
3836
3837 if (shuffle == -1) {
3838 log_sg("Missing player shuffle information (index %d) "
3839 "- reshuffle player list!", i);
3840 shuffle_loaded = FALSE;
3841 break;
3842 } else if (shuffled_player_set[shuffle]) {
3843 log_sg("Player shuffle %d used two times "
3844 "- reshuffle player list!", shuffle);
3845 shuffle_loaded = FALSE;
3846 break;
3847 }
3848 /* Set this ID as used. */
3849 shuffled_player_set[shuffle] = TRUE;
3850
3851 /* Save the player ID in the shuffle list. */
3852 shuffled_players[i] = shuffle;
3853 }
3854
3855 if (shuffle_loaded) {
3856 /* Insert missing numbers. */
3857 int shuffle_index = player_count();
3858 for (i = 0; i < player_slot_count(); i++){
3859 if (!shuffled_player_set[i]) {
3860 shuffled_players[shuffle_index] = i;
3861 shuffle_index++;
3862 }
3863 /* shuffle_index must not grow behind the size of shuffled_players. */
3864 sg_failure_ret(shuffle_index <= player_slot_count(),
3865 "Invalid player shuffle data!");
3866 }
3867
3868 #ifdef DEBUG
3869 log_debug("[load shuffle] player_count() = %d", player_count());
3870 player_slots_iterate(pslot) {
3871 int plrid = player_slot_index(pslot);
3872 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3873 plrid, shuffled_players[plrid], plrid,
3874 shuffled_player_set[plrid] ? "is used" : "-");
3875 } player_slots_iterate_end;
3876 #endif /* DEBUG */
3877
3878 /* Set shuffle list from savegame. */
3879 set_shuffled_players(shuffled_players);
3880 }
3881 }
3882
3883 if (!shuffle_loaded) {
3884 /* No shuffled players included or error loading them, so shuffle them
3885 * (this may include scenarios). */
3886 shuffle_players();
3887 }
3888 }
3889
3890 /****************************************************************************
3891 Load '[player]'.
3892 ****************************************************************************/
sg_load_players(struct loaddata * loading)3893 static void sg_load_players(struct loaddata *loading)
3894 {
3895 /* Check status and return if not OK (sg_success != TRUE). */
3896 sg_check_ret();
3897
3898 if (game.info.is_new_game) {
3899 /* Nothing to do. */
3900 return;
3901 }
3902
3903 players_iterate(pplayer) {
3904 sg_load_player_main(loading, pplayer);
3905 sg_load_player_cities(loading, pplayer);
3906 sg_load_player_units(loading, pplayer);
3907 sg_load_player_attributes(loading, pplayer);
3908
3909 /* Check the sucess of the functions above. */
3910 sg_check_ret();
3911
3912 /* print out some informations */
3913 if (pplayer->ai_controlled) {
3914 log_normal(_("%s has been added as %s level AI-controlled player "
3915 "(%s)."), player_name(pplayer),
3916 ai_level_translated_name(pplayer->ai_common.skill_level),
3917 ai_name(pplayer->ai));
3918 } else {
3919 log_normal(_("%s has been added as human player."),
3920 player_name(pplayer));
3921 }
3922 } players_iterate_end;
3923
3924 /* Also load the transport status of the units here. It must be a special
3925 * case as all units must be known (unit on an allied transporter). */
3926 players_iterate(pplayer) {
3927 /* Load unit transport status. */
3928 sg_load_player_units_transport(loading, pplayer);
3929 } players_iterate_end;
3930
3931 /* Savegame may contain nation assignments that are incompatible with the
3932 * current nationset -- for instance, if it predates the introduction of
3933 * nationsets. Ensure they are compatible, one way or another. */
3934 fit_nationset_to_players();
3935
3936 /* Some players may have invalid nations in the ruleset. Once all players
3937 * are loaded, pick one of the remaining nations for them. */
3938 players_iterate(pplayer) {
3939 if (pplayer->nation == NO_NATION_SELECTED) {
3940 player_set_nation(pplayer, pick_a_nation(NULL, FALSE, TRUE,
3941 NOT_A_BARBARIAN));
3942 /* TRANS: Minor error message: <Leader> ... <Poles>. */
3943 log_sg(_("%s had invalid nation; changing to %s."),
3944 player_name(pplayer), nation_plural_for_player(pplayer));
3945
3946 ai_traits_init(pplayer);
3947 }
3948 } players_iterate_end;
3949
3950 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
3951 players_iterate_alive(plr) {
3952 players_iterate_alive(aplayer) {
3953 if (pplayers_allied(plr, aplayer)) {
3954 enum dipl_reason can_ally = pplayer_can_make_treaty(plr, aplayer,
3955 DS_ALLIANCE);
3956 if (can_ally == DIPL_ALLIANCE_PROBLEM_US
3957 || can_ally == DIPL_ALLIANCE_PROBLEM_THEM) {
3958 log_sg("Illegal alliance structure detected: "
3959 "%s alliance to %s reduced to peace treaty.",
3960 nation_rule_name(nation_of_player(plr)),
3961 nation_rule_name(nation_of_player(aplayer)));
3962 player_diplstate_get(plr, aplayer)->type = DS_PEACE;
3963 player_diplstate_get(aplayer, plr)->type = DS_PEACE;
3964 }
3965 }
3966 } players_iterate_alive_end;
3967 } players_iterate_alive_end;
3968
3969 /* Update cached city illness. This can depend on trade routes,
3970 * so can't be calculated until all players have been loaded. */
3971 if (game.info.illness_on) {
3972 cities_iterate(pcity) {
3973 pcity->server.illness
3974 = city_illness_calc(pcity, NULL, NULL,
3975 &(pcity->illness_trade), NULL);
3976 } cities_iterate_end;
3977 }
3978
3979 /* Update all city information. This must come after all cities are
3980 * loaded (in player_load) but before player (dumb) cities are loaded
3981 * in player_load_vision(). */
3982 players_iterate(plr) {
3983 city_list_iterate(plr->cities, pcity) {
3984 city_refresh(pcity);
3985 sanity_check_city(pcity);
3986 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
3987 } city_list_iterate_end;
3988 } players_iterate_end;
3989
3990 /* Since the cities must be placed on the map to put them on the
3991 player map we do this afterwards */
3992 players_iterate(pplayer) {
3993 sg_load_player_vision(loading, pplayer);
3994 /* Check the sucess of the function above. */
3995 sg_check_ret();
3996 } players_iterate_end;
3997
3998 /* Check shared vision. */
3999 players_iterate(pplayer) {
4000 BV_CLR_ALL(pplayer->gives_shared_vision);
4001 BV_CLR_ALL(pplayer->server.really_gives_vision);
4002 } players_iterate_end;
4003
4004 players_iterate(pplayer) {
4005 int plr1 = player_index(pplayer);
4006
4007 players_iterate(pplayer2) {
4008 int plr2 = player_index(pplayer2);
4009 if (secfile_lookup_bool_default(loading->file, FALSE,
4010 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
4011 give_shared_vision(pplayer, pplayer2);
4012 }
4013 } players_iterate_end;
4014 } players_iterate_end;
4015
4016 initialize_globals();
4017 unit_ordering_apply();
4018
4019 /* All vision is ready; this calls city_thaw_workers_queue(). */
4020 map_calculate_borders();
4021
4022 /* Make sure everything is consistent. */
4023 players_iterate(pplayer) {
4024 unit_list_iterate(pplayer->units, punit) {
4025 if (!can_unit_continue_current_activity(punit)) {
4026 log_sg("Unit doing illegal activity in savegame!");
4027 log_sg("Activity: %s, Target: %s",
4028 unit_activity_name(punit->activity),
4029 punit->activity_target ? extra_rule_name(
4030 punit->activity_target)
4031 : "missing");
4032 punit->activity = ACTIVITY_IDLE;
4033 }
4034 } unit_list_iterate_end;
4035 } players_iterate_end;
4036
4037 cities_iterate(pcity) {
4038 city_refresh(pcity);
4039 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4040 } cities_iterate_end;
4041
4042 /* Player colors are always needed once game has started. Pre-2.4 savegames
4043 * lack them. This cannot be in compatibility conversion layer as we need
4044 * all the player data available to be able to assign best colors. */
4045 if (game_was_started()) {
4046 assign_player_colors();
4047 }
4048 }
4049
4050 /****************************************************************************
4051 Save '[player]'.
4052 ****************************************************************************/
sg_save_players(struct savedata * saving)4053 static void sg_save_players(struct savedata *saving)
4054 {
4055 /* Check status and return if not OK (sg_success != TRUE). */
4056 sg_check_ret();
4057
4058 if ((saving->scenario && !saving->save_players)
4059 || !game_was_started()) {
4060 /* Nothing to do for a scenario without saved players or a game in
4061 * INITIAL state. */
4062 return;
4063 }
4064
4065 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4066
4067 /* Save destroyed wonders as bitvector. Note that improvement order
4068 * is saved in 'savefile.improvement.order'. */
4069 {
4070 char destroyed[B_LAST+1];
4071
4072 improvement_iterate(pimprove) {
4073 if (is_great_wonder(pimprove)
4074 && great_wonder_is_destroyed(pimprove)) {
4075 destroyed[improvement_index(pimprove)] = '1';
4076 } else {
4077 destroyed[improvement_index(pimprove)] = '0';
4078 }
4079 } improvement_iterate_end;
4080 destroyed[improvement_count()] = '\0';
4081 secfile_insert_str(saving->file, destroyed,
4082 "players.destroyed_wonders");
4083 }
4084
4085 secfile_insert_int(saving->file, server.identity_number,
4086 "players.identity_number_used");
4087
4088 /* Save player order. */
4089 {
4090 int i = 0;
4091 shuffled_players_iterate(pplayer) {
4092 secfile_insert_int(saving->file, player_number(pplayer),
4093 "players.shuffled_player_%d", i);
4094 i++;
4095 } shuffled_players_iterate_end;
4096 }
4097
4098 /* Sort units. */
4099 unit_ordering_calc();
4100
4101 /* Save players. */
4102 players_iterate(pplayer) {
4103 sg_save_player_main(saving, pplayer);
4104 sg_save_player_cities(saving, pplayer);
4105 sg_save_player_units(saving, pplayer);
4106 sg_save_player_attributes(saving, pplayer);
4107 sg_save_player_vision(saving, pplayer);
4108 } players_iterate_end;
4109 }
4110
4111 /****************************************************************************
4112 Main player data loading function
4113 ****************************************************************************/
sg_load_player_main(struct loaddata * loading,struct player * plr)4114 static void sg_load_player_main(struct loaddata *loading,
4115 struct player *plr)
4116 {
4117 int i, plrno = player_number(plr);
4118 const char *string;
4119 struct government *gov;
4120 const char *level;
4121 const char *barb_str;
4122
4123 /* Check status and return if not OK (sg_success != TRUE). */
4124 sg_check_ret();
4125
4126 /* Basic player data. */
4127 string = secfile_lookup_str(loading->file, "player%d.name", plrno);
4128 sg_failure_ret(string != NULL, "%s", secfile_error());
4129 server_player_set_name(plr, string);
4130 sz_strlcpy(plr->username,
4131 secfile_lookup_str_default(loading->file, "",
4132 "player%d.username", plrno));
4133 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->unassigned_user,
4134 "player%d.unassigned_user", plrno),
4135 "%s", secfile_error());
4136 sz_strlcpy(plr->server.orig_username,
4137 secfile_lookup_str_default(loading->file, "",
4138 "player%d.orig_username",
4139 plrno));
4140 sz_strlcpy(plr->ranked_username,
4141 secfile_lookup_str_default(loading->file, "",
4142 "player%d.ranked_username",
4143 plrno));
4144 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->unassigned_ranked,
4145 "player%d.unassigned_ranked", plrno),
4146 "%s", secfile_error());
4147 string = secfile_lookup_str_default(loading->file, "",
4148 "player%d.delegation_username",
4149 plrno);
4150 /* Defaults to no delegation. */
4151 if (strlen(string)) {
4152 player_delegation_set(plr, string);
4153 }
4154
4155 /* Nation */
4156 string = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4157 player_set_nation(plr, nation_by_rule_name(string));
4158 if (plr->nation != NULL) {
4159 ai_traits_init(plr);
4160 }
4161
4162 /* Government */
4163 string = secfile_lookup_str(loading->file, "player%d.government_name",
4164 plrno);
4165 gov = government_by_rule_name(string);
4166 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4167 plrno, string);
4168 plr->government = gov;
4169
4170 /* Target government */
4171 string = secfile_lookup_str(loading->file,
4172 "player%d.target_government_name", plrno);
4173 if (string) {
4174 plr->target_government = government_by_rule_name(string);
4175 } else {
4176 plr->target_government = NULL;
4177 }
4178 plr->revolution_finishes
4179 = secfile_lookup_int_default(loading->file, -1,
4180 "player%d.revolution_finishes", plrno);
4181
4182 sg_failure_ret(secfile_lookup_bool(loading->file,
4183 &plr->server.got_first_city,
4184 "player%d.got_first_city", plrno),
4185 "%s", secfile_error());
4186
4187 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->ai_controlled,
4188 "player%d.ai.control", plrno),
4189 "%s", secfile_error());
4190
4191 /* Load diplomatic data (diplstate + embassy + vision).
4192 * Shared vision is loaded in sg_load_players(). */
4193 BV_CLR_ALL(plr->real_embassy);
4194 players_iterate(pplayer) {
4195 char buf[32];
4196 int unconverted;
4197 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4198 i = player_index(pplayer);
4199
4200 /* load diplomatic status */
4201 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4202
4203 unconverted =
4204 secfile_lookup_int_default(loading->file, -1, "%s.type", buf);
4205 if (unconverted >= 0 && unconverted < loading->ds_t.size) {
4206 /* Look up what state the unconverted number represents. */
4207 ds->type = loading->ds_t.order[unconverted];
4208 } else {
4209 log_sg("No valid diplomatic state type between players %d and %d",
4210 plrno, i);
4211
4212 ds->type = DS_WAR;
4213 }
4214
4215 unconverted =
4216 secfile_lookup_int_default(loading->file, -1, "%s.max_state", buf);
4217 if (unconverted >= 0 && unconverted < loading->ds_t.size) {
4218 /* Look up what state the unconverted number represents. */
4219 ds->max_state = loading->ds_t.order[unconverted];
4220 } else {
4221 log_sg("No valid diplomatic max_state between players %d and %d",
4222 plrno, i);
4223
4224 ds->max_state = DS_WAR;
4225 }
4226
4227 ds->first_contact_turn =
4228 secfile_lookup_int_default(loading->file, 0,
4229 "%s.first_contact_turn", buf);
4230 ds->turns_left =
4231 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4232 ds->has_reason_to_cancel =
4233 secfile_lookup_int_default(loading->file, 0,
4234 "%s.has_reason_to_cancel", buf);
4235 ds->contact_turns_left =
4236 secfile_lookup_int_default(loading->file, 0,
4237 "%s.contact_turns_left", buf);
4238
4239 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4240 buf)) {
4241 BV_SET(plr->real_embassy, i);
4242 }
4243 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4244 * must be known. */
4245 } players_iterate_end;
4246
4247 /* load ai data */
4248 players_iterate(aplayer) {
4249 char buf[32];
4250
4251 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4252 player_index(aplayer));
4253
4254 plr->ai_common.love[player_index(aplayer)] =
4255 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4256 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4257 } players_iterate_end;
4258
4259 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4260
4261 /* Some sane defaults */
4262 plr->ai_common.fuzzy = 0;
4263 plr->ai_common.expand = 100;
4264 plr->ai_common.science_cost = 100;
4265
4266
4267 level = secfile_lookup_str_default(loading->file, NULL,
4268 "player%d.ai.level", plrno);
4269 if (level != NULL) {
4270 plr->ai_common.skill_level = ai_level_by_name(level, fc_strcasecmp);
4271
4272 /* In builds where level "Experimental" is not supported, convert it to "Hard" */
4273 if (!ai_level_is_valid(plr->ai_common.skill_level)
4274 && !fc_strcasecmp(level, "Experimental")) {
4275 plr->ai_common.skill_level = AI_LEVEL_HARD;
4276 }
4277 } else {
4278 plr->ai_common.skill_level = ai_level_invalid();
4279 }
4280
4281 if (!ai_level_is_valid(plr->ai_common.skill_level)) {
4282 plr->ai_common.skill_level
4283 = ai_level_convert(secfile_lookup_int_default(loading->file,
4284 game.info.skill_level,
4285 "player%d.ai.skill_level",
4286 plrno));
4287 }
4288
4289 barb_str = secfile_lookup_str_default(loading->file, "None",
4290 "player%d.ai.barb_type", plrno);
4291 plr->ai_common.barbarian_type = barbarian_type_by_name(barb_str, fc_strcasecmp);
4292
4293 if (!barbarian_type_is_valid(plr->ai_common.barbarian_type)) {
4294 log_sg("Player%d: Invalid barbarian type \"%s\". "
4295 "Changed to \"None\".", plrno, barb_str);
4296 plr->ai_common.barbarian_type = NOT_A_BARBARIAN;
4297 }
4298
4299 if (is_barbarian(plr)) {
4300 server.nbarbarians++;
4301 }
4302
4303 if (plr->ai_controlled) {
4304 set_ai_level_directer(plr, plr->ai_common.skill_level);
4305 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4306 }
4307
4308 /* Load nation style. */
4309 {
4310 struct nation_style *style;
4311
4312 string = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4313
4314 /* Handle pre-2.6 savegames */
4315 if (string == NULL) {
4316 string = secfile_lookup_str(loading->file, "player%d.city_style_by_name",
4317 plrno);
4318 }
4319
4320 sg_failure_ret(string != NULL, "%s", secfile_error());
4321 style = style_by_rule_name(string);
4322 if (style == NULL) {
4323 style = style_by_number(0);
4324 log_sg("Player%d: unsupported city_style_name \"%s\". "
4325 "Changed to \"%s\".", plrno, string, style_rule_name(style));
4326 }
4327 plr->style = style;
4328 }
4329
4330 sg_failure_ret(secfile_lookup_int(loading->file, &plr->nturns_idle,
4331 "player%d.idle_turns", plrno),
4332 "%s", secfile_error());
4333 plr->is_male = secfile_lookup_bool_default(loading->file, TRUE,
4334 "player%d.is_male", plrno);
4335 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->is_alive,
4336 "player%d.is_alive", plrno),
4337 "%s", secfile_error());
4338 sg_failure_ret(secfile_lookup_int(loading->file, &plr->turns_alive,
4339 "player%d.turns_alive", plrno),
4340 "%s", secfile_error());
4341 sg_failure_ret(secfile_lookup_int(loading->file, &plr->last_war_action,
4342 "player%d.last_war", plrno),
4343 "%s", secfile_error());
4344 plr->phase_done = secfile_lookup_bool_default(loading->file, FALSE,
4345 "player%d.phase_done", plrno);
4346 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.gold,
4347 "player%d.gold", plrno),
4348 "%s", secfile_error());
4349 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.tax,
4350 "player%d.rates.tax", plrno),
4351 "%s", secfile_error());
4352 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.science,
4353 "player%d.rates.science", plrno),
4354 "%s", secfile_error());
4355 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.luxury,
4356 "player%d.rates.luxury", plrno),
4357 "%s", secfile_error());
4358 plr->server.bulbs_last_turn =
4359 secfile_lookup_int_default(loading->file, 0,
4360 "player%d.research.bulbs_last_turn", plrno);
4361
4362 /* Traits */
4363 if (plr->nation) {
4364 for (i = 0; i < loading->trait.size; i++) {
4365 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4366
4367 if (trait_is_valid(tr)) {
4368 int val = secfile_lookup_int_default(loading->file, -1, "player%d.trait%d.val",
4369 plrno, i);
4370
4371 if (val != -1) {
4372 plr->ai_common.traits[tr].val = val;
4373 }
4374
4375 sg_failure_ret(secfile_lookup_int(loading->file, &val,
4376 "player%d.trait%d.mod", plrno, i),
4377 "%s", secfile_error());
4378 plr->ai_common.traits[tr].mod = val;
4379 }
4380 }
4381 }
4382
4383 /* Achievements */
4384 {
4385 int count;
4386
4387 count = secfile_lookup_int_default(loading->file, -1,
4388 "player%d.achievement_count", plrno);
4389
4390 if (count > 0) {
4391 for (i = 0; i < count; i++) {
4392 const char *name;
4393 struct achievement *pach;
4394 bool first;
4395
4396 name = secfile_lookup_str(loading->file,
4397 "player%d.achievement%d.name", plrno, i);
4398 pach = achievement_by_rule_name(name);
4399
4400 sg_failure_ret(pach != NULL,
4401 "Unknown achievement \"%s\".", name);
4402
4403 sg_failure_ret(secfile_lookup_bool(loading->file, &first,
4404 "player%d.achievement%d.first",
4405 plrno, i),
4406 "achievement error: %s", secfile_error());
4407
4408 sg_failure_ret(pach->first == NULL || !first,
4409 "Multiple players listed as first to get achievement \"%s\".",
4410 name);
4411
4412 BV_SET(pach->achievers, player_index(plr));
4413
4414 if (first) {
4415 pach->first = plr;
4416 }
4417 }
4418 }
4419 }
4420
4421 /* Player score. */
4422 plr->score.happy =
4423 secfile_lookup_int_default(loading->file, 0,
4424 "score%d.happy", plrno);
4425 plr->score.content =
4426 secfile_lookup_int_default(loading->file, 0,
4427 "score%d.content", plrno);
4428 plr->score.unhappy =
4429 secfile_lookup_int_default(loading->file, 0,
4430 "score%d.unhappy", plrno);
4431 plr->score.angry =
4432 secfile_lookup_int_default(loading->file, 0,
4433 "score%d.angry", plrno);
4434
4435 /* Make sure that the score about specialists in current ruleset that
4436 * were not present at saving time are set to zero. */
4437 specialist_type_iterate(sp) {
4438 plr->score.specialists[sp] = 0;
4439 } specialist_type_iterate_end;
4440
4441 for (i = 0; i < loading->specialist.size; i++) {
4442 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4443 = secfile_lookup_int_default(loading->file, 0,
4444 "score%d.specialists%d", plrno, i);
4445 }
4446
4447 plr->score.wonders =
4448 secfile_lookup_int_default(loading->file, 0,
4449 "score%d.wonders", plrno);
4450 plr->score.techs =
4451 secfile_lookup_int_default(loading->file, 0,
4452 "score%d.techs", plrno);
4453 plr->score.techout =
4454 secfile_lookup_int_default(loading->file, 0,
4455 "score%d.techout", plrno);
4456 plr->score.landarea =
4457 secfile_lookup_int_default(loading->file, 0,
4458 "score%d.landarea", plrno);
4459 plr->score.settledarea =
4460 secfile_lookup_int_default(loading->file, 0,
4461 "score%d.settledarea", plrno);
4462 plr->score.population =
4463 secfile_lookup_int_default(loading->file, 0,
4464 "score%d.population", plrno);
4465 plr->score.cities =
4466 secfile_lookup_int_default(loading->file, 0,
4467 "score%d.cities", plrno);
4468 plr->score.units =
4469 secfile_lookup_int_default(loading->file, 0,
4470 "score%d.units", plrno);
4471 plr->score.pollution =
4472 secfile_lookup_int_default(loading->file, 0,
4473 "score%d.pollution", plrno);
4474 plr->score.literacy =
4475 secfile_lookup_int_default(loading->file, 0,
4476 "score%d.literacy", plrno);
4477 plr->score.bnp =
4478 secfile_lookup_int_default(loading->file, 0,
4479 "score%d.bnp", plrno);
4480 plr->score.mfg =
4481 secfile_lookup_int_default(loading->file, 0,
4482 "score%d.mfg", plrno);
4483 plr->score.spaceship =
4484 secfile_lookup_int_default(loading->file, 0,
4485 "score%d.spaceship", plrno);
4486 plr->score.units_built =
4487 secfile_lookup_int_default(loading->file, 0,
4488 "score%d.units_built", plrno);
4489 plr->score.units_killed =
4490 secfile_lookup_int_default(loading->file, 0,
4491 "score%d.units_killed", plrno);
4492 plr->score.units_lost =
4493 secfile_lookup_int_default(loading->file, 0,
4494 "score%d.units_lost", plrno);
4495 plr->score.culture =
4496 secfile_lookup_int_default(loading->file, 0,
4497 "score%d.culture", plrno);
4498 plr->score.game =
4499 secfile_lookup_int_default(loading->file, 0,
4500 "score%d.total", plrno);
4501
4502 /* Load space ship data. */
4503 {
4504 struct player_spaceship *ship = &plr->spaceship;
4505 char prefix[32];
4506 const char *st;
4507 int ei;
4508
4509 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4510 spaceship_init(ship);
4511 sg_failure_ret(secfile_lookup_int(loading->file,
4512 &ei,
4513 "%s.state", prefix),
4514 "%s", secfile_error());
4515 ship->state = ei;
4516
4517 if (ship->state != SSHIP_NONE) {
4518 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4519 "%s.structurals", prefix),
4520 "%s", secfile_error());
4521 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4522 "%s.components", prefix),
4523 "%s", secfile_error());
4524 sg_failure_ret(secfile_lookup_int(loading->file, &ship->modules,
4525 "%s.modules", prefix),
4526 "%s", secfile_error());
4527 sg_failure_ret(secfile_lookup_int(loading->file, &ship->fuel,
4528 "%s.fuel", prefix),
4529 "%s", secfile_error());
4530 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4531 "%s.propulsion", prefix),
4532 "%s", secfile_error());
4533 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4534 "%s.habitation", prefix),
4535 "%s", secfile_error());
4536 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4537 "%s.life_support", prefix),
4538 "%s", secfile_error());
4539 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4540 "%s.solar_panels", prefix),
4541 "%s", secfile_error());
4542
4543 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4544 sg_failure_ret(st != NULL, "%s", secfile_error())
4545 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4546 sg_failure_ret(st[i] == '1' || st[i] == '0',
4547 "Undefined value '%c' within '%s.structure'.", st[i],
4548 prefix)
4549
4550 if (!(st[i] == '0')) {
4551 BV_SET(ship->structure, i);
4552 }
4553 }
4554 if (ship->state >= SSHIP_LAUNCHED) {
4555 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4556 "%s.launch_year", prefix),
4557 "%s", secfile_error());
4558 }
4559 spaceship_calc_derived(ship);
4560 }
4561 }
4562
4563 /* Load lost wonder data. */
4564 string = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4565 /* If not present, probably an old savegame; nothing to be done */
4566 if (string) {
4567 int k;
4568 sg_failure_ret(strlen(string) == loading->improvement.size,
4569 "Invalid length for 'player%d.lost_wonders' "
4570 "(%lu ~= %lu)", plrno, (unsigned long) strlen(string),
4571 (unsigned long) loading->improvement.size);
4572 for (k = 0; k < loading->improvement.size; k++) {
4573 sg_failure_ret(string[k] == '1' || string[k] == '0',
4574 "Undefined value '%c' within "
4575 "'player%d.lost_wonders'.", plrno, string[k]);
4576
4577 if (string[k] == '1') {
4578 struct impr_type *pimprove =
4579 improvement_by_rule_name(loading->improvement.order[k]);
4580 if (pimprove) {
4581 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4582 }
4583 }
4584 }
4585 }
4586
4587 plr->history =
4588 secfile_lookup_int_default(loading->file, 0, "player%d.culture", plrno);
4589 plr->server.huts =
4590 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4591 }
4592
4593 /****************************************************************************
4594 Main player data saving function.
4595 ****************************************************************************/
sg_save_player_main(struct savedata * saving,struct player * plr)4596 static void sg_save_player_main(struct savedata *saving,
4597 struct player *plr)
4598 {
4599 int i, k, plrno = player_number(plr);
4600 struct player_spaceship *ship = &plr->spaceship;
4601
4602 /* Check status and return if not OK (sg_success != TRUE). */
4603 sg_check_ret();
4604
4605 secfile_insert_str(saving->file, ai_name(plr->ai),
4606 "player%d.ai_type", plrno);
4607 secfile_insert_str(saving->file, player_name(plr),
4608 "player%d.name", plrno);
4609 secfile_insert_str(saving->file, plr->username,
4610 "player%d.username", plrno);
4611 secfile_insert_bool(saving->file, plr->unassigned_user,
4612 "player%d.unassigned_user", plrno);
4613 if (plr->rgb != NULL) {
4614 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4615 } else {
4616 /* Colorless players are ok in pregame */
4617 if (game_was_started()) {
4618 log_sg("Game has started, yet player %d has no color defined.", plrno);
4619 }
4620 }
4621 secfile_insert_str(saving->file, plr->server.orig_username,
4622 "player%d.orig_username", plrno);
4623 secfile_insert_str(saving->file, plr->ranked_username,
4624 "player%d.ranked_username", plrno);
4625 secfile_insert_bool(saving->file, plr->unassigned_ranked,
4626 "player%d.unassigned_ranked", plrno);
4627 secfile_insert_str(saving->file,
4628 player_delegation_get(plr) ? player_delegation_get(plr)
4629 : "",
4630 "player%d.delegation_username", plrno);
4631 secfile_insert_str(saving->file, nation_rule_name(nation_of_player(plr)),
4632 "player%d.nation", plrno);
4633 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4634 "player%d.team_no", plrno);
4635
4636 secfile_insert_str(saving->file,
4637 government_rule_name(government_of_player(plr)),
4638 "player%d.government_name", plrno);
4639
4640 if (plr->target_government) {
4641 secfile_insert_str(saving->file,
4642 government_rule_name(plr->target_government),
4643 "player%d.target_government_name", plrno);
4644 }
4645
4646 secfile_insert_str(saving->file, style_rule_name(plr->style),
4647 "player%d.style_by_name", plrno);
4648
4649 secfile_insert_int(saving->file, plr->nturns_idle,
4650 "player%d.idle_turns", plrno);
4651 secfile_insert_bool(saving->file, plr->is_male,
4652 "player%d.is_male", plrno);
4653 secfile_insert_bool(saving->file, plr->is_alive,
4654 "player%d.is_alive", plrno);
4655 secfile_insert_int(saving->file, plr->turns_alive,
4656 "player%d.turns_alive", plrno);
4657 secfile_insert_int(saving->file, plr->last_war_action,
4658 "player%d.last_war", plrno);
4659 secfile_insert_bool(saving->file, plr->ai_controlled,
4660 "player%d.ai.control", plrno);
4661 secfile_insert_bool(saving->file, plr->phase_done,
4662 "player%d.phase_done", plrno);
4663
4664 players_iterate(pplayer) {
4665 char buf[32];
4666 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4667
4668 i = player_index(pplayer);
4669
4670 /* save diplomatic state */
4671 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4672
4673 secfile_insert_int(saving->file, ds->type,
4674 "%s.type", buf);
4675 secfile_insert_int(saving->file, ds->max_state,
4676 "%s.max_state", buf);
4677 secfile_insert_int(saving->file, ds->first_contact_turn,
4678 "%s.first_contact_turn", buf);
4679 secfile_insert_int(saving->file, ds->turns_left,
4680 "%s.turns_left", buf);
4681 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4682 "%s.has_reason_to_cancel", buf);
4683 secfile_insert_int(saving->file, ds->contact_turns_left,
4684 "%s.contact_turns_left", buf);
4685 secfile_insert_bool(saving->file, player_has_real_embassy(plr, pplayer),
4686 "%s.embassy", buf);
4687 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4688 "%s.gives_shared_vision", buf);
4689 } players_iterate_end;
4690
4691 players_iterate(aplayer) {
4692 i = player_index(aplayer);
4693 /* save ai data */
4694 secfile_insert_int(saving->file, plr->ai_common.love[i],
4695 "player%d.ai%d.love", plrno, i);
4696 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4697 } players_iterate_end;
4698
4699 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4700
4701 /* Multipliers (policies) */
4702 i = multiplier_count();
4703
4704 for (k = 0; k < i; k++) {
4705 secfile_insert_int(saving->file, plr->multipliers[k],
4706 "player%d.multiplier%d.val", plrno, k);
4707 secfile_insert_int(saving->file, plr->multipliers_target[k],
4708 "player%d.multiplier%d.target", plrno, k);
4709 }
4710
4711 secfile_insert_str(saving->file, ai_level_name(plr->ai_common.skill_level),
4712 "player%d.ai.level", plrno);
4713 secfile_insert_str(saving->file, barbarian_type_name(plr->ai_common.barbarian_type),
4714 "player%d.ai.barb_type", plrno);
4715 secfile_insert_int(saving->file, plr->economic.gold,
4716 "player%d.gold", plrno);
4717 secfile_insert_int(saving->file, plr->economic.tax,
4718 "player%d.rates.tax", plrno);
4719 secfile_insert_int(saving->file, plr->economic.science,
4720 "player%d.rates.science", plrno);
4721 secfile_insert_int(saving->file, plr->economic.luxury,
4722 "player%d.rates.luxury", plrno);
4723 secfile_insert_int(saving->file, plr->server.bulbs_last_turn,
4724 "player%d.research.bulbs_last_turn", plrno);
4725
4726 /* Save traits */
4727 {
4728 enum trait tr;
4729 int j;
4730
4731 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4732 secfile_insert_int(saving->file, plr->ai_common.traits[tr].val,
4733 "player%d.trait%d.val", plrno, j);
4734 secfile_insert_int(saving->file, plr->ai_common.traits[tr].mod,
4735 "player%d.trait%d.mod", plrno, j);
4736 }
4737 }
4738
4739 /* Save achievements */
4740 {
4741 int j = 0;
4742
4743 achievements_iterate(pach) {
4744 if (achievement_player_has(pach, plr)) {
4745 secfile_insert_str(saving->file, achievement_rule_name(pach),
4746 "player%d.achievement%d.name", plrno, j);
4747 if (pach->first == plr) {
4748 secfile_insert_bool(saving->file, TRUE,
4749 "player%d.achievement%d.first", plrno, j);
4750 } else {
4751 secfile_insert_bool(saving->file, FALSE,
4752 "player%d.achievement%d.first", plrno, j);
4753 }
4754
4755 j++;
4756 }
4757 } achievements_iterate_end;
4758
4759 secfile_insert_int(saving->file, j,
4760 "player%d.achievement_count", plrno);
4761 }
4762
4763 secfile_insert_bool(saving->file, plr->server.got_first_city,
4764 "player%d.got_first_city", plrno);
4765 secfile_insert_int(saving->file, plr->revolution_finishes,
4766 "player%d.revolution_finishes", plrno);
4767
4768 /* Player score */
4769 secfile_insert_int(saving->file, plr->score.happy,
4770 "score%d.happy", plrno);
4771 secfile_insert_int(saving->file, plr->score.content,
4772 "score%d.content", plrno);
4773 secfile_insert_int(saving->file, plr->score.unhappy,
4774 "score%d.unhappy", plrno);
4775 secfile_insert_int(saving->file, plr->score.angry,
4776 "score%d.angry", plrno);
4777 specialist_type_iterate(sp) {
4778 secfile_insert_int(saving->file, plr->score.specialists[sp],
4779 "score%d.specialists%d", plrno, sp);
4780 } specialist_type_iterate_end;
4781 secfile_insert_int(saving->file, plr->score.wonders,
4782 "score%d.wonders", plrno);
4783 secfile_insert_int(saving->file, plr->score.techs,
4784 "score%d.techs", plrno);
4785 secfile_insert_int(saving->file, plr->score.techout,
4786 "score%d.techout", plrno);
4787 secfile_insert_int(saving->file, plr->score.landarea,
4788 "score%d.landarea", plrno);
4789 secfile_insert_int(saving->file, plr->score.settledarea,
4790 "score%d.settledarea", plrno);
4791 secfile_insert_int(saving->file, plr->score.population,
4792 "score%d.population", plrno);
4793 secfile_insert_int(saving->file, plr->score.cities,
4794 "score%d.cities", plrno);
4795 secfile_insert_int(saving->file, plr->score.units,
4796 "score%d.units", plrno);
4797 secfile_insert_int(saving->file, plr->score.pollution,
4798 "score%d.pollution", plrno);
4799 secfile_insert_int(saving->file, plr->score.literacy,
4800 "score%d.literacy", plrno);
4801 secfile_insert_int(saving->file, plr->score.bnp,
4802 "score%d.bnp", plrno);
4803 secfile_insert_int(saving->file, plr->score.mfg,
4804 "score%d.mfg", plrno);
4805 secfile_insert_int(saving->file, plr->score.spaceship,
4806 "score%d.spaceship", plrno);
4807 secfile_insert_int(saving->file, plr->score.units_built,
4808 "score%d.units_built", plrno);
4809 secfile_insert_int(saving->file, plr->score.units_killed,
4810 "score%d.units_killed", plrno);
4811 secfile_insert_int(saving->file, plr->score.units_lost,
4812 "score%d.units_lost", plrno);
4813 secfile_insert_int(saving->file, plr->score.culture,
4814 "score%d.culture", plrno);
4815 secfile_insert_int(saving->file, plr->score.game,
4816 "score%d.total", plrno);
4817
4818 /* Save space ship status. */
4819 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4820 plrno);
4821 if (ship->state != SSHIP_NONE) {
4822 char buf[32];
4823 char st[NUM_SS_STRUCTURALS+1];
4824 int ssi;
4825
4826 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4827
4828 secfile_insert_int(saving->file, ship->structurals,
4829 "%s.structurals", buf);
4830 secfile_insert_int(saving->file, ship->components,
4831 "%s.components", buf);
4832 secfile_insert_int(saving->file, ship->modules,
4833 "%s.modules", buf);
4834 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4835 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4836 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4837 secfile_insert_int(saving->file, ship->life_support,
4838 "%s.life_support", buf);
4839 secfile_insert_int(saving->file, ship->solar_panels,
4840 "%s.solar_panels", buf);
4841
4842 for(ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4843 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4844 }
4845 st[ssi] = '\0';
4846 secfile_insert_str(saving->file, st, "%s.structure", buf);
4847 if (ship->state >= SSHIP_LAUNCHED) {
4848 secfile_insert_int(saving->file, ship->launch_year,
4849 "%s.launch_year", buf);
4850 }
4851 }
4852
4853 /* Save lost wonders info. */
4854 {
4855 char lost[B_LAST+1];
4856
4857 improvement_iterate(pimprove) {
4858 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
4859 lost[improvement_index(pimprove)] = '1';
4860 } else {
4861 lost[improvement_index(pimprove)] = '0';
4862 }
4863 } improvement_iterate_end;
4864 lost[improvement_count()] = '\0';
4865 secfile_insert_str(saving->file, lost,
4866 "player%d.lost_wonders", plrno);
4867 }
4868
4869 secfile_insert_int(saving->file, plr->history,
4870 "player%d.culture", plrno);
4871 secfile_insert_int(saving->file, plr->server.huts,
4872 "player%d.hut_count", plrno);
4873 }
4874
4875 /****************************************************************************
4876 Load city data
4877 ****************************************************************************/
sg_load_player_cities(struct loaddata * loading,struct player * plr)4878 static void sg_load_player_cities(struct loaddata *loading,
4879 struct player *plr)
4880 {
4881 int ncities, i, plrno = player_number(plr);
4882 bool tasks_handled;
4883
4884 /* Check status and return if not OK (sg_success != TRUE). */
4885 sg_check_ret();
4886
4887 sg_failure_ret(secfile_lookup_int(loading->file, &ncities,
4888 "player%d.ncities", plrno),
4889 "%s", secfile_error());
4890
4891 if (!plr->is_alive && ncities > 0) {
4892 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
4893 ncities = 0;
4894 }
4895
4896 if (!plr->server.got_first_city && ncities > 0) {
4897 /* Probably barbarians in an old savegame; fix up */
4898 plr->server.got_first_city = TRUE;
4899 }
4900
4901 /* Load all cities of the player. */
4902 for (i = 0; i < ncities; i++) {
4903 char buf[32];
4904 struct city *pcity;
4905
4906 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
4907
4908 /* Create a dummy city. */
4909 pcity = create_city_virtual(plr, NULL, buf);
4910 adv_city_alloc(pcity);
4911 if (!sg_load_player_city(loading, plr, pcity, buf)) {
4912 adv_city_free(pcity);
4913 destroy_city_virtual(pcity);
4914 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
4915 }
4916
4917 identity_number_reserve(pcity->id);
4918 idex_register_city(pcity);
4919
4920 /* Load the information about the nationality of citizens. This is done
4921 * here because the city sanity check called by citizens_update() requires
4922 * that the city is registered. */
4923 sg_load_player_city_citizens(loading, plr, pcity, buf);
4924
4925 /* After everything is loaded, but before vision. */
4926 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
4927
4928 /* adding the city contribution to fog-of-war */
4929 pcity->server.vision = vision_new(plr, city_tile(pcity));
4930 vision_reveal_tiles(pcity->server.vision, game.server.vision_reveal_tiles);
4931 city_refresh_vision(pcity);
4932
4933 city_list_append(plr->cities, pcity);
4934 }
4935
4936 tasks_handled = FALSE;
4937 for (i = 0; !tasks_handled; i++) {
4938 int city_id;
4939 struct city *pcity = NULL;
4940
4941 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
4942 plrno, i);
4943
4944 if (city_id != -1) {
4945 pcity = player_city_by_number(plr, city_id);
4946 }
4947
4948 if (pcity != NULL) {
4949 const char *str;
4950 int nat_x, nat_y;
4951 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
4952
4953 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
4954 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
4955
4956 ptask->ptile = native_pos_to_tile(nat_x, nat_y);
4957
4958 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
4959 ptask->act = unit_activity_by_name(str, fc_strcasecmp);
4960
4961 sg_failure_ret(unit_activity_is_valid(ptask->act),
4962 "Unknown workertask activity %s", str);
4963
4964 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
4965
4966 if (strcmp("-", str)) {
4967 ptask->tgt = extra_type_by_rule_name(str);
4968
4969 sg_failure_ret(ptask->tgt != NULL,
4970 "Unknown workertask target %s", str);
4971 } else {
4972 ptask->tgt = NULL;
4973 }
4974
4975 ptask->want = secfile_lookup_int_default(loading->file, 1,
4976 "player%d.task%d.want", plrno, i);
4977
4978 worker_task_list_append(pcity->task_reqs, ptask);
4979 } else {
4980 tasks_handled = TRUE;
4981 }
4982 }
4983 }
4984
4985 /****************************************************************************
4986 Load data for one city. sg_save_player_city() is not defined.
4987 ****************************************************************************/
sg_load_player_city(struct loaddata * loading,struct player * plr,struct city * pcity,const char * citystr)4988 static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
4989 struct city *pcity, const char *citystr)
4990 {
4991 struct player *past;
4992 const char *kind, *name, *string;
4993 int id, i, repair, sp_count = 0, workers = 0, value;
4994 int nat_x, nat_y;
4995 citizens size;
4996 const char *stylename;
4997
4998 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x", citystr),
4999 FALSE, "%s", secfile_error());
5000 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y", citystr),
5001 FALSE, "%s", secfile_error());
5002 pcity->tile = native_pos_to_tile(nat_x, nat_y);
5003 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5004 "%s has invalid center tile (%d, %d)",
5005 citystr, nat_x, nat_y);
5006 sg_warn_ret_val(NULL == tile_city(pcity->tile), FALSE,
5007 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5008
5009 /* Instead of dying, use 'citystr' string for damaged name. */
5010 sz_strlcpy(pcity->name, secfile_lookup_str_default(loading->file, citystr,
5011 "%s.name", citystr));
5012
5013 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5014 citystr), FALSE, "%s", secfile_error());
5015
5016 id = secfile_lookup_int_default(loading->file, player_number(plr),
5017 "%s.original", citystr);
5018 past = player_by_number(id);
5019 if (NULL != past) {
5020 pcity->original = past;
5021 }
5022
5023 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5024 citystr), FALSE, "%s", secfile_error());
5025 size = (citizens)value; /* set the correct type */
5026 sg_warn_ret_val(value == (int)size, FALSE,
5027 "Invalid city size: %d, set to %d", value, size);
5028 city_size_set(pcity, size);
5029
5030 for (i = 0; i < loading->specialist.size; i++) {
5031 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5032 citystr, i),
5033 FALSE, "%s", secfile_error());
5034 pcity->specialists[specialist_index(loading->specialist.order[i])]
5035 = (citizens)value;
5036 sp_count += value;
5037 }
5038
5039 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
5040 pcity->trade[i] = secfile_lookup_int_default(loading->file, 0,
5041 "%s.traderoute%d", citystr, i);
5042 }
5043
5044 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5045 "%s.food_stock", citystr),
5046 FALSE, "%s", secfile_error());
5047 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5048 "%s.shield_stock", citystr),
5049 FALSE, "%s", secfile_error());
5050 pcity->history =
5051 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5052
5053 pcity->airlift =
5054 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5055 pcity->was_happy =
5056 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5057 citystr);
5058
5059 pcity->turn_plague =
5060 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5061
5062 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->anarchy,
5063 "%s.anarchy", citystr),
5064 FALSE, "%s", secfile_error());
5065 pcity->rapture =
5066 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5067 pcity->server.steal =
5068 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5069
5070 /* before did_buy for undocumented hack */
5071 pcity->turn_founded =
5072 secfile_lookup_int_default(loading->file, -2, "%s.turn_founded",
5073 citystr);
5074 sg_warn_ret_val(secfile_lookup_int(loading->file, &i, "%s.did_buy",
5075 citystr), FALSE, "%s", secfile_error());
5076 pcity->did_buy = (i != 0);
5077 if (i == -1 && pcity->turn_founded == -2) {
5078 /* undocumented hack */
5079 pcity->turn_founded = game.info.turn;
5080 }
5081
5082 pcity->did_sell =
5083 secfile_lookup_bool_default(loading->file, FALSE, "%s.did_sell", citystr);
5084
5085 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5086 "%s.turn_last_built", citystr),
5087 FALSE, "%s", secfile_error());
5088
5089 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5090 citystr);
5091 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5092 citystr);
5093 pcity->production = universal_by_rule_name(kind, name);
5094 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5095 "%s.currently_building: unknown \"%s\" \"%s\".",
5096 citystr, kind, name);
5097
5098 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5099 citystr);
5100 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5101 citystr);
5102 pcity->changed_from = universal_by_rule_name(kind, name);
5103 sg_warn_ret_val(pcity->changed_from.kind != universals_n_invalid(), FALSE,
5104 "%s.changed_from: unknown \"%s\" \"%s\".",
5105 citystr, kind, name);
5106
5107 pcity->before_change_shields =
5108 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5109 "%s.before_change_shields", citystr);
5110 pcity->caravan_shields =
5111 secfile_lookup_int_default(loading->file, 0,
5112 "%s.caravan_shields", citystr);
5113 pcity->disbanded_shields =
5114 secfile_lookup_int_default(loading->file, 0,
5115 "%s.disbanded_shields", citystr);
5116 pcity->last_turns_shield_surplus =
5117 secfile_lookup_int_default(loading->file, 0,
5118 "%s.last_turns_shield_surplus",
5119 citystr);
5120
5121 stylename = secfile_lookup_str_default(loading->file, NULL,
5122 "%s.style", citystr);
5123 if (stylename != NULL) {
5124 pcity->style = city_style_by_rule_name(stylename);
5125 } else {
5126 pcity->style = 0;
5127 }
5128 if (pcity->style < 0) {
5129 pcity->style = city_style(pcity);
5130 }
5131
5132 pcity->server.synced = FALSE; /* must re-sync with clients */
5133
5134 /* Initialise list of city improvements. */
5135 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5136 pcity->built[i].turn = I_NEVER;
5137 }
5138
5139 /* Load city improvements. */
5140 string = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5141 sg_warn_ret_val(string != NULL, FALSE, "%s", secfile_error());
5142 sg_warn_ret_val(strlen(string) == loading->improvement.size, FALSE,
5143 "Invalid length of '%s.improvements' (%lu ~= %lu).",
5144 citystr, (unsigned long) strlen(string),
5145 (unsigned long) loading->improvement.size);
5146 for (i = 0; i < loading->improvement.size; i++) {
5147 sg_warn_ret_val(string[i] == '1' || string[i] == '0', FALSE,
5148 "Undefined value '%c' within '%s.improvements'.",
5149 string[i], citystr)
5150
5151 if (string[i] == '1') {
5152 struct impr_type *pimprove =
5153 improvement_by_rule_name(loading->improvement.order[i]);
5154 if (pimprove) {
5155 city_add_improvement(pcity, pimprove);
5156 }
5157 }
5158 }
5159
5160 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5161 "No worked tiles map defined.");
5162
5163 city_freeze_workers(pcity);
5164
5165 /* load new savegame with variable (squared) city radius and worked
5166 * tiles map */
5167
5168 int radius_sq
5169 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5170 citystr);
5171 city_map_radius_sq_set(pcity, radius_sq);
5172
5173 city_tile_iterate(radius_sq, city_tile(pcity), ptile) {
5174 if (loading->worked_tiles[ptile->index] == pcity->id) {
5175 tile_set_worked(ptile, pcity);
5176 workers++;
5177
5178 #ifdef FREECIV_DEBUG
5179 /* set this tile to unused; a check for not resetted tiles is
5180 * included in game_load_internal() */
5181 loading->worked_tiles[ptile->index] = -1;
5182 #endif /* FREECIV_DEBUG */
5183 }
5184 } city_tile_iterate_end;
5185
5186 if (tile_worked(city_tile(pcity)) != pcity) {
5187 struct city *pwork = tile_worked(city_tile(pcity));
5188
5189 if (NULL != pwork) {
5190 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5191 "(%d,%d) [%d]; repairing ", citystr, city_name_get(pcity),
5192 TILE_XY(city_tile(pcity)), city_size_get(pcity), city_name_get(pwork),
5193 TILE_XY(city_tile(pwork)), city_size_get(pwork));
5194
5195 tile_set_worked(city_tile(pcity), NULL); /* remove tile from pwork */
5196 pwork->specialists[DEFAULT_SPECIALIST]++;
5197 auto_arrange_workers(pwork);
5198 } else {
5199 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing ",
5200 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5201 city_size_get(pcity));
5202 }
5203
5204 /* repair pcity */
5205 tile_set_worked(city_tile(pcity), pcity);
5206 city_repair_size(pcity, -1);
5207 }
5208
5209 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5210 if (0 != repair) {
5211 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5212 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5213 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5214 workers, FREE_WORKED_TILES, sp_count);
5215
5216 /* repair pcity */
5217 city_repair_size(pcity, repair);
5218 }
5219
5220 /* worklist_init() done in create_city_virtual() */
5221 worklist_load(loading->file, &pcity->worklist, "%s", citystr);
5222
5223 /* Load city options. */
5224 BV_CLR_ALL(pcity->city_options);
5225 for (i = 0; i < CITYO_LAST; i++) {
5226 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5227 citystr, i)) {
5228 BV_SET(pcity->city_options, i);
5229 }
5230 }
5231
5232 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5233
5234 return TRUE;
5235 }
5236
5237 /****************************************************************************
5238 Load nationality data for one city.
5239 ****************************************************************************/
sg_load_player_city_citizens(struct loaddata * loading,struct player * plr,struct city * pcity,const char * citystr)5240 static void sg_load_player_city_citizens(struct loaddata *loading,
5241 struct player *plr,
5242 struct city *pcity,
5243 const char *citystr)
5244 {
5245 if (game.info.citizen_nationality) {
5246 citizens size;
5247
5248 citizens_init(pcity);
5249 player_slots_iterate(pslot) {
5250 int nationality;
5251
5252 nationality = secfile_lookup_int_default(loading->file, -1,
5253 "%s.citizen%d", citystr,
5254 player_slot_index(pslot));
5255 if (nationality > 0 && !player_slot_is_used(pslot)) {
5256 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5257 city_name_get(pcity), player_slot_index(pslot));
5258 continue;
5259 }
5260
5261 if (nationality != -1 && player_slot_is_used(pslot)) {
5262 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5263 "Invalid value for citizens of player %d in %s: %d.",
5264 player_slot_index(pslot), city_name_get(pcity), nationality);
5265 citizens_nation_set(pcity, pslot, nationality);
5266 }
5267 } player_slots_iterate_end;
5268 /* Sanity check. */
5269 size = citizens_count(pcity);
5270 if (size != city_size_get(pcity)) {
5271 if (size != 0) {
5272 /* size == 0 can be result from the fact that ruleset had no
5273 * nationality enabled at saving time, so no citizens at all
5274 * were saved. But something more serious must be going on if
5275 * citizens have been saved partially - if some of them are there. */
5276 log_sg("City size and number of citizens does not match in %s "
5277 "(%d != %d)! Repairing ...", city_name_get(pcity),
5278 city_size_get(pcity), size);
5279 }
5280 citizens_update(pcity, NULL);
5281 }
5282 }
5283 }
5284
5285 /****************************************************************************
5286 Save cities data
5287 ****************************************************************************/
sg_save_player_cities(struct savedata * saving,struct player * plr)5288 static void sg_save_player_cities(struct savedata *saving,
5289 struct player *plr)
5290 {
5291 int wlist_max_length = 0;
5292 int i = 0;
5293 int plrno = player_number(plr);
5294 bool nations[MAX_NUM_PLAYER_SLOTS];
5295
5296 /* Check status and return if not OK (sg_success != TRUE). */
5297 sg_check_ret();
5298
5299 secfile_insert_int(saving->file, city_list_size(plr->cities),
5300 "player%d.ncities", plrno);
5301
5302 if (game.info.citizen_nationality) {
5303 /* Initialise the nation list for the citizens information. */
5304 player_slots_iterate(pslot) {
5305 nations[player_slot_index(pslot)] = FALSE;
5306 } player_slots_iterate_end;
5307 }
5308
5309 /* First determine lenght of longest worklist and the nations we have. */
5310 city_list_iterate(plr->cities, pcity) {
5311 /* Check the sanity of the city. */
5312 city_refresh(pcity);
5313 sanity_check_city(pcity);
5314
5315 if (pcity->worklist.length > wlist_max_length) {
5316 wlist_max_length = pcity->worklist.length;
5317 }
5318
5319 if (game.info.citizen_nationality) {
5320 /* Find all nations of the citizens,*/
5321 players_iterate(pplayer) {
5322 if (!nations[player_index(pplayer)]
5323 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5324 nations[player_index(pplayer)] = TRUE;
5325 }
5326 } players_iterate_end;
5327 }
5328 } city_list_iterate_end;
5329
5330 city_list_iterate(plr->cities, pcity) {
5331 struct tile *pcenter = city_tile(pcity);
5332 char impr_buf[MAX_NUM_ITEMS + 1];
5333 char buf[32];
5334 int j, nat_x, nat_y;
5335
5336 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5337
5338
5339 index_to_native_pos(&nat_x, &nat_y, tile_index(pcenter));
5340 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5341 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5342
5343 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5344
5345 secfile_insert_int(saving->file, player_number(pcity->original),
5346 "%s.original", buf);
5347 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5348
5349 j = 0;
5350 specialist_type_iterate(sp) {
5351 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5352 buf, j++);
5353 } specialist_type_iterate_end;
5354
5355 for (j = 0; j < MAX_TRADE_ROUTES; j++) {
5356 secfile_insert_int(saving->file, pcity->trade[j], "%s.traderoute%d",
5357 buf, j);
5358 }
5359
5360 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5361 buf);
5362 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5363 buf);
5364 secfile_insert_int(saving->file, pcity->history, "%s.history",
5365 buf);
5366
5367 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5368 buf);
5369 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5370 buf);
5371 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5372 buf);
5373
5374 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5375 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5376 secfile_insert_int(saving->file, pcity->server.steal, "%s.steal", buf);
5377
5378 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5379 buf);
5380 if (pcity->turn_founded == game.info.turn) {
5381 j = -1; /* undocumented hack */
5382 } else {
5383 fc_assert(pcity->did_buy == TRUE || pcity->did_buy == FALSE);
5384 j = pcity->did_buy ? 1 : 0;
5385 }
5386 secfile_insert_int(saving->file, j, "%s.did_buy", buf);
5387 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5388 secfile_insert_int(saving->file, pcity->turn_last_built,
5389 "%s.turn_last_built", buf);
5390
5391 /* for visual debugging, variable length strings together here */
5392 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5393
5394 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5395 "%s.currently_building_kind", buf);
5396 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5397 "%s.currently_building_name", buf);
5398
5399 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5400 "%s.changed_from_kind", buf);
5401 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5402 "%s.changed_from_name", buf);
5403
5404 secfile_insert_int(saving->file, pcity->before_change_shields,
5405 "%s.before_change_shields", buf);
5406 secfile_insert_int(saving->file, pcity->caravan_shields,
5407 "%s.caravan_shields", buf);
5408 secfile_insert_int(saving->file, pcity->disbanded_shields,
5409 "%s.disbanded_shields", buf);
5410 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5411 "%s.last_turns_shield_surplus", buf);
5412
5413 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5414 "%s.style", buf);
5415
5416 /* Save the squared city radius and all tiles within the corresponing
5417 * city map. */
5418 secfile_insert_int(saving->file, pcity->city_radius_sq,
5419 "player%d.c%d.city_radius_sq", plrno, i);
5420 /* The tiles worked by the city are saved using the main map.
5421 * See also sg_save_map_worked(). */
5422
5423 /* Save improvement list as bytevector. Note that improvement order
5424 * is saved in savefile.improvement_order. */
5425 improvement_iterate(pimprove) {
5426 impr_buf[improvement_index(pimprove)]
5427 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5428 : '1';
5429 } improvement_iterate_end;
5430 impr_buf[improvement_count()] = '\0';
5431 sg_failure_ret(strlen(impr_buf) < sizeof(impr_buf),
5432 "Invalid size of the improvement vector (%s.improvements: "
5433 "%lu < %lu).", buf, (long unsigned int) strlen(impr_buf),
5434 (long unsigned int) sizeof(impr_buf));
5435 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5436
5437 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5438 buf);
5439
5440 for (j = 0; j < CITYO_LAST; j++) {
5441 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5442 "%s.option%d", buf, j);
5443 }
5444
5445 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5446
5447 if (game.info.citizen_nationality) {
5448 /* Save nationality of the citizens,*/
5449 players_iterate(pplayer) {
5450 if (nations[player_index(pplayer)]) {
5451 secfile_insert_int(saving->file,
5452 citizens_nation_get(pcity, pplayer->slot),
5453 "%s.citizen%d", buf, player_index(pplayer));
5454 }
5455 } players_iterate_end;
5456 }
5457
5458 i++;
5459 } city_list_iterate_end;
5460
5461 i = 0;
5462 city_list_iterate(plr->cities, pcity) {
5463 worker_task_list_iterate(pcity->task_reqs, ptask) {
5464 int nat_x, nat_y;
5465
5466 index_to_native_pos(&nat_x, &nat_y, tile_index(ptask->ptile));
5467 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
5468 plrno, i);
5469 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
5470 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
5471 secfile_insert_str(saving->file, unit_activity_name(ptask->act),
5472 "player%d.task%d.activity",
5473 plrno, i);
5474 if (ptask->tgt != NULL) {
5475 secfile_insert_str(saving->file, extra_rule_name(ptask->tgt),
5476 "player%d.task%d.target",
5477 plrno, i);
5478 } else {
5479 secfile_insert_str(saving->file, "-",
5480 "player%d.task%d.target",
5481 plrno, i);
5482 }
5483 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
5484
5485 i++;
5486 } worker_task_list_iterate_end;
5487 } city_list_iterate_end;
5488 }
5489
5490 /****************************************************************************
5491 Load unit data
5492 ****************************************************************************/
sg_load_player_units(struct loaddata * loading,struct player * plr)5493 static void sg_load_player_units(struct loaddata *loading,
5494 struct player *plr)
5495 {
5496 int nunits, i, plrno = player_number(plr);
5497
5498 /* Check status and return if not OK (sg_success != TRUE). */
5499 sg_check_ret();
5500
5501 sg_failure_ret(secfile_lookup_int(loading->file, &nunits,
5502 "player%d.nunits", plrno),
5503 "%s", secfile_error());
5504 if (!plr->is_alive && nunits > 0) {
5505 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
5506 nunits = 0; /* Some old savegames may be buggy. */
5507 }
5508
5509 for (i = 0; i < nunits; i++) {
5510 struct unit *punit;
5511 struct city *pcity;
5512 const char *name;
5513 char buf[32];
5514 struct unit_type *type;
5515 struct tile *ptile;
5516
5517 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
5518
5519 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
5520 type = unit_type_by_rule_name(name);
5521 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
5522
5523 /* Create a dummy unit. */
5524 punit = unit_virtual_create(plr, NULL, type, 0);
5525 if (!sg_load_player_unit(loading, plr, punit, buf)) {
5526 unit_virtual_destroy(punit);
5527 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
5528 }
5529
5530 identity_number_reserve(punit->id);
5531 idex_register_unit(punit);
5532
5533 if ((pcity = game_city_by_number(punit->homecity))) {
5534 unit_list_prepend(pcity->units_supported, punit);
5535 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
5536 log_sg("%s: bad home city %d.", buf, punit->homecity);
5537 punit->homecity = IDENTITY_NUMBER_ZERO;
5538 }
5539
5540 ptile = unit_tile(punit);
5541
5542 /* allocate the unit's contribution to fog of war */
5543 punit->server.vision = vision_new(unit_owner(punit), ptile);
5544 unit_refresh_vision(punit);
5545 /* NOTE: There used to be some map_set_known calls here. These were
5546 * unneeded since unfogging the tile when the unit sees it will
5547 * automatically reveal that tile. */
5548
5549 unit_list_append(plr->units, punit);
5550 unit_list_prepend(unit_tile(punit)->units, punit);
5551
5552 /* Claim ownership of fortress? */
5553 if ((extra_owner(ptile) == NULL
5554 || pplayers_at_war(extra_owner(ptile), plr))
5555 && tile_has_claimable_base(ptile, unit_type_get(punit))) {
5556 tile_claim_bases(ptile, plr);
5557 }
5558 }
5559 }
5560
5561 /****************************************************************************
5562 Load one unit. sg_save_player_unit() is not defined.
5563 ****************************************************************************/
sg_load_player_unit(struct loaddata * loading,struct player * plr,struct unit * punit,const char * unitstr)5564 static bool sg_load_player_unit(struct loaddata *loading,
5565 struct player *plr, struct unit *punit,
5566 const char *unitstr)
5567 {
5568 int j;
5569 enum unit_activity activity;
5570 int nat_x, nat_y;
5571 enum tile_special_type target;
5572 struct extra_type *pextra = NULL;
5573 struct base_type *pbase = NULL;
5574 struct road_type *proad = NULL;
5575 struct tile *ptile;
5576 int extra_id;
5577 int base_id;
5578 int road_id;
5579 int ei;
5580 const char *facing_str;
5581 enum tile_special_type cfspe;
5582 int natnbr;
5583
5584 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->id, "%s.id",
5585 unitstr), FALSE, "%s", secfile_error());
5586 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x", unitstr),
5587 FALSE, "%s", secfile_error());
5588 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y", unitstr),
5589 FALSE, "%s", secfile_error());
5590
5591 ptile = native_pos_to_tile(nat_x, nat_y);
5592 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
5593 unitstr, nat_x, nat_y);
5594 unit_tile_set(punit, ptile);
5595
5596 facing_str
5597 = secfile_lookup_str_default(loading->file, "x",
5598 "%s.facing", unitstr);
5599 if (facing_str[0] != 'x') {
5600 /* We don't touch punit->facing if savegame does not contain that
5601 * information. Initial orientation set by unit_virtual_create()
5602 * is as good as any. */
5603 enum direction8 facing = char2dir(facing_str[0]);
5604
5605 if (direction8_is_valid(facing)) {
5606 punit->facing = facing;
5607 } else {
5608 log_error("Illegal unit orientation '%s'", facing_str);
5609 }
5610 }
5611
5612 /* If savegame has unit nationality, it doesn't hurt to
5613 * internally set it even if nationality rules are disabled. */
5614 natnbr = secfile_lookup_int_default(loading->file,
5615 player_number(plr),
5616 "%s.nationality", unitstr);
5617
5618 punit->nationality = player_by_number(natnbr);
5619 if (punit->nationality == NULL) {
5620 punit->nationality = plr;
5621 }
5622
5623 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->homecity,
5624 "%s.homecity", unitstr), FALSE,
5625 "%s", secfile_error());
5626 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->moves_left,
5627 "%s.moves", unitstr), FALSE,
5628 "%s", secfile_error());
5629 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->fuel,
5630 "%s.fuel", unitstr), FALSE,
5631 "%s", secfile_error());
5632 sg_warn_ret_val(secfile_lookup_int(loading->file, &ei,
5633 "%s.activity", unitstr), FALSE,
5634 "%s", secfile_error());
5635 activity = ei;
5636
5637 punit->server.birth_turn
5638 = secfile_lookup_int_default(loading->file, game.info.turn,
5639 "%s.born", unitstr);
5640
5641 if (activity == ACTIVITY_PATROL_UNUSED) {
5642 /* Previously ACTIVITY_PATROL and ACTIVITY_GOTO were used for
5643 * client-side goto. Now client-side goto is handled by setting
5644 * a special flag, and units with orders generally have ACTIVITY_IDLE.
5645 * Old orders are lost. Old client-side goto units will still have
5646 * ACTIVITY_GOTO and will goto the correct position via server goto.
5647 * Old client-side patrol units lose their patrol routes and are put
5648 * into idle mode. */
5649 activity = ACTIVITY_IDLE;
5650 }
5651
5652 extra_id = secfile_lookup_int_default(loading->file, -2,
5653 "%s.activity_tgt", unitstr);
5654
5655 if (extra_id != -2) {
5656 if (extra_id >= 0 && extra_id < loading->extra.size) {
5657 pextra = loading->extra.order[extra_id];
5658 set_unit_activity_targeted(punit, activity, pextra);
5659 } else if (activity == ACTIVITY_IRRIGATE) {
5660 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5661 EC_IRRIGATION,
5662 unit_owner(punit),
5663 punit);
5664 if (tgt != NULL) {
5665 set_unit_activity_targeted(punit, ACTIVITY_IRRIGATE, tgt);
5666 } else {
5667 set_unit_activity_targeted(punit, ACTIVITY_IRRIGATE, NULL);
5668 }
5669 } else if (activity == ACTIVITY_MINE) {
5670 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5671 EC_MINE,
5672 unit_owner(punit),
5673 punit);
5674 if (tgt != NULL) {
5675 set_unit_activity_targeted(punit, ACTIVITY_MINE, tgt);
5676 } else {
5677 set_unit_activity_targeted(punit, ACTIVITY_MINE, NULL);
5678 }
5679 } else {
5680 set_unit_activity(punit, activity);
5681 }
5682 } else {
5683 /* extra_id == -2 -> activity_tgt not set */
5684 base_id = secfile_lookup_int_default(loading->file, -1,
5685 "%s.activity_base", unitstr);
5686 if (base_id >= 0 && base_id < loading->base.size) {
5687 pbase = loading->base.order[base_id];
5688 }
5689 road_id = secfile_lookup_int_default(loading->file, -1,
5690 "%s.activity_road", unitstr);
5691 if (road_id >= 0 && road_id < loading->road.size) {
5692 proad = loading->road.order[road_id];
5693 }
5694
5695 {
5696 int tgt_no = secfile_lookup_int_default(loading->file,
5697 loading->special.size /* S_LAST */,
5698 "%s.activity_target", unitstr);
5699 if (tgt_no >= 0 && tgt_no < loading->special.size) {
5700 target = loading->special.order[tgt_no];
5701 } else {
5702 target = S_LAST;
5703 }
5704 }
5705
5706 if (target == S_OLD_ROAD) {
5707 target = S_LAST;
5708 proad = road_by_compat_special(ROCO_ROAD);
5709 } else if (target == S_OLD_RAILROAD) {
5710 target = S_LAST;
5711 proad = road_by_compat_special(ROCO_RAILROAD);
5712 }
5713
5714 if (activity == ACTIVITY_OLD_ROAD) {
5715 activity = ACTIVITY_GEN_ROAD;
5716 proad = road_by_compat_special(ROCO_ROAD);
5717 } else if (activity == ACTIVITY_OLD_RAILROAD) {
5718 activity = ACTIVITY_GEN_ROAD;
5719 proad = road_by_compat_special(ROCO_RAILROAD);
5720 }
5721
5722 /* We need changed_from == ACTIVITY_IDLE by now so that
5723 * set_unit_activity() and friends don't spuriously restore activity
5724 * points -- unit should have been created this way */
5725 fc_assert(punit->changed_from == ACTIVITY_IDLE);
5726
5727 if (activity == ACTIVITY_BASE) {
5728 if (pbase) {
5729 set_unit_activity_base(punit, base_number(pbase));
5730 } else {
5731 log_sg("Cannot find base %d for %s to build",
5732 base_id, unit_rule_name(punit));
5733 set_unit_activity(punit, ACTIVITY_IDLE);
5734 }
5735 } else if (activity == ACTIVITY_GEN_ROAD) {
5736 if (proad) {
5737 set_unit_activity_road(punit, road_number(proad));
5738 } else {
5739 log_sg("Cannot find road %d for %s to build",
5740 road_id, unit_rule_name(punit));
5741 set_unit_activity(punit, ACTIVITY_IDLE);
5742 }
5743 } else if (activity == ACTIVITY_PILLAGE) {
5744 struct extra_type *a_target;
5745
5746 if (target != S_LAST) {
5747 a_target = special_extra_get(target);
5748 } else if (pbase != NULL) {
5749 a_target = base_extra_get(pbase);
5750 } else if (proad != NULL) {
5751 a_target = road_extra_get(proad);
5752 } else {
5753 a_target = NULL;
5754 }
5755 /* An out-of-range base number is seen with old savegames. We take
5756 * it as indicating undirected pillaging. We will assign pillage
5757 * targets before play starts. */
5758 set_unit_activity_targeted(punit, activity, a_target);
5759 } else if (activity == ACTIVITY_IRRIGATE) {
5760 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5761 EC_IRRIGATION,
5762 unit_owner(punit),
5763 punit);
5764 if (tgt != NULL) {
5765 set_unit_activity_targeted(punit, ACTIVITY_IRRIGATE, tgt);
5766 } else {
5767 set_unit_activity_targeted(punit, ACTIVITY_IRRIGATE, NULL);
5768 }
5769 } else if (activity == ACTIVITY_MINE) {
5770 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5771 EC_MINE,
5772 unit_owner(punit),
5773 punit);
5774 if (tgt != NULL) {
5775 set_unit_activity_targeted(punit, ACTIVITY_MINE, tgt);
5776 } else {
5777 set_unit_activity_targeted(punit, ACTIVITY_MINE, NULL);
5778 }
5779 } else if (activity == ACTIVITY_POLLUTION) {
5780 struct extra_type *tgt = prev_extra_in_tile(unit_tile(punit),
5781 ERM_CLEANPOLLUTION,
5782 unit_owner(punit),
5783 punit);
5784 if (tgt != NULL) {
5785 set_unit_activity_targeted(punit, ACTIVITY_POLLUTION, tgt);
5786 } else {
5787 set_unit_activity_targeted(punit, ACTIVITY_POLLUTION, NULL);
5788 }
5789 } else if (activity == ACTIVITY_FALLOUT) {
5790 struct extra_type *tgt = prev_extra_in_tile(unit_tile(punit),
5791 ERM_CLEANFALLOUT,
5792 unit_owner(punit),
5793 punit);
5794 if (tgt != NULL) {
5795 set_unit_activity_targeted(punit, ACTIVITY_FALLOUT, tgt);
5796 } else {
5797 set_unit_activity_targeted(punit, ACTIVITY_FALLOUT, NULL);
5798 }
5799 } else {
5800 set_unit_activity_targeted(punit, activity, NULL);
5801 }
5802 } /* activity_tgt == NULL */
5803
5804 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->activity_count,
5805 "%s.activity_count", unitstr), FALSE,
5806 "%s", secfile_error());
5807
5808 punit->changed_from =
5809 secfile_lookup_int_default(loading->file, ACTIVITY_IDLE,
5810 "%s.changed_from", unitstr);
5811
5812 extra_id = secfile_lookup_int_default(loading->file, -2,
5813 "%s.changed_from_tgt", unitstr);
5814
5815 if (extra_id != -2) {
5816 if (extra_id >= 0 && extra_id < loading->extra.size) {
5817 punit->changed_from_target = loading->extra.order[extra_id];
5818 } else {
5819 punit->changed_from_target = NULL;
5820 }
5821 } else {
5822 /* extra_id == -2 -> changed_from_tgt not set */
5823
5824 cfspe =
5825 secfile_lookup_int_default(loading->file, S_LAST,
5826 "%s.changed_from_target", unitstr);
5827 base_id =
5828 secfile_lookup_int_default(loading->file, -1,
5829 "%s.changed_from_base", unitstr);
5830 road_id =
5831 secfile_lookup_int_default(loading->file, -1,
5832 "%s.changed_from_road", unitstr);
5833
5834 if (road_id == -1) {
5835 if (cfspe == S_OLD_ROAD) {
5836 proad = road_by_compat_special(ROCO_ROAD);
5837 if (proad) {
5838 road_id = road_index(proad);
5839 }
5840 } else if (cfspe == S_OLD_RAILROAD) {
5841 proad = road_by_compat_special(ROCO_RAILROAD);
5842 if (proad) {
5843 road_id = road_index(proad);
5844 }
5845 }
5846 }
5847
5848 if (base_id >= 0 && base_id < loading->base.size) {
5849 punit->changed_from_target = base_extra_get(loading->base.order[base_id]);
5850 } else if (road_id >= 0 && road_id < loading->road.size) {
5851 punit->changed_from_target = road_extra_get(loading->road.order[road_id]);
5852 } else if (cfspe != S_LAST) {
5853 punit->changed_from_target = special_extra_get(cfspe);
5854 } else {
5855 punit->changed_from_target = NULL;
5856 }
5857
5858 if (punit->changed_from == ACTIVITY_IRRIGATE) {
5859 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5860 EC_IRRIGATION,
5861 unit_owner(punit),
5862 punit);
5863 if (tgt != NULL) {
5864 punit->changed_from_target = tgt;
5865 } else {
5866 punit->changed_from_target = NULL;
5867 }
5868 } else if (punit->changed_from == ACTIVITY_MINE) {
5869 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
5870 EC_MINE,
5871 unit_owner(punit),
5872 punit);
5873 if (tgt != NULL) {
5874 punit->changed_from_target = tgt;
5875 } else {
5876 punit->changed_from_target = NULL;
5877 }
5878 } else if (punit->changed_from == ACTIVITY_POLLUTION) {
5879 struct extra_type *tgt = prev_extra_in_tile(unit_tile(punit),
5880 ERM_CLEANPOLLUTION,
5881 unit_owner(punit),
5882 punit);
5883 if (tgt != NULL) {
5884 punit->changed_from_target = tgt;
5885 } else {
5886 punit->changed_from_target = NULL;
5887 }
5888 } else if (punit->changed_from == ACTIVITY_FALLOUT) {
5889 struct extra_type *tgt = prev_extra_in_tile(unit_tile(punit),
5890 ERM_CLEANFALLOUT,
5891 unit_owner(punit),
5892 punit);
5893 if (tgt != NULL) {
5894 punit->changed_from_target = tgt;
5895 } else {
5896 punit->changed_from_target = NULL;
5897 }
5898 }
5899 }
5900
5901 punit->changed_from_count =
5902 secfile_lookup_int_default(loading->file, 0,
5903 "%s.changed_from_count", unitstr);
5904
5905 /* Special case: for a long time, we accidentally incremented
5906 * activity_count while a unit was sentried, so it could increase
5907 * without bound (bug #20641) and be saved in old savefiles.
5908 * We zero it to prevent potential trouble overflowing the range
5909 * in network packets, etc. */
5910 if (activity == ACTIVITY_SENTRY) {
5911 punit->activity_count = 0;
5912 }
5913 if (punit->changed_from == ACTIVITY_SENTRY) {
5914 punit->changed_from_count = 0;
5915 }
5916
5917 punit->veteran
5918 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
5919 {
5920 /* Protect against change in veteran system in ruleset */
5921 const int levels = utype_veteran_levels(unit_type_get(punit));
5922 if (punit->veteran >= levels) {
5923 fc_assert(levels >= 1);
5924 punit->veteran = levels - 1;
5925 }
5926 }
5927 punit->done_moving
5928 = secfile_lookup_bool_default(loading->file, (punit->moves_left == 0),
5929 "%s.done_moving", unitstr);
5930 punit->battlegroup
5931 = secfile_lookup_int_default(loading->file, BATTLEGROUP_NONE,
5932 "%s.battlegroup", unitstr);
5933
5934 if (secfile_lookup_bool_default(loading->file, FALSE,
5935 "%s.go", unitstr)) {
5936 int gnat_x, gnat_y;
5937
5938 sg_warn_ret_val(secfile_lookup_int(loading->file, &gnat_x,
5939 "%s.goto_x", unitstr), FALSE,
5940 "%s", secfile_error());
5941 sg_warn_ret_val(secfile_lookup_int(loading->file, &gnat_y,
5942 "%s.goto_y", unitstr), FALSE,
5943 "%s", secfile_error());
5944
5945 punit->goto_tile = native_pos_to_tile(gnat_x, gnat_y);
5946 } else {
5947 punit->goto_tile = NULL;
5948
5949 /* These variables are not used but needed for saving the unit table.
5950 * Load them to prevent unused variables errors. */
5951 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
5952 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
5953 }
5954
5955 /* Load AI data of the unit. */
5956 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
5957
5958 sg_warn_ret_val(secfile_lookup_bool(loading->file,
5959 &punit->ai_controlled,
5960 "%s.ai", unitstr), FALSE,
5961 "%s", secfile_error());
5962 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->hp,
5963 "%s.hp", unitstr), FALSE,
5964 "%s", secfile_error());
5965
5966 punit->server.ord_map
5967 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
5968 punit->server.ord_city
5969 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
5970 punit->moved
5971 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
5972 punit->paradropped
5973 = secfile_lookup_bool_default(loading->file, FALSE,
5974 "%s.paradropped", unitstr);
5975
5976 /* The transport status (punit->transported_by) is loaded in
5977 * sg_player_units_transport(). */
5978
5979 /* Initialize upkeep values: these are hopefully initialized
5980 * elsewhere before use (specifically, in city_support(); but
5981 * fixme: check whether always correctly initialized?).
5982 * Below is mainly for units which don't have homecity --
5983 * otherwise these don't get initialized (and AI calculations
5984 * etc may use junk values). */
5985 output_type_iterate(o) {
5986 punit->upkeep[o] = utype_upkeep_cost(unit_type_get(punit), plr, o);
5987 } output_type_iterate_end;
5988
5989 punit->action_decision_want
5990 = secfile_lookup_enum_default(loading->file,
5991 ACT_DEC_NOTHING, action_decision,
5992 "%s.action_decision_want", unitstr);
5993
5994 if (punit->action_decision_want != ACT_DEC_NOTHING) {
5995 /* Load the tile to act against. */
5996 int adwt_x, adwt_y;
5997
5998 if (secfile_lookup_int(loading->file, &adwt_x,
5999 "%s.action_decision_tile_x", unitstr)
6000 && secfile_lookup_int(loading->file, &adwt_y,
6001 "%s.action_decision_tile_y", unitstr)) {
6002 punit->action_decision_tile = native_pos_to_tile(adwt_x, adwt_y);
6003 } else {
6004 punit->action_decision_want = ACT_DEC_NOTHING;
6005 punit->action_decision_tile = NULL;
6006 log_sg("Bad action_decision_tile for unit %d", punit->id);
6007 }
6008 } else {
6009 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6010 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6011 punit->action_decision_tile = NULL;
6012 }
6013
6014 /* load the unit orders */
6015 {
6016 int len = secfile_lookup_int_default(loading->file, 0,
6017 "%s.orders_length", unitstr);
6018 if (len > 0) {
6019 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6020 const char *tgt_unitstr;
6021 const char *base_unitstr = NULL;
6022 const char *road_unitstr = NULL;
6023 int road_idx = road_index(road_by_compat_special(ROCO_ROAD));
6024 int rail_idx = road_index(road_by_compat_special(ROCO_RAILROAD));
6025
6026 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6027 punit->orders.length = len;
6028 punit->orders.index
6029 = secfile_lookup_int_default(loading->file, 0,
6030 "%s.orders_index", unitstr);
6031 punit->orders.repeat
6032 = secfile_lookup_bool_default(loading->file, FALSE,
6033 "%s.orders_repeat", unitstr);
6034 punit->orders.vigilant
6035 = secfile_lookup_bool_default(loading->file, FALSE,
6036 "%s.orders_vigilant", unitstr);
6037
6038 orders_unitstr
6039 = secfile_lookup_str_default(loading->file, "",
6040 "%s.orders_list", unitstr);
6041 dir_unitstr
6042 = secfile_lookup_str_default(loading->file, "",
6043 "%s.dir_list", unitstr);
6044 act_unitstr
6045 = secfile_lookup_str_default(loading->file, "",
6046 "%s.activity_list", unitstr);
6047 tgt_unitstr
6048 = secfile_lookup_str_default(loading->file, NULL, "%s.tgt_list", unitstr);
6049
6050 if (tgt_unitstr == NULL) {
6051 base_unitstr
6052 = secfile_lookup_str(loading->file, "%s.base_list", unitstr);
6053 road_unitstr
6054 = secfile_lookup_str_default(loading->file, NULL, "%s.road_list", unitstr);
6055 }
6056
6057 punit->has_orders = TRUE;
6058 for (j = 0; j < len; j++) {
6059 struct unit_order *order = &punit->orders.list[j];
6060
6061 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6062 || act_unitstr[j] == '\0') {
6063 log_sg("Invalid unit orders.");
6064 free_unit_orders(punit);
6065 break;
6066 }
6067 order->order = char2order(orders_unitstr[j]);
6068 order->dir = char2dir(dir_unitstr[j]);
6069 order->activity = char2activity(act_unitstr[j]);
6070 if (order->order == ORDER_LAST
6071 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6072 || (order->order == ORDER_ACTION_MOVE
6073 && !direction8_is_valid(order->dir))
6074 || (order->order == ORDER_ACTIVITY
6075 && order->activity == ACTIVITY_LAST)) {
6076 /* An invalid order. Just drop the orders for this unit. */
6077 free(punit->orders.list);
6078 punit->orders.list = NULL;
6079 punit->has_orders = FALSE;
6080 break;
6081 }
6082
6083 if (tgt_unitstr) {
6084 if (tgt_unitstr[j] != '?') {
6085 extra_id = char2num(tgt_unitstr[j]);
6086
6087 if (extra_id < 0 || extra_id >= loading->extra.size) {
6088 log_sg("Cannot find extra %d for %s to build",
6089 extra_id, unit_rule_name(punit));
6090 order->target = EXTRA_NONE;
6091 } else {
6092 order->target = extra_id;
6093 }
6094 } else {
6095 order->target = EXTRA_NONE;
6096 }
6097 } else {
6098 /* In pre-2.6 savegames, base_list and road_list were only saved
6099 * for those activities (and not e.g. pillaging) */
6100 if (base_unitstr && base_unitstr[j] != '?'
6101 && order->activity == ACTIVITY_BASE) {
6102 base_id = char2num(base_unitstr[j]);
6103
6104 if (base_id < 0 || base_id >= loading->base.size) {
6105 log_sg("Cannot find base %d for %s to build",
6106 base_id, unit_rule_name(punit));
6107 base_id = base_number(get_base_by_gui_type(BASE_GUI_FORTRESS,
6108 NULL, NULL));
6109 }
6110
6111 order->target
6112 = extra_number(base_extra_get(base_by_number(base_id)));
6113 } else if (road_unitstr && road_unitstr[j] != '?'
6114 && order->activity == ACTIVITY_GEN_ROAD) {
6115 road_id = char2num(road_unitstr[j]);
6116
6117 if (road_id < 0 || road_id >= loading->road.size) {
6118 log_sg("Cannot find road %d for %s to build",
6119 road_id, unit_rule_name(punit));
6120 road_id = 0;
6121 }
6122
6123 order->target
6124 = extra_number(road_extra_get(road_by_number(road_id)));
6125 } else {
6126 order->target = EXTRA_NONE;
6127 }
6128
6129 if (order->activity == ACTIVITY_OLD_ROAD) {
6130 order->activity = ACTIVITY_GEN_ROAD;
6131 order->target
6132 = extra_number(road_extra_get(road_by_number(road_idx)));
6133 } else if (order->activity == ACTIVITY_OLD_RAILROAD) {
6134 order->activity = ACTIVITY_GEN_ROAD;
6135 order->target
6136 = extra_number(road_extra_get(road_by_number(rail_idx)));
6137 }
6138 }
6139 }
6140 } else {
6141 punit->has_orders = FALSE;
6142 punit->orders.list = NULL;
6143
6144 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6145 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6146 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6147 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6148 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6149 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6150 (void) secfile_entry_lookup(loading->file, "%s.tgt_list", unitstr);
6151 }
6152 }
6153
6154 return TRUE;
6155 }
6156
6157 /*****************************************************************************
6158 Load the transport status of all units. This is seperated from the other
6159 code as all units must be known.
6160 *****************************************************************************/
sg_load_player_units_transport(struct loaddata * loading,struct player * plr)6161 static void sg_load_player_units_transport(struct loaddata *loading,
6162 struct player *plr)
6163 {
6164 int nunits, i, plrno = player_number(plr);
6165
6166 /* Check status and return if not OK (sg_success != TRUE). */
6167 sg_check_ret();
6168
6169 /* Recheck the number of units for the player. This is a copied from
6170 * sg_load_player_units(). */
6171 sg_failure_ret(secfile_lookup_int(loading->file, &nunits,
6172 "player%d.nunits", plrno),
6173 "%s", secfile_error());
6174 if (!plr->is_alive && nunits > 0) {
6175 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6176 nunits = 0; /* Some old savegames may be buggy. */
6177 }
6178
6179 for (i = 0; i < nunits; i++) {
6180 int id_unit, id_trans;
6181 struct unit *punit, *ptrans;
6182
6183 id_unit = secfile_lookup_int_default(loading->file, -1,
6184 "player%d.u%d.id",
6185 plrno, i);
6186 punit = player_unit_by_number(plr, id_unit);
6187 fc_assert_action(punit != NULL, continue);
6188
6189 id_trans = secfile_lookup_int_default(loading->file, -1,
6190 "player%d.u%d.transported_by",
6191 plrno, i);
6192 if (id_trans == -1) {
6193 /* Not transported. */
6194 continue;
6195 }
6196
6197 ptrans = game_unit_by_number(id_trans);
6198 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6199
6200 if (ptrans) {
6201 bool load_success = unit_transport_load(punit, ptrans, TRUE);
6202
6203 fc_assert_action(load_success == TRUE, continue);
6204 }
6205 }
6206 }
6207
6208 /****************************************************************************
6209 Save unit data
6210 ****************************************************************************/
sg_save_player_units(struct savedata * saving,struct player * plr)6211 static void sg_save_player_units(struct savedata *saving,
6212 struct player *plr)
6213 {
6214 int i = 0;
6215
6216 /* Check status and return if not OK (sg_success != TRUE). */
6217 sg_check_ret();
6218
6219 secfile_insert_int(saving->file, unit_list_size(plr->units),
6220 "player%d.nunits", player_number(plr));
6221
6222 unit_list_iterate(plr->units, punit) {
6223 char buf[32];
6224 char dirbuf[2] = " ";
6225 int nat_x, nat_y;
6226
6227 fc_snprintf(buf, sizeof(buf), "player%d.u%d", player_number(plr), i);
6228 dirbuf[0] = dir2char(punit->facing);
6229 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6230
6231 index_to_native_pos(&nat_x, &nat_y, tile_index(unit_tile(punit)));
6232 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6233 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6234
6235 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6236 if (game.info.citizen_nationality) {
6237 secfile_insert_int(saving->file, player_number(unit_nationality(punit)),
6238 "%s.nationality", buf);
6239 }
6240 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6241 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6242 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6243 secfile_insert_str(saving->file, unit_rule_name(punit),
6244 "%s.type_by_name", buf);
6245
6246 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6247 secfile_insert_int(saving->file, punit->activity_count,
6248 "%s.activity_count", buf);
6249 if (punit->activity_target == NULL) {
6250 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6251 } else {
6252 secfile_insert_int(saving->file, extra_index(punit->activity_target),
6253 "%s.activity_tgt", buf);
6254 }
6255
6256 secfile_insert_int(saving->file, punit->changed_from,
6257 "%s.changed_from", buf);
6258 secfile_insert_int(saving->file, punit->changed_from_count,
6259 "%s.changed_from_count", buf);
6260 if (punit->changed_from_target == NULL) {
6261 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6262 } else {
6263 secfile_insert_int(saving->file, extra_index(punit->changed_from_target),
6264 "%s.changed_from_tgt", buf);
6265 }
6266
6267 secfile_insert_bool(saving->file, punit->done_moving,
6268 "%s.done_moving", buf);
6269 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6270 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6271 secfile_insert_int(saving->file, punit->server.birth_turn,
6272 "%s.born", buf);
6273 secfile_insert_int(saving->file, punit->battlegroup,
6274 "%s.battlegroup", buf);
6275
6276 if (punit->goto_tile) {
6277 index_to_native_pos(&nat_x, &nat_y, tile_index(punit->goto_tile));
6278 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6279 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6280 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6281 } else {
6282 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6283 /* Set this values to allow saving it as table. */
6284 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6285 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6286 }
6287
6288 secfile_insert_bool(saving->file, punit->ai_controlled,
6289 "%s.ai", buf);
6290
6291 /* Save AI data of the unit. */
6292 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6293
6294 secfile_insert_int(saving->file, punit->server.ord_map,
6295 "%s.ord_map", buf);
6296 secfile_insert_int(saving->file, punit->server.ord_city,
6297 "%s.ord_city", buf);
6298 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6299 secfile_insert_bool(saving->file, punit->paradropped,
6300 "%s.paradropped", buf);
6301 secfile_insert_int(saving->file, unit_transport_get(punit)
6302 ? unit_transport_get(punit)->id : -1,
6303 "%s.transported_by", buf);
6304
6305 secfile_insert_enum(saving->file, punit->action_decision_want,
6306 action_decision, "%s.action_decision_want", buf);
6307
6308 /* Stored as tile rather than direction to make sure the target tile is
6309 * sane. */
6310 if (punit->action_decision_tile) {
6311 index_to_native_pos(&nat_x, &nat_y,
6312 tile_index(punit->action_decision_tile));
6313 secfile_insert_int(saving->file, nat_x,
6314 "%s.action_decision_tile_x", buf);
6315 secfile_insert_int(saving->file, nat_y,
6316 "%s.action_decision_tile_y", buf);
6317 } else {
6318 /* Dummy values to get tabular format. */
6319 secfile_insert_int(saving->file, -1,
6320 "%s.action_decision_tile_x", buf);
6321 secfile_insert_int(saving->file, -1,
6322 "%s.action_decision_tile_y", buf);
6323 }
6324
6325 if (punit->has_orders) {
6326 int len = punit->orders.length, j;
6327 char orders_buf[len + 1], dir_buf[len + 1];
6328 char act_buf[len + 1], tgt_buf[len + 1];
6329
6330 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6331 secfile_insert_int(saving->file, punit->orders.index,
6332 "%s.orders_index", buf);
6333 secfile_insert_bool(saving->file, punit->orders.repeat,
6334 "%s.orders_repeat", buf);
6335 secfile_insert_bool(saving->file, punit->orders.vigilant,
6336 "%s.orders_vigilant", buf);
6337
6338 for (j = 0; j < len; j++) {
6339 orders_buf[j] = order2char(punit->orders.list[j].order);
6340 dir_buf[j] = '?';
6341 act_buf[j] = '?';
6342 tgt_buf[j] = '?';
6343 switch (punit->orders.list[j].order) {
6344 case ORDER_MOVE:
6345 case ORDER_ACTION_MOVE:
6346 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6347 break;
6348 case ORDER_ACTIVITY:
6349 tgt_buf[j] = num2char(punit->orders.list[j].target);
6350 act_buf[j] = activity2char(punit->orders.list[j].activity);
6351 break;
6352 case ORDER_FULL_MP:
6353 case ORDER_BUILD_CITY:
6354 case ORDER_DISBAND:
6355 case ORDER_BUILD_WONDER:
6356 case ORDER_TRADE_ROUTE:
6357 case ORDER_HOMECITY:
6358 case ORDER_LAST:
6359 break;
6360 }
6361 }
6362 orders_buf[len] = dir_buf[len] = act_buf[len] = tgt_buf[len] = '\0';
6363
6364 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6365 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6366 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6367 secfile_insert_str(saving->file, tgt_buf, "%s.tgt_list", buf);
6368 } else {
6369 /* Put all the same fields into the savegame - otherwise the
6370 * registry code can't correctly use a tabular format and the
6371 * savegame will be bigger. */
6372 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6373 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6374 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6375 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6376 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6377 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6378 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6379 secfile_insert_str(saving->file, "-", "%s.tgt_list", buf);
6380 }
6381
6382 i++;
6383 } unit_list_iterate_end;
6384 }
6385
6386 /****************************************************************************
6387 Load player (client) attributes data
6388 ****************************************************************************/
sg_load_player_attributes(struct loaddata * loading,struct player * plr)6389 static void sg_load_player_attributes(struct loaddata *loading,
6390 struct player *plr)
6391 {
6392 int plrno = player_number(plr);
6393
6394 /* Check status and return if not OK (sg_success != TRUE). */
6395 sg_check_ret();
6396
6397 /* Toss any existing attribute_block (should not exist) */
6398 if (plr->attribute_block.data) {
6399 free(plr->attribute_block.data);
6400 plr->attribute_block.data = NULL;
6401 }
6402
6403 /* This is a big heap of opaque data for the client, check everything! */
6404 plr->attribute_block.length = secfile_lookup_int_default(
6405 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6406
6407 if (0 > plr->attribute_block.length) {
6408 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6409 plr->attribute_block.length);
6410 plr->attribute_block.length = 0;
6411 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6412 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6413 plrno, plr->attribute_block.length, MAX_ATTRIBUTE_BLOCK);
6414 plr->attribute_block.length = 0;
6415 } else if (0 < plr->attribute_block.length) {
6416 int part_nr, parts;
6417 size_t actual_length;
6418 int quoted_length;
6419 char *quoted;
6420
6421 sg_failure_ret(
6422 secfile_lookup_int(loading->file, "ed_length,
6423 "player%d.attribute_v2_block_length_quoted",
6424 plrno), "%s", secfile_error());
6425 sg_failure_ret(
6426 secfile_lookup_int(loading->file, &parts,
6427 "player%d.attribute_v2_block_parts", plrno),
6428 "%s", secfile_error());
6429
6430 quoted = fc_malloc(quoted_length + 1);
6431 quoted[0] = '\0';
6432 plr->attribute_block.data = fc_malloc(plr->attribute_block.length);
6433 for (part_nr = 0; part_nr < parts; part_nr++) {
6434 const char *current =
6435 secfile_lookup_str(loading->file,
6436 "player%d.attribute_v2_block_data.part%d",
6437 plrno, part_nr);
6438 if (!current) {
6439 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6440 break;
6441 }
6442 log_debug("attribute_v2_block_length_quoted=%lu have=%lu part=%lu",
6443 (unsigned long) quoted_length,
6444 (unsigned long) strlen(quoted),
6445 (unsigned long) strlen(current));
6446 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6447 strcat(quoted, current);
6448 }
6449 fc_assert_msg(quoted_length == strlen(quoted),
6450 "attribute_v2_block_length_quoted=%lu actual=%lu",
6451 (unsigned long) quoted_length,
6452 (unsigned long) strlen(quoted));
6453
6454 actual_length =
6455 unquote_block(quoted,
6456 plr->attribute_block.data,
6457 plr->attribute_block.length);
6458 fc_assert(actual_length == plr->attribute_block.length);
6459 free(quoted);
6460 }
6461 }
6462
6463 /****************************************************************************
6464 Save player (client) attributes data.
6465 ****************************************************************************/
sg_save_player_attributes(struct savedata * saving,struct player * plr)6466 static void sg_save_player_attributes(struct savedata *saving,
6467 struct player *plr)
6468 {
6469 int plrno = player_number(plr);
6470
6471 /* Check status and return if not OK (sg_success != TRUE). */
6472 sg_check_ret();
6473
6474 /* This is a big heap of opaque data from the client. Although the binary
6475 * format is not user editable, keep the lines short enough for debugging,
6476 * and hope that data compression will keep the file a reasonable size.
6477 * Note that the "quoted" format is a multiple of 3.
6478 */
6479 #define PART_SIZE (3*256)
6480 #define PART_ADJUST (3)
6481 if (plr->attribute_block.data) {
6482 char part[PART_SIZE + PART_ADJUST];
6483 int parts;
6484 int current_part_nr;
6485 char *quoted = quote_block(plr->attribute_block.data,
6486 plr->attribute_block.length);
6487 char *quoted_at = strchr(quoted, ':');
6488 size_t bytes_left = strlen(quoted);
6489 size_t bytes_at_colon = 1 + (quoted_at - quoted);
6490 size_t bytes_adjust = bytes_at_colon % PART_ADJUST;
6491
6492 secfile_insert_int(saving->file, plr->attribute_block.length,
6493 "player%d.attribute_v2_block_length", plrno);
6494 secfile_insert_int(saving->file, bytes_left,
6495 "player%d.attribute_v2_block_length_quoted", plrno);
6496
6497 /* Try to wring some compression efficiencies out of the "quoted" format.
6498 * The first line has a variable length decimal, mis-aligning triples.
6499 */
6500 if ((bytes_left - bytes_adjust) > PART_SIZE) {
6501 /* first line can be longer */
6502 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
6503 } else {
6504 parts = 1;
6505 }
6506
6507 secfile_insert_int(saving->file, parts,
6508 "player%d.attribute_v2_block_parts", plrno);
6509
6510 if (parts > 1) {
6511 size_t size_of_current_part = PART_SIZE + bytes_adjust;
6512
6513 /* first line can be longer */
6514 memcpy(part, quoted, size_of_current_part);
6515 part[size_of_current_part] = '\0';
6516 secfile_insert_str(saving->file, part,
6517 "player%d.attribute_v2_block_data.part%d",
6518 plrno, 0);
6519 bytes_left -= size_of_current_part;
6520 quoted_at = "ed[size_of_current_part];
6521 current_part_nr = 1;
6522 } else {
6523 quoted_at = quoted;
6524 current_part_nr = 0;
6525 }
6526
6527 for (; current_part_nr < parts; current_part_nr++) {
6528 size_t size_of_current_part = MIN(bytes_left, PART_SIZE);
6529
6530 memcpy(part, quoted_at, size_of_current_part);
6531 part[size_of_current_part] = '\0';
6532 secfile_insert_str(saving->file, part,
6533 "player%d.attribute_v2_block_data.part%d",
6534 plrno,
6535 current_part_nr);
6536 bytes_left -= size_of_current_part;
6537 quoted_at = "ed_at[size_of_current_part];
6538 }
6539 fc_assert(bytes_left == 0);
6540 free(quoted);
6541 }
6542 #undef PART_ADJUST
6543 #undef PART_SIZE
6544 }
6545
6546 /****************************************************************************
6547 Load vision data
6548 ****************************************************************************/
sg_load_player_vision(struct loaddata * loading,struct player * plr)6549 static void sg_load_player_vision(struct loaddata *loading,
6550 struct player *plr)
6551 {
6552 int plrno = player_number(plr);
6553 int total_ncities =
6554 secfile_lookup_int_default(loading->file, -1,
6555 "player%d.dc_total", plrno);
6556 int i;
6557
6558 /* Check status and return if not OK (sg_success != TRUE). */
6559 sg_check_ret();
6560
6561 if (!plr->is_alive) {
6562 if (game.server.revealmap & REVEAL_MAP_DEAD
6563 && player_list_size(team_members(plr->team)) == 1) {
6564 /* Reveal all for dead players. */
6565 map_know_and_see_all(plr);
6566 }
6567 }
6568
6569 if (!plr->is_alive
6570 || -1 == total_ncities
6571 || FALSE == game.info.fogofwar
6572 || !secfile_lookup_bool_default(loading->file, TRUE,
6573 "game.save_private_map")) {
6574 /* We have:
6575 * - a dead player;
6576 * - fogged cities are not saved for any reason;
6577 * - a savegame with fog of war turned off;
6578 * - or game.save_private_map is not set to FALSE in the scenario /
6579 * savegame. The players private knowledge is set to be what he could
6580 * see without fog of war. */
6581 whole_map_iterate(ptile) {
6582 if (map_is_known(ptile, plr)) {
6583 struct city *pcity = tile_city(ptile);
6584
6585 update_player_tile_last_seen(plr, ptile);
6586 update_player_tile_knowledge(plr, ptile);
6587
6588 if (NULL != pcity) {
6589 update_dumb_city(plr, pcity);
6590 }
6591 }
6592 } whole_map_iterate_end;
6593
6594 /* Nothing more to do; */
6595 return;
6596 }
6597
6598 /* Load player map (terrain). */
6599 LOAD_MAP_CHAR(ch, ptile,
6600 map_get_player_tile(ptile, plr)->terrain
6601 = char2terrain(ch), loading->file,
6602 "player%d.map_t%04d", plrno);
6603
6604 /* Load player map (resources). */
6605 LOAD_MAP_CHAR(ch, ptile,
6606 map_get_player_tile(ptile, plr)->resource
6607 = char2resource(ch), loading->file,
6608 "player%d.map_res%04d", plrno);
6609
6610 if (loading->version >= 30) {
6611 /* 2.6.0 or newer */
6612
6613 /* Load player map (extras). */
6614 halfbyte_iterate_extras(j, loading->extra.size) {
6615 LOAD_MAP_CHAR(ch, ptile,
6616 sg_extras_set(&map_get_player_tile(ptile, plr)->extras,
6617 ch, loading->extra.order + 4 * j),
6618 loading->file, "player%d.map_e%02d_%04d", plrno, j);
6619 } halfbyte_iterate_extras_end;
6620 } else {
6621 /* Load player map (specials). */
6622 halfbyte_iterate_special(j, loading->special.size) {
6623 LOAD_MAP_CHAR(ch, ptile,
6624 sg_special_set(ptile, &map_get_player_tile(ptile, plr)->extras,
6625 ch, loading->special.order + 4 * j, FALSE),
6626 loading->file, "player%d.map_spe%02d_%04d", plrno, j);
6627 } halfbyte_iterate_special_end;
6628
6629 /* Load player map (bases). */
6630 halfbyte_iterate_bases(j, loading->base.size) {
6631 LOAD_MAP_CHAR(ch, ptile,
6632 sg_bases_set(&map_get_player_tile(ptile, plr)->extras,
6633 ch, loading->base.order + 4 * j),
6634 loading->file, "player%d.map_b%02d_%04d", plrno, j);
6635 } halfbyte_iterate_bases_end;
6636
6637 /* Load player map (roads). */
6638 if (loading->version >= 20) {
6639 /* 2.5.0 or newer */
6640 halfbyte_iterate_roads(j, loading->road.size) {
6641 LOAD_MAP_CHAR(ch, ptile,
6642 sg_roads_set(&map_get_player_tile(ptile, plr)->extras,
6643 ch, loading->road.order + 4 * j),
6644 loading->file, "player%d.map_r%02d_%04d", plrno, j);
6645 } halfbyte_iterate_roads_end;
6646 }
6647 }
6648
6649 if (game.server.foggedborders) {
6650 /* Load player map (border). */
6651 int x, y;
6652
6653 for (y = 0; y < game.map.ysize; y++) {
6654 const char *buffer
6655 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
6656 plrno, y);
6657 const char *buffer2
6658 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
6659 plrno, y);
6660 const char *ptr = buffer;
6661 const char *ptr2 = buffer2;
6662
6663 sg_failure_ret(NULL != buffer,
6664 "Savegame corrupt - map line %d not found.", y);
6665 for (x = 0; x < game.map.xsize; x++) {
6666 char token[TOKEN_SIZE];
6667 char token2[TOKEN_SIZE];
6668 int number;
6669 struct tile *ptile = native_pos_to_tile(x, y);
6670
6671 scanin(&ptr, ",", token, sizeof(token));
6672 sg_failure_ret('\0' != token[0],
6673 "Savegame corrupt - map size not correct.");
6674 if (strcmp(token, "-") == 0) {
6675 map_get_player_tile(ptile, plr)->owner = NULL;
6676 } else {
6677 sg_failure_ret(str_to_int(token, &number),
6678 "Savegame corrupt - got tile owner=%s in (%d, %d).",
6679 token, x, y);
6680 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
6681 }
6682
6683 if (loading->version >= 30) {
6684 scanin(&ptr2, ",", token2, sizeof(token2));
6685 sg_failure_ret('\0' != token2[0],
6686 "Savegame corrupt - map size not correct.");
6687 if (strcmp(token2, "-") == 0) {
6688 map_get_player_tile(ptile, plr)->extras_owner = NULL;
6689 } else {
6690 sg_failure_ret(str_to_int(token2, &number),
6691 "Savegame corrupt - got extras owner=%s in (%d, %d).",
6692 token, x, y);
6693 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
6694 }
6695 } else {
6696 map_get_player_tile(ptile, plr)->extras_owner
6697 = map_get_player_tile(ptile, plr)->owner;
6698 }
6699 }
6700 }
6701 }
6702
6703 /* Load player map (update time). */
6704 for (i = 0; i < 4; i++) {
6705 /* put 4-bit segments of 16-bit "updated" field */
6706 if (i == 0) {
6707 LOAD_MAP_CHAR(ch, ptile,
6708 map_get_player_tile(ptile, plr)->last_updated
6709 = ascii_hex2bin(ch, i),
6710 loading->file, "player%d.map_u%02d_%04d", plrno, i);
6711 } else {
6712 LOAD_MAP_CHAR(ch, ptile,
6713 map_get_player_tile(ptile, plr)->last_updated
6714 |= ascii_hex2bin(ch, i),
6715 loading->file, "player%d.map_u%02d_%04d", plrno, i);
6716 }
6717 }
6718
6719 /* Load player map known cities. */
6720 for (i = 0; i < total_ncities; i++) {
6721 struct vision_site *pdcity;
6722 char buf[32];
6723 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
6724
6725 pdcity = vision_site_new(0, NULL, NULL);
6726 if (sg_load_player_vision_city(loading, plr, pdcity, buf)) {
6727 change_playertile_site(map_get_player_tile(pdcity->location, plr),
6728 pdcity);
6729 identity_number_reserve(pdcity->identity);
6730 } else {
6731 /* Error loading the data. */
6732 log_sg("Skipping seen city %d for player %d.", i, plrno);
6733 if (pdcity != NULL) {
6734 vision_site_destroy(pdcity);
6735 }
6736 }
6737 }
6738
6739 /* Repair inconsistent player maps. */
6740 whole_map_iterate(ptile) {
6741 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
6742 struct city *pcity = tile_city(ptile);
6743
6744 update_player_tile_knowledge(plr, ptile);
6745 reality_check_city(plr, ptile);
6746
6747 if (NULL != pcity) {
6748 update_dumb_city(plr, pcity);
6749 }
6750 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
6751 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
6752 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
6753
6754 plrtile->owner = tile_owner(ptile);
6755 }
6756 } whole_map_iterate_end;
6757 }
6758
6759 /****************************************************************************
6760 Load data for one seen city. sg_save_player_vision_city() is not defined.
6761 ****************************************************************************/
sg_load_player_vision_city(struct loaddata * loading,struct player * plr,struct vision_site * pdcity,const char * citystr)6762 static bool sg_load_player_vision_city(struct loaddata *loading,
6763 struct player *plr,
6764 struct vision_site *pdcity,
6765 const char *citystr)
6766 {
6767 const char *string;
6768 int i, id, size;
6769 citizens city_size;
6770 int nat_x, nat_y;
6771 const char *stylename;
6772
6773 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x",
6774 citystr),
6775 FALSE, "%s", secfile_error());
6776 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y",
6777 citystr),
6778 FALSE, "%s", secfile_error());
6779 pdcity->location = native_pos_to_tile(nat_x, nat_y);
6780 sg_warn_ret_val(NULL != pdcity->location, FALSE,
6781 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
6782
6783 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
6784 citystr),
6785 FALSE, "%s", secfile_error());
6786 pdcity->owner = player_by_number(id);
6787 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
6788 "%s has invalid owner (%d); skipping.", citystr, id);
6789
6790 sg_warn_ret_val(secfile_lookup_int(loading->file, &pdcity->identity,
6791 "%s.id", citystr),
6792 FALSE, "%s", secfile_error());
6793 sg_warn_ret_val(IDENTITY_NUMBER_ZERO < pdcity->identity, FALSE,
6794 "%s has invalid id (%d); skipping.", citystr, id);
6795
6796 sg_warn_ret_val(secfile_lookup_int(loading->file, &size,
6797 "%s.size", citystr),
6798 FALSE, "%s", secfile_error());
6799 city_size = (citizens)size; /* set the correct type */
6800 sg_warn_ret_val(size == (int)city_size, FALSE,
6801 "Invalid city size: %d; set to %d.", size, city_size);
6802 vision_site_size_set(pdcity, city_size);
6803
6804 /* Initialise list of improvements */
6805 BV_CLR_ALL(pdcity->improvements);
6806 string = secfile_lookup_str(loading->file, "%s.improvements", citystr);
6807 sg_warn_ret_val(string != NULL, FALSE, "%s", secfile_error());
6808 sg_warn_ret_val(strlen(string) == loading->improvement.size, FALSE,
6809 "Invalid length of '%s.improvements' (%lu ~= %lu).",
6810 citystr, (unsigned long) strlen(string),
6811 (unsigned long) loading->improvement.size);
6812 for (i = 0; i < loading->improvement.size; i++) {
6813 sg_warn_ret_val(string[i] == '1' || string[i] == '0', FALSE,
6814 "Undefined value '%c' within '%s.improvements'.",
6815 string[i], citystr)
6816
6817 if (string[i] == '1') {
6818 struct impr_type *pimprove =
6819 improvement_by_rule_name(loading->improvement.order[i]);
6820 if (pimprove) {
6821 BV_SET(pdcity->improvements, improvement_index(pimprove));
6822 }
6823 }
6824 }
6825
6826 /* Use the section as backup name. */
6827 sz_strlcpy(pdcity->name, secfile_lookup_str_default(loading->file, citystr,
6828 "%s.name", citystr));
6829
6830 pdcity->occupied = secfile_lookup_bool_default(loading->file, FALSE,
6831 "%s.occupied", citystr);
6832 pdcity->walls = secfile_lookup_bool_default(loading->file, FALSE,
6833 "%s.walls", citystr);
6834 pdcity->happy = secfile_lookup_bool_default(loading->file, FALSE,
6835 "%s.happy", citystr);
6836 pdcity->unhappy = secfile_lookup_bool_default(loading->file, FALSE,
6837 "%s.unhappy", citystr);
6838 stylename = secfile_lookup_str_default(loading->file, NULL,
6839 "%s.style", citystr);
6840 if (stylename != NULL) {
6841 pdcity->style = city_style_by_rule_name(stylename);
6842 } else {
6843 pdcity->style = 0;
6844 }
6845 if (pdcity->style < 0) {
6846 pdcity->style = 0;
6847 }
6848
6849 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
6850 "%s.city_image", citystr);
6851
6852 return TRUE;
6853 }
6854
6855 /****************************************************************************
6856 Save vision data
6857 ****************************************************************************/
sg_save_player_vision(struct savedata * saving,struct player * plr)6858 static void sg_save_player_vision(struct savedata *saving,
6859 struct player *plr)
6860 {
6861 int i, plrno = player_number(plr);
6862
6863 /* Check status and return if not OK (sg_success != TRUE). */
6864 sg_check_ret();
6865
6866 if (!game.info.fogofwar || !game.server.save_options.save_private_map) {
6867 /* The player can see all, there's no reason to save the private map. */
6868 return;
6869 }
6870
6871 if (!plr->is_alive) {
6872 /* Nothing to save. */
6873 return;
6874 }
6875
6876 /* Save the map (terrain). */
6877 SAVE_MAP_CHAR(ptile,
6878 terrain2char(map_get_player_tile(ptile, plr)->terrain),
6879 saving->file, "player%d.map_t%04d", plrno);
6880
6881 /* Save the map (resources). */
6882 SAVE_MAP_CHAR(ptile,
6883 resource2char(map_get_player_tile(ptile, plr)->resource),
6884 saving->file, "player%d.map_res%04d", plrno);
6885
6886 if (game.server.foggedborders) {
6887 /* Save the map (borders). */
6888 int x, y;
6889
6890 for (y = 0; y < game.map.ysize; y++) {
6891 char line[game.map.xsize * TOKEN_SIZE];
6892
6893 line[0] = '\0';
6894 for (x = 0; x < game.map.xsize; x++) {
6895 char token[TOKEN_SIZE];
6896 struct tile *ptile = native_pos_to_tile(x, y);
6897 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
6898
6899 if (plrtile == NULL || plrtile->owner == NULL) {
6900 strcpy(token, "-");
6901 } else {
6902 fc_snprintf(token, sizeof(token), "%d",
6903 player_number(plrtile->owner));
6904 }
6905 strcat(line, token);
6906 if (x < game.map.xsize) {
6907 strcat(line, ",");
6908 }
6909 }
6910 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
6911 plrno, y);
6912 }
6913
6914 for (y = 0; y < game.map.ysize; y++) {
6915 char line[game.map.xsize * TOKEN_SIZE];
6916
6917 line[0] = '\0';
6918 for (x = 0; x < game.map.xsize; x++) {
6919 char token[TOKEN_SIZE];
6920 struct tile *ptile = native_pos_to_tile(x, y);
6921 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
6922
6923 if (plrtile == NULL || plrtile->extras_owner == NULL) {
6924 strcpy(token, "-");
6925 } else {
6926 fc_snprintf(token, sizeof(token), "%d",
6927 player_number(plrtile->extras_owner));
6928 }
6929 strcat(line, token);
6930 if (x < game.map.xsize) {
6931 strcat(line, ",");
6932 }
6933 }
6934 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
6935 plrno, y);
6936 }
6937 }
6938
6939 /* Save the map (extras). */
6940 halfbyte_iterate_extras(j, game.control.num_extra_types) {
6941 int mod[4];
6942 int l;
6943
6944 for (l = 0; l < 4; l++) {
6945 if (4 * j + 1 > game.control.num_extra_types) {
6946 mod[l] = -1;
6947 } else {
6948 mod[l] = 4 * j + l;
6949 }
6950 }
6951
6952 SAVE_MAP_CHAR(ptile,
6953 sg_extras_get(map_get_player_tile(ptile, plr)->extras, mod),
6954 saving->file, "player%d.map_e%02d_%04d", plrno, j);
6955 } halfbyte_iterate_extras_end;
6956
6957 /* Save the map (update time). */
6958 for (i = 0; i < 4; i++) {
6959 /* put 4-bit segments of 16-bit "updated" field */
6960 SAVE_MAP_CHAR(ptile,
6961 bin2ascii_hex(
6962 map_get_player_tile(ptile, plr)->last_updated, i),
6963 saving->file, "player%d.map_u%02d_%04d", plrno, i);
6964 }
6965
6966 /* Save known cities. */
6967 i = 0;
6968 whole_map_iterate(ptile) {
6969 struct vision_site *pdcity = map_get_player_city(ptile, plr);
6970 char impr_buf[MAX_NUM_ITEMS + 1];
6971 char buf[32];
6972
6973 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
6974
6975 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
6976 int nat_x, nat_y;
6977
6978 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
6979 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6980 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6981
6982 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
6983 secfile_insert_int(saving->file, player_number(vision_site_owner(pdcity)),
6984 "%s.owner", buf);
6985
6986 secfile_insert_int(saving->file, vision_site_size_get(pdcity),
6987 "%s.size", buf);
6988 secfile_insert_bool(saving->file, pdcity->occupied,
6989 "%s.occupied", buf);
6990 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
6991 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
6992 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
6993 secfile_insert_str(saving->file, city_style_rule_name(pdcity->style),
6994 "%s.style", buf);
6995 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
6996
6997 /* Save improvement list as bitvector. Note that improvement order
6998 * is saved in savefile.improvement.order. */
6999 improvement_iterate(pimprove) {
7000 impr_buf[improvement_index(pimprove)]
7001 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7002 ? '1' : '0';
7003 } improvement_iterate_end;
7004 impr_buf[improvement_count()] = '\0';
7005 sg_failure_ret(strlen(impr_buf) < sizeof(impr_buf),
7006 "Invalid size of the improvement vector (%s.improvements: "
7007 "%lu < %lu).", buf, (long unsigned int) strlen(impr_buf),
7008 (long unsigned int) sizeof(impr_buf));
7009 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7010 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7011
7012 i++;
7013 }
7014 } whole_map_iterate_end;
7015
7016 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7017 }
7018
7019 /* =======================================================================
7020 * Load / save the researches.
7021 * ======================================================================= */
7022
7023 /****************************************************************************
7024 Load '[research]'.
7025 ****************************************************************************/
sg_load_researches(struct loaddata * loading)7026 static void sg_load_researches(struct loaddata *loading)
7027 {
7028 struct research *presearch;
7029 int count;
7030 int number;
7031 const char *string;
7032 int i, j;
7033
7034 /* Check status and return if not OK (sg_success != TRUE). */
7035 sg_check_ret();
7036
7037 /* Initialize all researches. */
7038 researches_iterate(pinitres) {
7039 init_tech(pinitres, FALSE);
7040 } researches_iterate_end;
7041
7042 /* May be unsaved (e.g. scenario case). */
7043 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7044 for (i = 0; i < count; i++) {
7045 sg_failure_ret(secfile_lookup_int(loading->file, &number,
7046 "research.r%d.number", i),
7047 "%s", secfile_error());
7048 presearch = research_by_number(number);
7049 sg_failure_ret(presearch != NULL,
7050 "Invalid research number %d in 'research.r%d.number'",
7051 number, i);
7052
7053 presearch->tech_goal = technology_load(loading->file,
7054 "research.r%d.goal", i);
7055 sg_failure_ret(secfile_lookup_int(loading->file,
7056 &presearch->techs_researched,
7057 "research.r%d.techs", i),
7058 "%s", secfile_error());
7059 sg_failure_ret(secfile_lookup_int(loading->file,
7060 &presearch->future_tech,
7061 "research.r%d.futuretech", i),
7062 "%s", secfile_error());
7063 sg_failure_ret(secfile_lookup_int(loading->file,
7064 &presearch->bulbs_researched,
7065 "research.r%d.bulbs", i),
7066 "%s", secfile_error());
7067 sg_failure_ret(secfile_lookup_int(loading->file,
7068 &presearch->bulbs_researching_saved,
7069 "research.r%d.bulbs_before", i),
7070 "%s", secfile_error());
7071 presearch->researching_saved = technology_load(loading->file,
7072 "research.r%d.saved", i);
7073 presearch->researching = technology_load(loading->file,
7074 "research.r%d.now", i);
7075 sg_failure_ret(secfile_lookup_bool(loading->file,
7076 &presearch->got_tech,
7077 "research.r%d.got_tech", i),
7078 "%s", secfile_error());
7079
7080 string = secfile_lookup_str(loading->file, "research.r%d.done",
7081 i);
7082 sg_failure_ret(string != NULL, "%s", secfile_error());
7083 sg_failure_ret(strlen(string) == loading->technology.size,
7084 "Invalid length of 'research.r%d.done' (%lu ~= %lu).",
7085 i, (unsigned long) strlen(string),
7086 (unsigned long) loading->technology.size);
7087 for (j = 0; j < loading->technology.size; j++) {
7088 sg_failure_ret(string[j] == '1' || string[j] == '0',
7089 "Undefined value '%c' within 'research.r%d.done'.",
7090 string[j], i);
7091
7092 if (string[j] == '1') {
7093 struct advance *padvance =
7094 advance_by_rule_name(loading->technology.order[j]);
7095
7096 if (padvance) {
7097 research_invention_set(presearch, advance_number(padvance),
7098 TECH_KNOWN);
7099 }
7100 }
7101 }
7102 }
7103
7104 /* In case of tech_leakage, we can update research only after all the
7105 * researches have been loaded */
7106 researches_iterate(pupres) {
7107 research_update(pupres);
7108 } researches_iterate_end;
7109 }
7110
7111 /****************************************************************************
7112 Save '[research]'.
7113 ****************************************************************************/
sg_save_researches(struct savedata * saving)7114 static void sg_save_researches(struct savedata *saving)
7115 {
7116 char invs[A_LAST];
7117 int i = 0;
7118
7119 /* Check status and return if not OK (sg_success != TRUE). */
7120 sg_check_ret();
7121
7122 if (saving->save_players) {
7123 researches_iterate(presearch) {
7124 secfile_insert_int(saving->file, research_number(presearch),
7125 "research.r%d.number", i);
7126 technology_save(saving->file, "research.r%d.goal",
7127 i, presearch->tech_goal);
7128 secfile_insert_int(saving->file, presearch->techs_researched,
7129 "research.r%d.techs", i);
7130 secfile_insert_int(saving->file, presearch->future_tech,
7131 "research.r%d.futuretech", i);
7132 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7133 "research.r%d.bulbs_before", i);
7134 technology_save(saving->file, "research.r%d.saved",
7135 i, presearch->researching_saved);
7136 secfile_insert_int(saving->file, presearch->bulbs_researched,
7137 "research.r%d.bulbs", i);
7138 technology_save(saving->file, "research.r%d.now",
7139 i, presearch->researching);
7140 secfile_insert_bool(saving->file, presearch->got_tech,
7141 "research.r%d.got_tech", i);
7142 /* Save technology lists as bytevector. Note that technology order is
7143 * saved in savefile.technology.order */
7144 advance_index_iterate(A_NONE, tech_id) {
7145 invs[tech_id] = (research_invention_state(presearch, tech_id)
7146 == TECH_KNOWN ? '1' : '0');
7147 } advance_index_iterate_end;
7148 invs[game.control.num_tech_types] = '\0';
7149 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7150 i++;
7151 } researches_iterate_end;
7152 secfile_insert_int(saving->file, i, "research.count");
7153 }
7154 }
7155
7156 /* =======================================================================
7157 * Load / save the event cache. Should be the last thing to do.
7158 * ======================================================================= */
7159
7160 /****************************************************************************
7161 Load '[event_cache]'.
7162 ****************************************************************************/
sg_load_event_cache(struct loaddata * loading)7163 static void sg_load_event_cache(struct loaddata *loading)
7164 {
7165 /* Check status and return if not OK (sg_success != TRUE). */
7166 sg_check_ret();
7167
7168 event_cache_load(loading->file, "event_cache");
7169 }
7170
7171 /****************************************************************************
7172 Save '[event_cache]'.
7173 ****************************************************************************/
sg_save_event_cache(struct savedata * saving)7174 static void sg_save_event_cache(struct savedata *saving)
7175 {
7176 /* Check status and return if not OK (sg_success != TRUE). */
7177 sg_check_ret();
7178
7179 if (saving->scenario) {
7180 /* Do _not_ save events in a scenario. */
7181 return;
7182 }
7183
7184 event_cache_save(saving->file, "event_cache");
7185 }
7186
7187 /* =======================================================================
7188 * Load / save the open treaties
7189 * ======================================================================= */
7190
7191 /****************************************************************************
7192 Load '[treaty_xxx]'.
7193 ****************************************************************************/
sg_load_treaties(struct loaddata * loading)7194 static void sg_load_treaties(struct loaddata *loading)
7195 {
7196 int tidx;
7197 const char *plr0;
7198 struct treaty_list *treaties = get_all_treaties();
7199
7200 /* Check status and return if not OK (sg_success != TRUE). */
7201 sg_check_ret();
7202
7203 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7204 "treaty%d.plr0", tidx)) != NULL ;
7205 tidx++) {
7206 const char *plr1;
7207 const char *ct;
7208 int cidx;
7209 struct player *p0, *p1;
7210
7211 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7212
7213 p0 = player_by_name(plr0);
7214 p1 = player_by_name(plr1);
7215
7216 if (p0 == NULL || p1 == NULL) {
7217 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7218 } else {
7219 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7220
7221 init_treaty(ptreaty, p0, p1);
7222 treaty_list_prepend(treaties, ptreaty);
7223
7224 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7225 "treaty%d.clause%d.type",
7226 tidx, cidx)) != NULL ;
7227 cidx++ ) {
7228 enum clause_type type = clause_type_by_name(ct, fc_strcasecmp);
7229 const char *plrx;
7230
7231 if (!clause_type_is_valid(type)) {
7232 log_error("Invalid clause type \"%s\"", ct);
7233 } else {
7234 struct player *pgiver = NULL;
7235
7236 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7237 tidx, cidx);
7238
7239 if (!fc_strcasecmp(plrx, plr0)) {
7240 pgiver = p0;
7241 } else if (!fc_strcasecmp(plrx, plr1)) {
7242 pgiver = p1;
7243 } else {
7244 log_error("Clause giver %s is not participant of the treaty"
7245 "between %s and %s", plrx, plr0, plr1);
7246 }
7247
7248 if (pgiver != NULL) {
7249 int value;
7250
7251 value = secfile_lookup_int_default(loading->file, 0,
7252 "treaty%d.clause%d.value",
7253 tidx, cidx);
7254
7255 add_clause(ptreaty, pgiver, type, value);
7256 }
7257 }
7258
7259 /* These must be after clauses have been added so that acceptance
7260 * does not get cleared by what seems like changes to the treaty. */
7261 ptreaty->accept0 = secfile_lookup_bool_default(loading->file, FALSE,
7262 "treaty%d.accept0", tidx);
7263 ptreaty->accept1 = secfile_lookup_bool_default(loading->file, FALSE,
7264 "treaty%d.accept1", tidx);
7265 }
7266 }
7267 }
7268 }
7269
7270 /****************************************************************************
7271 Save '[treaty_xxx]'.
7272 ****************************************************************************/
sg_save_treaties(struct savedata * saving)7273 static void sg_save_treaties(struct savedata *saving)
7274 {
7275 struct treaty_list *treaties = get_all_treaties();
7276 int tidx = 0;
7277
7278 treaty_list_iterate(treaties, ptr) {
7279 char tpath[512];
7280 int cidx = 0;
7281
7282 fc_snprintf(tpath, sizeof(tpath), "treaty%d", tidx++);
7283
7284 secfile_insert_str(saving->file, player_name(ptr->plr0), "%s.plr0", tpath);
7285 secfile_insert_str(saving->file, player_name(ptr->plr1), "%s.plr1", tpath);
7286 secfile_insert_bool(saving->file, ptr->accept0, "%s.accept0", tpath);
7287 secfile_insert_bool(saving->file, ptr->accept1, "%s.accept1", tpath);
7288
7289 clause_list_iterate(ptr->clauses, pclaus) {
7290 char cpath[512];
7291
7292 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7293
7294 secfile_insert_str(saving->file, clause_type_name(pclaus->type), "%s.type", cpath);
7295 secfile_insert_str(saving->file, player_name(pclaus->from), "%s.from", cpath);
7296 secfile_insert_int(saving->file, pclaus->value, "%s.value", cpath);
7297 } clause_list_iterate_end;
7298 } treaty_list_iterate_end;
7299 }
7300
7301 /* =======================================================================
7302 * Load / save the history report
7303 * ======================================================================= */
7304
7305 /****************************************************************************
7306 Load '[history]'.
7307 ****************************************************************************/
sg_load_history(struct loaddata * loading)7308 static void sg_load_history(struct loaddata *loading)
7309 {
7310 struct history_report *hist = history_report_get();
7311 int turn;
7312
7313 /* Check status and return if not OK (sg_success != TRUE). */
7314 sg_check_ret();
7315
7316 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7317
7318 if (turn + 1 >= game.info.turn) {
7319 const char *str;
7320
7321 hist->turn = turn;
7322 str = secfile_lookup_str(loading->file, "history.title");
7323 sg_failure_ret(str != NULL, "%s", secfile_error());
7324 sz_strlcpy(hist->title, str);
7325 str = secfile_lookup_str(loading->file, "history.body");
7326 sg_failure_ret(str != NULL, "%s", secfile_error());
7327 sz_strlcpy(hist->body, str);
7328 }
7329 }
7330
7331 /****************************************************************************
7332 Save '[history]'.
7333 ****************************************************************************/
sg_save_history(struct savedata * saving)7334 static void sg_save_history(struct savedata *saving)
7335 {
7336 struct history_report *hist = history_report_get();
7337
7338 secfile_insert_int(saving->file, hist->turn, "history.turn");
7339
7340 if (hist->turn + 1 >= game.info.turn) {
7341 secfile_insert_str(saving->file, hist->title, "history.title");
7342 secfile_insert_str(saving->file, hist->body, "history.body");
7343 }
7344 }
7345
7346 /* =======================================================================
7347 * Load / save the mapimg definitions.
7348 * ======================================================================= */
7349
7350 /****************************************************************************
7351 Load '[mapimg]'.
7352 ****************************************************************************/
sg_load_mapimg(struct loaddata * loading)7353 static void sg_load_mapimg(struct loaddata *loading)
7354 {
7355 int mapdef_count, i;
7356
7357 /* Check status and return if not OK (sg_success != TRUE). */
7358 sg_check_ret();
7359
7360 /* Clear all defined map images. */
7361 while (mapimg_count() > 0) {
7362 mapimg_delete(0);
7363 }
7364
7365 mapdef_count = secfile_lookup_int_default(loading->file, 0,
7366 "mapimg.count");
7367 log_verbose("Saved map image definitions: %d.", mapdef_count);
7368
7369 if (0 >= mapdef_count) {
7370 return;
7371 }
7372
7373 for (i = 0; i < mapdef_count; i++) {
7374 const char *p;
7375
7376 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7377 if (NULL == p) {
7378 log_verbose("[Mapimg %4d] Missing definition.", i);
7379 continue;
7380 }
7381
7382 if (!mapimg_define(p, FALSE)) {
7383 log_error("Invalid map image definition %4d: %s.", i, p);
7384 }
7385
7386 log_verbose("Mapimg %4d loaded.", i);
7387 }
7388 }
7389
7390 /****************************************************************************
7391 Save '[mapimg]'.
7392 ****************************************************************************/
sg_save_mapimg(struct savedata * saving)7393 static void sg_save_mapimg(struct savedata *saving)
7394 {
7395 /* Check status and return if not OK (sg_success != TRUE). */
7396 sg_check_ret();
7397
7398 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7399 if (mapimg_count() > 0) {
7400 int i;
7401
7402 for (i = 0; i < mapimg_count(); i++) {
7403 char buf[MAX_LEN_MAPDEF];
7404
7405 mapimg_id2str(i, buf, sizeof(buf));
7406 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7407 }
7408 }
7409 }
7410
7411 /* =======================================================================
7412 * Sanity checks for loading / saving a game.
7413 * ======================================================================= */
7414
7415 /****************************************************************************
7416 Sanity check for loaded game.
7417 ****************************************************************************/
sg_load_sanitycheck(struct loaddata * loading)7418 static void sg_load_sanitycheck(struct loaddata *loading)
7419 {
7420 int players;
7421
7422 /* Check status and return if not OK (sg_success != TRUE). */
7423 sg_check_ret();
7424
7425 if (game.info.is_new_game) {
7426 /* Nothing to do for new games (or not started scenarios). */
7427 return;
7428 }
7429
7430 /* Old savegames may have maxplayers lower than current player count,
7431 * fix. */
7432 players = normal_player_count();
7433 if (game.server.max_players < players) {
7434 log_verbose("Max players lower than current players, fixing");
7435 game.server.max_players = players;
7436 }
7437
7438 /* Fix ferrying sanity */
7439 players_iterate(pplayer) {
7440 unit_list_iterate_safe(pplayer->units, punit) {
7441 if (!unit_transport_get(punit)
7442 && !can_unit_exist_at_tile(punit, unit_tile(punit))) {
7443 log_sg("Removing %s unferried %s in %s at (%d, %d)",
7444 nation_rule_name(nation_of_player(pplayer)),
7445 unit_rule_name(punit),
7446 terrain_rule_name(unit_tile(punit)->terrain),
7447 TILE_XY(unit_tile(punit)));
7448 bounce_unit(punit, TRUE);
7449 }
7450 } unit_list_iterate_safe_end;
7451 } players_iterate_end;
7452
7453 /* Fix stacking issues. We don't rely on the savegame preserving
7454 * alliance invariants (old savegames often did not) so if there are any
7455 * unallied units on the same tile we just bounce them. */
7456 players_iterate(pplayer) {
7457 players_iterate(aplayer) {
7458 resolve_unit_stacks(pplayer, aplayer, TRUE);
7459 } players_iterate_end;
7460
7461 /* Backward compatibility: if we had any open-ended orders (pillage)
7462 * in the savegame, assign specific targets now */
7463 unit_list_iterate(pplayer->units, punit) {
7464 unit_assign_specific_activity_target(punit,
7465 &punit->activity,
7466 &punit->activity_target);
7467 } unit_list_iterate_end;
7468 } players_iterate_end;
7469
7470 /* Recalculate the potential buildings for each city. Has caused some
7471 * problems with game random state.
7472 * This also changes the game state if you save the game directly after
7473 * loading it and compare the results. */
7474 players_iterate(pplayer) {
7475 bool saved_ai_control = pplayer->ai_controlled;
7476
7477 /* Recalculate for all players. */
7478 pplayer->ai_controlled = FALSE;
7479
7480 /* Building advisor needs data phase open in order to work */
7481 adv_data_phase_init(pplayer, FALSE);
7482 building_advisor(pplayer);
7483 /* Close data phase again so it can be opened again when game starts. */
7484 adv_data_phase_done(pplayer);
7485
7486 pplayer->ai_controlled = saved_ai_control;
7487 } players_iterate_end;
7488
7489 /* Prevent a buggy or intentionally crafted save game from crashing
7490 * Freeciv. See hrm Bug #887748 */
7491 players_iterate(pplayer) {
7492 city_list_iterate(pplayer->cities, pcity) {
7493 worker_task_list_iterate(pcity->task_reqs, ptask) {
7494 if (!worker_task_is_sane(ptask)) {
7495 log_error("[city id: %d] Bad worker task %d.",
7496 pcity->id, ptask->act);
7497 worker_task_list_remove(pcity->task_reqs, ptask);
7498 free(ptask);
7499 ptask = NULL;
7500 }
7501 } worker_task_list_iterate_end;
7502 } city_list_iterate_end;
7503 } players_iterate_end;
7504
7505 /* Check worked tiles map */
7506 #ifdef DEBUG
7507 if (loading->worked_tiles != NULL) {
7508 /* check the entire map for unused worked tiles */
7509 whole_map_iterate(ptile) {
7510 if (loading->worked_tiles[ptile->index] != -1) {
7511 log_error("[city id: %d] Unused worked tile at (%d, %d).",
7512 loading->worked_tiles[ptile->index], TILE_XY(ptile));
7513 }
7514 } whole_map_iterate_end;
7515 }
7516 #endif /* DEBUG */
7517
7518 /* Check researching technologies and goals. */
7519 researches_iterate(presearch) {
7520 if (presearch->researching != A_UNSET
7521 && !is_future_tech(presearch->researching)
7522 && (valid_advance_by_number(presearch->researching) == NULL
7523 || (research_invention_state(presearch, presearch->researching)
7524 != TECH_PREREQS_KNOWN))) {
7525 log_sg(_("%s had invalid researching technology."),
7526 research_name_translation(presearch));
7527 presearch->researching = A_UNSET;
7528 }
7529 if (presearch->tech_goal != A_UNSET
7530 && !is_future_tech(presearch->tech_goal)
7531 && (valid_advance_by_number(presearch->tech_goal) == NULL
7532 || !research_invention_reachable(presearch, presearch->tech_goal)
7533 || (research_invention_state(presearch, presearch->tech_goal)
7534 == TECH_KNOWN))) {
7535 log_sg(_("%s had invalid technology goal."),
7536 research_name_translation(presearch));
7537 presearch->tech_goal = A_UNSET;
7538 }
7539 } researches_iterate_end;
7540
7541 if (0 == strlen(server.game_identifier)
7542 || !is_base64url(server.game_identifier)) {
7543 /* This uses fc_rand(), so random state has to be initialized before. */
7544 randomize_base64url_string(server.game_identifier,
7545 sizeof(server.game_identifier));
7546 }
7547
7548 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
7549 players_iterate(pplayer) {
7550 int unique_count[U_LAST];
7551
7552 memset(unique_count, 0, sizeof(unique_count));
7553
7554 unit_list_iterate(pplayer->units, punit) {
7555 unique_count[utype_index(unit_type_get(punit))]++;
7556 } unit_list_iterate_end;
7557
7558 unit_type_iterate(ut) {
7559 if (unique_count[utype_index(ut)] > 1 && utype_has_flag(ut, UTYF_UNIQUE)) {
7560 log_sg(_("%s has multiple units of type %s though it should be possible "
7561 "to have only one."),
7562 player_name(pplayer), utype_name_translation(ut));
7563 }
7564 } unit_type_iterate_end;
7565 } players_iterate_end;
7566
7567 /* Restore game random state, just in case various initialization code
7568 * inexplicably altered the previously existing state. */
7569 if (!game.info.is_new_game) {
7570 fc_rand_set_state(loading->rstate);
7571
7572 if (loading->version < 30) {
7573 /* For older savegames we have to recalculate the score with current data,
7574 * instead of using beginning-of-turn saved scores. */
7575 players_iterate(pplayer) {
7576 calc_civ_score(pplayer);
7577 } players_iterate_end;
7578 }
7579 }
7580
7581 /* At the end do the default sanity checks. */
7582 sanity_check();
7583 }
7584
7585 /****************************************************************************
7586 Sanity check for saved game.
7587 ****************************************************************************/
sg_save_sanitycheck(struct savedata * saving)7588 static void sg_save_sanitycheck(struct savedata *saving)
7589 {
7590 /* Check status and return if not OK (sg_success != TRUE). */
7591 sg_check_ret();
7592 }
7593