Freeciv-3.4
Loading...
Searching...
No Matches
savecompat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "capability.h"
20#include "log.h"
21
22/* common */
23#include "map.h"
24#include "specialist.h"
25
26/* server */
27#include "aiiface.h"
28#include "plrhand.h"
29#include "setcompat.h"
30#include "settings.h"
31#include "unittools.h"
32
33#include "savecompat.h"
34
36
37static char *special_names[] =
38 {
39 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
40 "Fallout", nullptr
41 };
42
43/*
44 For each savefile format after 2.3.0, compatibility functions are defined
45 which translate secfile structures from previous version to that version;
46 all necessary compat functions are called in order to
47 translate between the file and current version. See sg_load_compat().
48
49 The integer version ID should be increased every time the format is changed.
50 If the change is not backwards compatible, please state the changes in the
51 following list and update the compat functions at the end of this file.
52
53 - what was added / removed
54 - when was it added / removed (date and version)
55 - when can additional capability checks be set to mandatory (version)
56 - which compatibility checks are needed and till when (version)
57
58 freeciv | what | date | id
59 --------+------------------------------------------------+------------+----
60 current | (mapped to current savegame format) | ----/--/-- | 0
61 | first version (svn17538) | 2010/07/05 | -
62 2.3.0 | 2.3.0 release | 2010/11/?? | 3
63 2.4.0 | 2.4.0 release | 201./../.. | 10
64 | * player ai type | |
65 | * delegation | |
66 | * citizens | |
67 | * save player color | |
68 | * "known" info format change | |
69 2.5.0 | 2.5.0 release | 201./../.. | 20
70 2.6.0 | 2.6.0 release | 201./../.. | 30
71 3.0.0 | 3.0.0 release | 201./../.. | 40
72 3.1.0 | 3.1.0 release | 201./../.. | 50
73 3.2.0 | 3.2.0 release | 202./../.. | 60
74 3.3.0 | 3.3.0 release | 202./../.. | 70
75 3.4.0 | 3.4.0 release (development) | 202./../.. | 80
76 | | |
77*/
78
87static void compat_post_load_030100(struct loaddata *loading,
89static void compat_post_load_030300(struct loaddata *loading,
91
92#ifdef FREECIV_DEV_SAVE_COMPAT
93static void compat_load_dev(struct loaddata *loading);
94static void compat_post_load_dev(struct loaddata *loading);
95#endif /* FREECIV_DEV_SAVE_COMPAT */
96
98
104
105/* The struct below contains the information about the savegame versions. It
106 * is identified by the version number (first element), which should be
107 * steadily increasing. It is saved as 'savefile.version'. The support
108 * string (first element of 'name') is not saved in the savegame; it is
109 * saved in settings files (so, once assigned, cannot be changed). The
110 * 'pretty' string (second element of 'name') can be changed if necessary
111 * For changes in the development version, edit the definitions above and
112 * add the needed code to load the old version below. Thus, old
113 * savegames can still be loaded while the main definition
114 * represents the current state of the art. */
115/* While developing freeciv 3.4.0, add the compatibility functions to
116 * - compat_load_030400 to load old savegame. */
117static struct compatibility compat[] = {
118 /* Dummy; equal to the current version (last element) */
119 { 0, nullptr, nullptr },
120 /* Version 1 and 2 are not used */
121 /* Version 3: first savegame2 format, so no compat functions for translation
122 * from previous format */
123 { 3, nullptr, nullptr },
124 /* Version 4 to 9 are reserved for possible changes in 2.3.x */
125 { 10, compat_load_020400, nullptr },
126 /* Version 11 to 19 are reserved for possible changes in 2.4.x */
127 { 20, compat_load_020500, nullptr },
128 /* Version 21 to 29 are reserved for possible changes in 2.5.x */
129 { 30, compat_load_020600, nullptr },
130 /* Version 31 to 39 are reserved for possible changes in 2.6.x */
131 { 40, compat_load_030000, nullptr },
132 /* Version 41 to 49 are reserved for possible changes in 3.0.x */
134 /* Version 51 to 59 are reserved for possible changes in 3.1.x */
135 { 60, compat_load_030200, nullptr },
136 /* Version 61 to 69 are reserved for possible changes in 3.2.x */
138 /* Version 71 to 79 are reserved for possible changes in 3.3.x */
139 { 80, compat_load_030400, nullptr },
140 /* Current savefile version is listed above this line; it corresponds to
141 the definitions in this file. */
142};
143
144static const int compat_num = ARRAY_SIZE(compat);
145#define compat_current (compat_num - 1)
146
147/************************************************************************/
155{
156 int i;
157
158 /* Check status and return if not OK (sg_success FALSE). */
159 sg_check_ret();
160
161 loading->version = secfile_lookup_int_default(loading->file, -1,
162 "savefile.version");
163#ifdef FREECIV_DEBUG
164 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
165 loading->version);
166 if (loading->version > compat[compat_current].version) {
167 /* Debug build can (TRY TO!) load newer versions but ... */
168 log_error("Savegame version newer than this build found (%d > %d). "
169 "Trying to load the game nevertheless ...", loading->version,
171 }
172#else /* FREECIV_DEBUG */
173 sg_failure_ret(0 < loading->version
174 && loading->version <= compat[compat_current].version,
175 "Unknown savefile format version (%d).", loading->version);
176#endif /* FREECIV_DEBUG */
177
178
179 for (i = 0; i < compat_num; i++) {
180 if (loading->version < compat[i].version && compat[i].load != nullptr) {
181 log_normal(_("Run compatibility function for version: <%d "
182 "(save file: %d; server: %d)."), compat[i].version,
185 }
186 }
187
188#ifdef FREECIV_DEV_SAVE_COMPAT
189 if (loading->version == compat[compat_current].version) {
191 }
192#endif /* FREECIV_DEV_SAVE_COMPAT */
193}
194
195/************************************************************************/
207{
208 int i;
209
210 /* Check status and return if not OK (sg_success FALSE). */
211 sg_check_ret();
212
213 for (i = 0; i < compat_num; i++) {
214 if (loading->version < compat[i].version
215 && compat[i].post_load != nullptr) {
216 log_normal(_("Run post load compatibility function for version: <%d "
217 "(save file: %d; server: %d)."), compat[i].version,
220 }
221 }
222
223#ifdef FREECIV_DEV_SAVE_COMPAT
224 if (loading->version == compat[compat_current].version) {
226 }
227#endif /* FREECIV_DEV_SAVE_COMPAT */
228}
229
230/************************************************************************/
234{
236}
237
238/************************************************************************/
243char bin2ascii_hex(int value, int halfbyte_wanted)
244{
245 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
246}
247
248/************************************************************************/
256{
257 const char *pch;
258
259 if (ch == ' ') {
260 /* Sane value. It is unknown if there are savegames out there which
261 * need this fix. Savegame.c doesn't write such savegames
262 * (anymore) since the inclusion into CVS (2000-08-25). */
263 return 0;
264 }
265
267
268 sg_failure_ret_val(pch != nullptr && '\0' != ch, 0,
269 "Unknown hex value: '%c' %d", ch, ch);
270 return (pch - hex_chars) << (halfbyte * 4);
271}
272
273static const char num_chars[] =
274 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
275
276/************************************************************************/
279int char2num(char ch)
280{
281 const char *pch;
282
284
285 sg_failure_ret_val(pch != nullptr, 0,
286 "Unknown ascii value for num: '%c' %d", ch, ch);
287
288 return pch - num_chars;
289}
290
291/************************************************************************/
295{
296 int i;
297
298 for (i = 0; special_names[i] != nullptr; i++) {
299 if (!strcmp(name, special_names[i])) {
300 return i;
301 }
302 }
303
304 return S_LAST;
305}
306
307/************************************************************************/
311{
312 fc_assert(type >= 0 && type < S_LAST);
313
314 return special_names[type];
315}
316
317/************************************************************************/
321{
323
326 }
327
328 return nullptr;
329}
330
331/* =======================================================================
332 * Compatibility functions for loading a game.
333 * ======================================================================= */
334
335/************************************************************************/
340{
341 /* Check status and return if not OK (sg_success FALSE). */
342 sg_check_ret();
343
344 log_debug("Upgrading data from savegame to version 2.4.0");
345
346 /* Add the default player AI. */
347 player_slots_iterate(pslot) {
348 int ncities, i, plrno = player_slot_index(pslot);
349
350 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
351 continue;
352 }
353
355 "player%d.ai_type", player_slot_index(pslot));
356
357 /* Create dummy citizens information. We do not know if citizens are
358 * activated due to the fact that this information
359 * (game.info.citizen_nationality) is not available, but adding the
360 * information does no harm. */
362 "player%d.ncities", plrno);
363 if (ncities > 0) {
364 for (i = 0; i < ncities; i++) {
366 "player%d.c%d.size", plrno, i);
367 if (size > 0) {
369 "player%d.c%d.citizen%d", plrno, i, plrno);
370 }
371 }
372 }
373
375
376 /* Player colors are assigned at the end of player loading, as this
377 * needs information not available here. */
378
379 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
380 * workaround in later 2.3.x); see gna bug #19029.
381 * (The structure of this code is odd as it avoids relying on knowledge of
382 * xsize/ysize, which haven't been extracted from the savefile yet.) */
383 {
384 if (has_capability("knownv2",
385 secfile_lookup_str(loading->file, "savefile.options"))) {
386 /* This savefile contains known information in a sane format.
387 * Just move any entries to where 2.4.x+ expect to find them. */
388 struct section *map = secfile_section_by_name(loading->file, "map");
389
390 if (map != nullptr) {
392 const char *name = entry_name(pentry);
393
394 if (!fc_strncmp(name, "kvb", 3)) {
395 /* Rename the "kvb..." entry to "k..." */
396 char *name2 = fc_strdup(name), *newname = name2 + 2;
397
398 *newname = 'k';
399 /* Savefile probably contains existing "k" entries, which are bogus
400 * so we trash them. */
401 secfile_entry_delete(loading->file, "map.%s", newname);
403 FC_FREE(name2);
404 }
406 }
407 /* Could remove "knownv2" from savefile.options, but it's doing
408 * no harm there. */
409 } else {
410 /* This savefile only contains known information in the broken
411 * format. Try to recover it to a sane format. */
412 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
413 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
414 const int maxslots = 128, maxmapsize = 512;
415 const int lines = maxslots/32;
416 int xsize = 0, y, l, j, x;
417 unsigned int known_row_old[lines * maxmapsize],
419 /* Process a map row at a time */
420 for (y = 0; y < maxmapsize; y++) {
421 /* Look for broken info to convert */
422 bool found = FALSE;
424 for (l = 0; l < lines; l++) {
425 for (j = 0; j < 8; j++) {
426 const char *s =
427 secfile_lookup_str_default(loading->file, nullptr,
428 "map.k%02d_%04d", l * 8 + j, y);
429 if (s) {
430 found = TRUE;
431 if (xsize == 0) {
432 xsize = strlen(s);
433 }
434 sg_failure_ret(xsize == strlen(s),
435 "Inconsistent xsize in map.k%02d_%04d",
436 l * 8 + j, y);
437 for (x = 0; x < xsize; x++) {
438 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
439 }
440 }
441 }
442 }
443 if (found) {
444 /* At least one entry found for this row. Let's hope they were
445 * all there. */
446 /* Attempt to munge into sane format */
447 int p;
448 memset(known_row, 0, sizeof(known_row));
449 /* Iterate over possible player slots */
450 for (p = 0; p < maxslots; p++) {
451 l = p / 32;
452 for (x = 0; x < xsize; x++) {
453 /* This test causes bit-shifts of >=32 (undefined behavior), but
454 * on common platforms, information happens not to be lost, just
455 * oddly arranged. */
456 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
457 known_row[l * xsize + x] |= (1u << (p - l * 32));
458 }
459 }
460 }
461 /* Save sane format back to memory representation of secfile for
462 * real loading code to pick up */
463 for (l = 0; l < lines; l++) {
464 for (j = 0; j < 8; j++) {
465 /* Save info for all slots (not just used ones). It's only
466 * memory, after all. */
467 char row[xsize+1];
468 for (x = 0; x < xsize; x++) {
469 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
470 }
471 row[xsize] = '\0';
473 "map.k%02d_%04d", l * 8 + j, y);
474 }
475 }
476 }
477 }
478 }
479 }
480
481 /* Server setting migration. */
482 {
483 int set_count;
484
485 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
486 int i, new_opt = set_count;
487 bool gamestart_valid
489 "settings.gamestart_valid");
490
491 for (i = 0; i < set_count; i++) {
492 const char *name
493 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
494
495 if (!name) {
496 continue;
497 }
498
499 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
500 * This is now controlled by the "autosaves" setting. */
501 if (!fc_strcasecmp("saveturns", name)) {
502 /* XXX: Hardcodes details from GAME_AUTOSAVES_DEFAULT
503 * and settings.c:autosaves_name() (but these defaults reflect
504 * 2.3's behavior). */
505 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
506 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
507 int nturns;
508
510 "settings.set%d.value", i)) {
511 if (nturns == 0) {
512 /* Invent a new "autosaves" setting */
514 "settings.set%d.value", new_opt);
515 /* Pick something valid for saveturns */
517 "settings.set%d.value", i);
518 } else {
520 "settings.set%d.value", new_opt);
521 }
522 } else {
523 log_sg("Setting '%s': %s", name, secfile_error());
524 }
525 if (gamestart_valid) {
527 "settings.set%d.gamestart", i)) {
528 if (nturns == 0) {
529 /* Invent a new "autosaves" setting */
531 "settings.set%d.gamestart", new_opt);
532 /* Pick something valid for saveturns */
534 "settings.set%d.gamestart", i);
535 } else {
537 "settings.set%d.gamestart", new_opt);
538 }
539 } else {
540 log_sg("Setting '%s': %s", name, secfile_error());
541 }
542 }
543 } else if (!fc_strcasecmp("autosaves", name)) {
544 /* Sanity check. This won't trigger on an option we've just
545 * invented, as the loop won't include it. */
546 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
547 "savefile. It may have been overridden.");
548 }
549 }
550 }
551 }
552}
553
554/************************************************************************/
557static const char *killcitizen_enum_str(secfile_data_t data, int bit)
558{
559 switch (bit) {
560 case UMT_LAND:
561 return "LAND";
562 case UMT_SEA:
563 return "SEA";
564 case UMT_BOTH:
565 return "BOTH";
566 }
567
568 return nullptr;
569}
570
571/************************************************************************/
576{
577 const char *modname[] = { "Road", "Railroad" };
578 const char *old_activities_names[] = {
579 "Idle",
580 "Pollution",
581 "Unused Road",
582 "Mine",
583 "Irrigate",
584 "Mine",
585 "Irrigate",
586 "Fortified",
587 "Fortress",
588 "Sentry",
589 "Unused Railroad",
590 "Pillage",
591 "Goto",
592 "Explore",
593 "Transform",
594 "Unused",
595 "Unused Airbase",
596 "Fortifying",
597 "Fallout",
598 "Unused Patrol",
599 "Base"
600 };
601
602 /* Check status and return if not OK (sg_success FALSE). */
603 sg_check_ret();
604
605 log_debug("Upgrading data from savegame to version 2.5.0");
606
607 secfile_insert_int(loading->file, 2, "savefile.roads_size");
608 secfile_insert_int(loading->file, 0, "savefile.trait_size");
609
611 "savefile.roads_vector");
612
613 secfile_insert_int(loading->file, 19, "savefile.activities_size");
615 "savefile.activities_vector");
616
617 /* Server setting migration. */
618 {
619 int set_count;
620
621 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
622 int i;
623 bool gamestart_valid
625 "settings.gamestart_valid");
626 for (i = 0; i < set_count; i++) {
627 const char *name
628 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
629 if (!name) {
630 continue;
631 }
632 /* In 2.4.x and prior, "killcitizen" listed move types that
633 * killed citizens after successful attack. Now killcitizen
634 * is just boolean and classes affected are defined in ruleset. */
635 if (!fc_strcasecmp("killcitizen", name)) {
636 int value;
637
638 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
639 killcitizen_enum_str, nullptr,
640 "settings.set%d.value", i)) {
641 /* Lowest bit of old killcitizen value indicates if
642 * land units should kill citizens. We take that as
643 * new boolean killcitizen value. */
644 if (value & 0x1) {
646 "settings.set%d.value", i);
647 } else {
649 "settings.set%d.value", i);
650 }
651 } else {
652 log_sg("Setting '%s': %s", name, secfile_error());
653 }
654 if (gamestart_valid) {
655 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
656 killcitizen_enum_str, nullptr,
657 "settings.set%d.gamestart", i)) {
658 /* Lowest bit of old killcitizen value indicates if
659 * land units should kill citizens. We take that as
660 * new boolean killcitizen value. */
661 if (value & 0x1) {
663 "settings.set%d.gamestart", i);
664 } else {
666 "settings.set%d.gamestart", i);
667 }
668 } else {
669 log_sg("Setting '%s': %s", name, secfile_error());
670 }
671 }
672 }
673 }
674 }
675 }
676}
677
678/************************************************************************/
682{
683 switch (type) {
684 case REVOLEN_FIXED:
685 return "FIXED";
686 case REVOLEN_RANDOM:
687 return "RANDOM";
689 return "QUICKENING";
691 return "RANDQUICK";
692 }
693
694 return "";
695}
696
697/************************************************************************/
702{
703 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
704 int tsize;
705 int ti;
706 int turn;
707
708 /* Check status and return if not OK (sg_success FALSE). */
709 sg_check_ret();
710
711 log_debug("Upgrading data from savegame to version 2.6.0");
712
713 /* Terrain mapping table - use current ruleset as we have no way to know
714 * any other old values. */
715 ti = 0;
717 char buf[2];
718
719 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
721 buf[1] = '\0';
722 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
724
725 /* Server setting migration. */
726 {
727 int set_count;
728
729 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
730 char value_buffer[1024] = "";
731 char gamestart_buffer[1024] = "";
732 int i;
733 int dcost = -1;
734 int dstartcost = -1;
737 bool gamestart_valid
739 "settings.gamestart_valid");
740 int new_set_count;
741
742 for (i = 0; i < set_count; i++) {
743 const char *name
744 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
745 if (!name) {
746 continue;
747 }
748
749 /* In 2.5.x and prior, "spacerace" boolean controlled if
750 * spacerace victory condition was active. */
751 if (!fc_strcasecmp("spacerace", name)) {
752 bool value;
753
754 if (secfile_lookup_bool(loading->file, &value,
755 "settings.set%d.value", i)) {
756 if (value) {
757 if (value_buffer[0] != '\0') {
759 }
760 sz_strlcat(value_buffer, "SPACERACE");
761 }
762 } else {
763 log_sg("Setting '%s': %s", name, secfile_error());
764 }
765 if (secfile_lookup_bool(loading->file, &value,
766 "settings.set%d.gamestart", i)) {
767 if (value) {
768 if (gamestart_buffer[0] != '\0') {
770 }
771 sz_strlcat(gamestart_buffer, "SPACERACE");
772 }
773 } else {
774 log_sg("Setting '%s': %s", name, secfile_error());
775 }
776
777 /* We cannot delete old values from the secfile, or rather cannot
778 * change index of the later settings. Renumbering them is not easy as
779 * we don't know type of each setting we would encounter.
780 * So we keep old setting values and only add new "victories" setting. */
781 } else if (!fc_strcasecmp("alliedvictory", name)) {
782 bool value;
783
784 if (secfile_lookup_bool(loading->file, &value,
785 "settings.set%d.value", i)) {
786 if (value) {
787 if (value_buffer[0] != '\0') {
789 }
790 sz_strlcat(value_buffer, "ALLIED");
791 }
792 } else {
793 log_sg("Setting '%s': %s", name, secfile_error());
794 }
795 if (secfile_lookup_bool(loading->file, &value,
796 "settings.set%d.gamestart", i)) {
797 if (value) {
798 if (gamestart_buffer[0] != '\0') {
800 }
801 sz_strlcat(gamestart_buffer, "ALLIED");
802 }
803 } else {
804 log_sg("Setting '%s': %s", name, secfile_error());
805 }
806 } else if (!fc_strcasecmp("revolen", name)) {
807 int value;
808
809 if (secfile_lookup_int(loading->file, &value,
810 "settings.set%d.value", i)) {
811 /* 0 meant RANDOM 1-5 */
812 if (value == 0) {
815 "settings.set%d.value", i);
816 } else {
818 }
819 } else {
820 log_sg("Setting '%s': %s", name, secfile_error());
821 }
822 if (secfile_lookup_int(loading->file, &value,
823 "settings.set%d.gamestart", i)) {
824 /* 0 meant RANDOM 1-5 */
825 if (value == 0) {
828 "settings.set%d.gamestart", i);
829 } else {
831 }
832 } else {
833 log_sg("Setting '%s': %s", name, secfile_error());
834 }
835 } else if (!fc_strcasecmp("happyborders", name)) {
836 bool value;
837
838 if (secfile_lookup_bool(loading->file, &value,
839 "settings.set%d.value", i)) {
840 secfile_entry_delete(loading->file, "settings.set%d.value", i);
841 if (value) {
842 secfile_insert_str(loading->file, "NATIONAL",
843 "settings.set%d.value", i);
844 } else {
845 secfile_insert_str(loading->file, "DISABLED",
846 "settings.set%d.value", i);
847 }
848 } else {
849 log_sg("Setting '%s': %s", name, secfile_error());
850 }
851 if (secfile_lookup_bool(loading->file, &value,
852 "settings.set%d.gamestart", i)) {
853 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
854 if (value) {
855 secfile_insert_str(loading->file, "NATIONAL",
856 "settings.set%d.gamestart", i);
857 } else {
858 secfile_insert_str(loading->file, "DISABLED",
859 "settings.set%d.gamestart", i);
860 }
861 } else {
862 log_sg("Setting '%s': %s", name, secfile_error());
863 }
864 } else if (!fc_strcasecmp("team_pooled_research", name)) {
866 &team_pooled_research,
867 "settings.set%d.value", i),
868 "%s", secfile_error());
869 } else if (!fc_strcasecmp("diplcost", name)) {
870 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
871 if (secfile_lookup_int(loading->file, &dcost,
872 "settings.set%d.value", i)) {
873 } else {
874 log_sg("Setting '%s': %s", name, secfile_error());
875 }
876
878 "settings.set%d.gamestart", i)) {
879 } else {
880 log_sg("Setting '%s': %s", name, secfile_error());
881 }
882 } else if (!fc_strcasecmp("huts", name)) {
883 /* Scale of 'huts' changed. */
884 int hcount;
885
887 "settings.set%d.value", i)) {
888 } else {
889 log_sg("Setting '%s': %s", name, secfile_error());
890 }
891
892 /* Store old-style absolute value. */
894 }
895 }
896
897 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
898
899 if (dcost >= 0) {
900 new_set_count += 2;
901 }
902
903 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
904
905 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
906 set_count);
907 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
908 set_count);
909 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
910 set_count + 1);
911 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
912 set_count + 1);
913
914 if (dcost >= 0) {
915 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
916 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
917 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
918 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
919 }
920
921 if (gamestart_valid) {
922 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
923 set_count);
924 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
925 set_count + 1);
926
927 if (dcost >= 0) {
928 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
929 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
930 }
931 }
932 }
933 }
934
935 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
936 "Trait size: %s", secfile_error());
937
938 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
939
940 player_slots_iterate(pslot) {
941 int plrno = player_slot_index(pslot);
942 bool got_first_city;
943 int old_barb_type;
944 enum barbarian_type new_barb_type;
945 int i;
946 const char *name;
947 int score;
948 int units_num;
949
950 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
951 continue;
952 }
953
954 /* Renamed 'capital' to 'got_first_city'. */
956 "player%d.capital", plrno)) {
958 "player%d.got_first_city", plrno);
959 }
960
961 /* Add 'anonymous' qualifiers for user names */
962 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
964 "player%d.unassigned_user", plrno);
965
966 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
968 "player%d.unassigned_ranked", plrno);
969
970 /* Convert numeric barbarian type to textual */
972 "player%d.ai.is_barbarian", plrno);
975 "player%d.ai.barb_type", plrno);
976
977 /* Pre-2.6 didn't record when a player was created or died, so we have
978 * to assume they lived from the start of the game until last turn */
979 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
980
981 /* As if there never has been a war. */
982 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
983
984 /* Assume people were playing until current reload */
985 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
986
987 for (i = 0; i < tsize; i++) {
988 int val;
989
990 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
991 plrno, i);
992 if (val != -1) {
993 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
994 }
995
997 "player%d.trait.mod%d", plrno, i),
998 "Trait mod: %s", secfile_error());
999 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1000 }
1001
1002 score = secfile_lookup_int_default(loading->file, -1,
1003 "player%d.units_built", plrno);
1004 if (score >= 0) {
1005 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1006 }
1007
1008 score = secfile_lookup_int_default(loading->file, -1,
1009 "player%d.units_killed", plrno);
1010 if (score >= 0) {
1011 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1012 }
1013
1014 score = secfile_lookup_int_default(loading->file, -1,
1015 "player%d.units_lost", plrno);
1016 if (score >= 0) {
1017 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1018 }
1019
1020 /* Units orders. */
1022 "player%d.nunits",
1023 plrno);
1024
1025 for (i = 0; i < units_num; i++) {
1026 int len;
1027
1029 "player%d.u%d.orders_last_move_safe",
1030 plrno, i)) {
1031 continue;
1032 }
1033
1035 "player%d.u%d.orders_length",
1036 plrno, i);
1037 if (len > 0) {
1038 char orders_str[len + 1];
1039 char *p;
1040
1043 "player%d.u%d.orders_list",
1044 plrno, i));
1045 if ((p = strrchr(orders_str, 'm'))
1046 || (p = strrchr(orders_str, 'M'))) {
1047 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1049 "player%d.u%d.orders_list", plrno, i);
1050 }
1051 }
1052 }
1054
1055 /* Add specialist order - loading time order is ok here, as we will use
1056 * that when we in later part of compatibility conversion use the specialist
1057 * values */
1059 "savefile.specialists_size");
1060 {
1061 const char **modname;
1062 int i = 0;
1063
1065
1069
1071 "savefile.specialists_vector");
1072
1073 free(modname);
1074 }
1075
1076 /* Replace all city specialist count fields with correct names */
1077 player_slots_iterate(pslot) {
1078 int plrno = player_slot_index(pslot);
1079 int ncities;
1080 int i;
1081
1082 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1083 continue;
1084 }
1085
1086 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1087
1088 for (i = 0; i < ncities; i++) {
1089 int k = 0;
1090
1092 struct specialist *psp = specialist_by_number(sp);
1093 int count;
1094
1096 "player%d.c%d.n%s",
1098 "specialist error: %s", secfile_error());
1099 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1101 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1102 plrno, i, k++);
1104 }
1106
1107 /* Build [research]. */
1108 {
1109 const struct {
1110 const char *name;
1111 enum entry_type type;
1112 } entries[] = {
1113 { "goal_name", ENTRY_STR },
1114 { "techs", ENTRY_INT },
1115 { "futuretech", ENTRY_INT },
1116 { "bulbs_before", ENTRY_INT },
1117 { "saved_name", ENTRY_STR },
1118 { "bulbs", ENTRY_INT },
1119 { "now_name", ENTRY_STR },
1120 { "got_tech", ENTRY_BOOL },
1121 { "done", ENTRY_STR }
1122 };
1123
1125 int count = 0;
1126 int i;
1127
1128 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1129 researches[i] = -1;
1130 }
1131
1132 player_slots_iterate(pslot) {
1133 int plrno = player_slot_index(pslot);
1134 int ival;
1135 bool bval;
1136 const char *sval;
1137 int j;
1138
1139 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1140 continue;
1141 }
1142
1143 /* Get the research number. */
1144 if (team_pooled_research) {
1146 "player%d.team_no", plrno);
1147 } else {
1148 i = plrno;
1149 }
1150
1152 "Research out of bounds (%d)!", i);
1153
1154 /* Find the index in [research] section. */
1155 if (researches[i] == -1) {
1156 /* This is the first player for this research. */
1157 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1158 researches[i] = count;
1159 count++;
1160 }
1161 i = researches[i];
1162
1163 /* Move entries. */
1164 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1165 switch (entries[j].type) {
1166 case ENTRY_BOOL:
1167 if (secfile_lookup_bool(loading->file, &bval,
1168 "player%d.research.%s",
1169 plrno, entries[j].name)) {
1170 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1171 i, entries[j].name);
1172 }
1173 break;
1174 case ENTRY_INT:
1175 if (secfile_lookup_int(loading->file, &ival,
1176 "player%d.research.%s",
1177 plrno, entries[j].name)) {
1178 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1179 i, entries[j].name);
1180 }
1181 break;
1182 case ENTRY_STR:
1183 if ((sval = secfile_lookup_str(loading->file,
1184 "player%d.research.%s",
1185 plrno, entries[j].name))) {
1186 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1187 i, entries[j].name);
1188 }
1189 break;
1190 case ENTRY_FLOAT:
1192 "Research related entry marked as float.");
1193 break;
1196 break;
1197 case ENTRY_LONG_COMMENT:
1199 break;
1200 case ENTRY_ILLEGAL:
1202 break;
1203 }
1204 }
1206 secfile_insert_int(loading->file, count, "research.count");
1207 }
1208
1209 /* Add diplstate type order. */
1211 "savefile.diplstate_type_size");
1212 if (DS_LAST > 0) {
1213 const char **modname;
1214 int i;
1215 int j;
1216
1217 i = 0;
1218 modname = fc_calloc(DS_LAST, sizeof(*modname));
1219
1220 for (j = 0; j < DS_LAST; j++) {
1222 }
1223
1225 DS_LAST,
1226 "savefile.diplstate_type_vector");
1227 free(modname);
1228 }
1229
1230 /* Fix save games from Freeciv versions with a bug that made it view
1231 * "Never met" as closer than "Peace" or "Alliance". */
1232 player_slots_iterate(pslot) {
1233 int plrno = player_slot_index(pslot);
1234
1235 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1236 continue;
1237 }
1238
1240 int i = player_slot_index(pslot2);
1241 char buf[32];
1242 int current;
1243 int closest;
1244
1245 if (secfile_section_lookup(loading->file, "player%d", i) == nullptr) {
1246 continue;
1247 }
1248
1249 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1250
1251 /* Read the current diplomatic state. */
1253 "%s.type",
1254 buf);
1255
1256 /* Read the closest diplomatic state. */
1258 "%s.max_state",
1259 buf);
1260
1261 if (closest == DS_NO_CONTACT
1262 && (current == DS_PEACE
1263 || current == DS_ALLIANCE)) {
1264 const char *name1 = secfile_lookup_str_default(loading->file, "",
1265 "player%d.name", plrno);
1266 const char *name2 = secfile_lookup_str_default(loading->file, "",
1267 "player%d.name", i);
1268 /* The current relationship is closer than what the save game
1269 * claims is the closes relationship ever. */
1270
1271 log_sg(_("The save game is wrong about what the closest"
1272 " relationship %s (player %d) and %s (player %d) have had is."
1273 " Fixing it..."),
1274 name1, plrno, name2, i);
1275
1276 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1277 }
1280}
1281
1282/************************************************************************/
1285static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1286 int old_def, bool keep_default)
1287{
1288 int value;
1289
1290 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1291
1292 if (value != old_def || !keep_default) {
1293 value++;
1294 secfile_replace_int(loading->file, value, "%s", key);
1295 }
1296
1297 return value;
1298}
1299
1300/************************************************************************/
1308{
1309 bool randsaved;
1310 int num_settings;
1311 bool started;
1312 int old_turn;
1313 int event_count;
1314 int i;
1315
1316 /* Check status and return if not OK (sg_success FALSE). */
1317 sg_check_ret();
1318
1319 log_debug("Upgrading data from savegame to version 3.0.0");
1320
1321 /* Rename "random.save" as "random.saved"
1322 * Note that it's not an error if a scenario does not have [random] at all. */
1323 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1324 secfile_insert_bool(loading->file, randsaved, "random.saved");
1325 }
1326
1327 /* Already started games should have their turn counts increased by 1 */
1328 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1329 started = TRUE;
1330
1331 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1333 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1334 } else {
1335 started = FALSE;
1336 }
1337
1338 player_slots_iterate(pslot) {
1339 int plrno = player_slot_index(pslot);
1340 const char *flag_names[1];
1341
1342 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1343 continue;
1344 }
1345
1346 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1347 plrno)) {
1349
1351 "player%d.flags", plrno);
1352 }
1353
1354 if (started) {
1355 int num = secfile_lookup_int_default(loading->file, 0,
1356 "player%d.nunits",
1357 plrno);
1358
1359 for (i = 0; i < num; i++) {
1360 char buf[64];
1361
1362 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1363
1365 }
1366
1367 num = secfile_lookup_int_default(loading->file, 0,
1368 "player%d.ncities", plrno);
1369
1370 for (i = 0; i < num; i++) {
1371 char buf[64];
1372
1373 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1374
1376 }
1377 }
1379
1380 /* Settings */
1382 "settings.set_count");
1383
1384 /* User meta server message is now a setting. */
1386 "game.meta_usermessage")) {
1387 const char *metamessage;
1388
1390 "game.meta_message");
1391
1392 /* Insert the meta message as a setting */
1393 secfile_insert_str(loading->file, "metamessage",
1394 "settings.set%d.name", num_settings);
1396 "settings.set%d.value", num_settings);
1397 secfile_insert_str(loading->file, "",
1398 "settings.set%d.gamestart", num_settings);
1399 num_settings++;
1400 }
1401
1402 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1403
1404 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1405
1406 for (i = 0; i < event_count; i++) {
1407 const char *etype;
1408
1409 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1410
1411 if (etype != nullptr && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1412 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1413 "event_cache.events%d.event", i);
1414 }
1415 }
1416}
1417
1418/************************************************************************/
1423{
1424 int ssa_size;
1425
1426 if (format_class == SAVEGAME_2) {
1427 /* Handled in savegame2 */
1428 return;
1429 }
1430
1432 "savefile.server_side_agent_size");
1433
1434 if (ssa_size != 0) {
1435 /* Already inserted. */
1436 return;
1437 }
1438
1439 /* Add server side agent order. */
1441 "savefile.server_side_agent_size");
1442 if (SSA_COUNT > 0) {
1443 const char **modname;
1444 int i;
1445 int j;
1446
1447 i = 0;
1448 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1449
1450 for (j = 0; j < SSA_COUNT; j++) {
1452 }
1453
1455 SSA_COUNT,
1456 "savefile.server_side_agent_list");
1457 free(modname);
1458 }
1459
1460 /* Insert server_side_agent unit field. */
1461 player_slots_iterate(pslot) {
1462 int unit;
1463 int units_num;
1464 int plrno = player_slot_index(pslot);
1465
1466 if (secfile_section_lookup(loading->file, "player%d", plrno)
1467 == nullptr) {
1468 continue;
1469 }
1470
1471 /* Number of units the player has. */
1473 "player%d.nunits",
1474 plrno);
1475
1476 for (unit = 0; unit < units_num; unit++) {
1477 bool ai;
1478
1480 "player%d.u%d.server_side_agent",
1481 plrno, unit)
1482 != nullptr) {
1483 /* Already updated? */
1484 continue;
1485 }
1486
1488 "player%d.u%d.ai",
1489 plrno, unit);
1490
1491 if (ai) {
1492 /* Autoworker and Autoexplore are separated by
1493 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1495 "player%d.u%d.server_side_agent",
1496 plrno, unit);
1497 } else {
1499 "player%d.u%d.server_side_agent",
1500 plrno, unit);
1501 }
1502 }
1504}
1505
1506/************************************************************************/
1514{
1515 /* Check status and return if not OK (sg_success FALSE). */
1516 sg_check_ret();
1517
1518 log_debug("Upgrading data from savegame to version 3.1.0");
1519
1520 /* Actions are now stored by number. */
1521 player_slots_iterate(pslot) {
1522 int unit;
1523 int units_num;
1524 int plrno = player_slot_index(pslot);
1525
1526 if (secfile_section_lookup(loading->file, "player%d", plrno)
1527 == nullptr) {
1528 continue;
1529 }
1530
1531 /* Number of units the player has. */
1533 "player%d.nunits",
1534 plrno);
1535
1536 for (unit = 0; unit < units_num; unit++) {
1537 const char *action_unitstr;
1538 int order_len;
1539
1541 "player%d.u%d.orders_length",
1542 plrno, unit);
1543
1545 "player%d.u%d.action_list",
1546 plrno, unit))) {
1547 int order_num;
1548
1551 }
1552
1553 for (order_num = 0; order_num < order_len; order_num++) {
1555
1556 if (action_unitstr[order_num] == '?') {
1558 } else {
1560 }
1561
1562 if (order_num == 0) {
1563 /* The start of a vector has no number. */
1565 "player%d.u%d.action_vec",
1566 plrno, unit);
1567 } else {
1569 "player%d.u%d.action_vec,%d",
1570 plrno, unit, order_num);
1571 }
1572 }
1573 }
1574 }
1576
1577 {
1578 int action_count;
1579
1581 "savefile.action_size");
1582
1583 if (action_count > 0) {
1584 const char **modname;
1585 const char **savemod;
1586 int j;
1587 const char *dur_name = "Disband Unit Recover";
1588
1589 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1590 "savefile.action_vector");
1591
1593
1594 for (j = 0; j < action_count; j++) {
1595 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1596 savemod[j] = dur_name;
1597 } else {
1598 savemod[j] = modname[j];
1599 }
1600 }
1601
1603 "savefile.action_vector");
1604
1605 free(savemod);
1606 }
1607 }
1608
1609 /* Server setting migration. */
1610 {
1611 int set_count;
1612
1613 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1614 int i;
1615 bool gamestart_valid
1617 "settings.gamestart_valid");
1618
1619 /* Only add gamesetdef if gamestart is valid at all */
1620 if (gamestart_valid) {
1621 for (i = 0; i < set_count; i++) {
1622 const char *name
1623 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1624
1625 if (!name) {
1626 continue;
1627 }
1628
1630 "settings.set%d.gamesetdef", i);
1631 }
1632 }
1633 }
1634 }
1635
1636 /* Explicit server side agent was new in 3.1 */
1638}
1639
1640/************************************************************************/
1644{
1645 int i;
1646
1647 for (i = 0; i < act_unit->orders.length; i++) {
1648 struct unit_order *order = &act_unit->orders.list[i];
1649
1650 if (order->order != ORDER_ACTIVITY) {
1651 continue;
1652 }
1653
1654 switch (order->activity) {
1655 case ACTIVITY_CLEAN:
1656 case ACTIVITY_MINE:
1657 case ACTIVITY_IRRIGATE:
1658 case ACTIVITY_PLANT:
1659 case ACTIVITY_CULTIVATE:
1660 case ACTIVITY_TRANSFORM:
1661 case ACTIVITY_CONVERT:
1663 case ACTIVITY_BASE:
1664 case ACTIVITY_GEN_ROAD:
1665 case ACTIVITY_PILLAGE:
1666 action_iterate(act_id) {
1667 struct action *paction = action_by_number(act_id);
1668
1669 if (action_get_activity(paction) == order->activity) {
1670 order->order = ORDER_PERFORM_ACTION;
1671 order->action = action_number(paction);
1672 order->activity = ACTIVITY_LAST;
1673 break;
1674 }
1676 break;
1677 case ACTIVITY_SENTRY:
1678 /* Not an action */
1679 break;
1680 case ACTIVITY_EXPLORE:
1681 case ACTIVITY_IDLE:
1682 case ACTIVITY_GOTO:
1683 case ACTIVITY_FORTIFIED:
1684 case ACTIVITY_LAST:
1685 log_error("Activity %d is not supposed to appear in unit orders",
1686 order->activity);
1687 break;
1688 }
1689 }
1690}
1691
1692/************************************************************************/
1696{
1697 switch (dir) {
1698 case DIR8_NORTH:
1699 return DIR8_SOUTH;
1700 case DIR8_NORTHEAST:
1701 return DIR8_SOUTHWEST;
1702 case DIR8_EAST:
1703 return DIR8_WEST;
1704 case DIR8_SOUTHEAST:
1705 return DIR8_NORTHWEST;
1706 case DIR8_SOUTH:
1707 return DIR8_NORTH;
1708 case DIR8_SOUTHWEST:
1709 return DIR8_NORTHEAST;
1710 case DIR8_WEST:
1711 return DIR8_EAST;
1712 case DIR8_NORTHWEST:
1713 return DIR8_SOUTHEAST;
1714 }
1715
1716 return DIR8_ORIGIN;
1717}
1718
1719/************************************************************************/
1723{
1724 int i;
1725 struct tile *current_tile;
1726 struct tile *tgt_tile;
1727
1728 if (!unit_has_orders(act_unit)) {
1729 return;
1730 }
1731
1732 /* The order index is for the unit at its current tile. */
1733 current_tile = unit_tile(act_unit);
1734
1735 /* Rewind to the beginning of the orders */
1736 for (i = act_unit->orders.index; i > 0 && current_tile != nullptr; i--) {
1737 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1738
1739 if (!(prev_order->order == ORDER_PERFORM_ACTION
1743 current_tile = mapstep(&(wld.map), current_tile,
1744 dir_opposite(prev_order->dir));
1745 }
1746 }
1747
1748 /* Upgrade to explicit target tile */
1749 for (i = 0; i < act_unit->orders.length && current_tile != nullptr; i++) {
1750 struct unit_order *order = &act_unit->orders.list[i];
1751
1752 if (order->order == ORDER_PERFORM_ACTION
1753 && order->target != NO_TARGET) {
1754 /* The target is already specified in the new format. */
1755
1756 /* The index_to_tile() call has no side-effects that we
1757 * would want also in NDEBUG builds. */
1758 fc_assert(index_to_tile(&(wld.map), order->target) != nullptr);
1759 return;
1760 }
1761
1762 if (!direction8_is_valid(order->dir)) {
1763 /* The target of the action is on the actor's tile. */
1764 tgt_tile = current_tile;
1765 } else {
1766 /* The target of the action is on a tile next to the actor. */
1767 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1768 }
1769
1770 if (order->order == ORDER_PERFORM_ACTION) {
1771 if (tgt_tile != nullptr) {
1772 struct action *paction = action_by_number(order->action);
1773
1774 order->target = tgt_tile->index;
1775 /* Leave no traces. */
1776 order->dir = DIR8_ORIGIN;
1777
1779 /* The action moves the unit to the target tile (unless this is the
1780 * final order) */
1783 || i == act_unit->orders.length - 1);
1784 current_tile = tgt_tile;
1785 }
1786 } else {
1787 current_tile = nullptr;
1788 }
1789 } else {
1790 current_tile = tgt_tile;
1791 }
1792 }
1793
1794 if (current_tile == nullptr) {
1795 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1797 }
1798}
1799
1800/************************************************************************/
1804{
1805 players_iterate_alive(pplayer) {
1806 unit_list_iterate(pplayer->units, punit) {
1809 }
1812}
1813
1814/************************************************************************/
1819{
1820 /* Check status and return if not OK (sg_success FALSE). */
1821 sg_check_ret();
1822
1823 /* Action orders were new in 3.0 */
1824 if (format_class == SAVEGAME_3) {
1825 /* Only 3.0 savegames may have "Attack" action orders. */
1826 players_iterate_alive(pplayer) {
1827 unit_list_iterate(pplayer->units, punit) {
1828 int i;
1829
1830 if (!punit->has_orders) {
1831 continue;
1832 }
1833
1835 || punit->orders.list != nullptr, continue);
1836
1837 for (i = 0; i < punit->orders.length; i++) {
1838 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1844 }
1845
1846 /* Production targeted actions were split from building targeted
1847 * actions in 3.1. The building sub target encoding changed. */
1849 && ((punit->orders.list[i].action
1851 || (punit->orders.list[i].action
1853 punit->orders.list[i].sub_target -= 1;
1854 }
1856 && (punit->orders.list[i].action
1858 && punit->orders.list[i].sub_target == -1) {
1861 }
1863 && (punit->orders.list[i].action
1865 && punit->orders.list[i].sub_target == -1) {
1868 }
1869 }
1872 }
1873
1874 /* Explicit server side agent was new in 3.1 */
1876
1877 /* Some activities should only be ordered in action orders. */
1878 players_iterate_alive(pplayer) {
1879 unit_list_iterate(pplayer->units, punit) {
1883
1884 /* Unit order action target isn't dir anymore */
1885 players_iterate_alive(pplayer) {
1886 unit_list_iterate(pplayer->units, punit) {
1890
1891 /* Backward compatibility: if we had any open-ended orders (pillage)
1892 * in the savegame, assign specific targets now */
1893 players_iterate_alive(pplayer) {
1894 unit_list_iterate(pplayer->units, punit) {
1896 &punit->activity,
1897 punit->action,
1901}
1902
1903/************************************************************************/
1911{
1912 int i;
1913 int count;
1914 int set_count;
1915 bool gamestart_valid = FALSE;
1916
1917 /* Check status and return if not OK (sg_success FALSE). */
1918 sg_check_ret();
1919
1920 log_debug("Upgrading data from savegame to version 3.2.0");
1921
1922 {
1923 const char *str = secfile_lookup_str_default(loading->file, nullptr,
1924 "savefile.orig_version");
1925
1926 if (str == nullptr) {
1927 /* Make sure CURRENTLY running version does not
1928 * end as orig_version when we resave. */
1929 if (format_class == SAVEGAME_3) {
1930 secfile_insert_str(loading->file, "old savegame3, or older",
1931 "savefile.orig_version");
1932 } else {
1934
1935 secfile_insert_str(loading->file, "savegame2, or older",
1936 "savefile.orig_version");
1937 }
1938 }
1939 }
1940
1941 {
1942 int action_count;
1943
1945 "savefile.action_size");
1946
1947 if (action_count > 0) {
1948 const char **modname;
1949 const char **savemod;
1950 int j;
1951 const char *dur_name = "Transport Deboard";
1952 const char *clean_name = "Clean";
1953
1954 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1955 "savefile.action_vector");
1956
1958
1959 for (j = 0; j < action_count; j++) {
1960 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1961 savemod[j] = dur_name;
1962 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1963 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1964 savemod[j] = clean_name;
1965 } else {
1966 savemod[j] = modname[j];
1967 }
1968 }
1969
1971 "savefile.action_vector");
1972
1973 free(savemod);
1974 }
1975 }
1976
1977 {
1978 int activities_count;
1979
1981 "savefile.activities_size");
1982
1983 if (activities_count > 0) {
1984 const char **modname;
1985 const char **savemod;
1986 int j;
1987 const char *clean_name = "Clean";
1988
1989 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1990 "savefile.activities_vector");
1991
1993
1994 for (j = 0; j < activities_count; j++) {
1995 if (!fc_strcasecmp("Pollution", modname[j])
1996 || !fc_strcasecmp("Fallout", modname[j])) {
1997 savemod[j] = clean_name;
1998 } else {
1999 savemod[j] = modname[j];
2000 }
2001 }
2002
2004 "savefile.activities_vector");
2005
2006 free(savemod);
2007 }
2008 }
2009
2010 /* Server setting migration. */
2011 {
2012 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2013 int alltemperate_idx = -1, singlepole_idx = -1;
2014 bool count_changed = FALSE;
2015
2018 "settings.gamestart_valid");
2019
2020 for (i = 0; i < set_count; i++) {
2021 const char *old_name
2022 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2023 const char *name;
2024
2025 if (!old_name) {
2026 continue;
2027 }
2028
2030
2031 if (fc_strcasecmp(old_name, name)) {
2032 /* Setting's name changed */
2033 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2034 }
2035
2036 if (!gamestart_valid) {
2037 /* Older savegames saved these values even when they were not valid.
2038 * Silence warnings caused by them. */
2039 secfile_entry_ignore(loading->file, "settings.set%d.gamestart", i);
2040 secfile_entry_ignore(loading->file, "settings.set%d.gamesetdef", i);
2041 }
2042
2043 if (!fc_strcasecmp("compresstype", name)) {
2044 const char *val = secfile_lookup_str(loading->file,
2045 "settings.set%d.value", i);
2046 if (!fc_strcasecmp(val, "BZIP2")) {
2047#ifdef FREECIV_HAVE_LIBZSTD
2048 secfile_replace_str(loading->file, "ZSTD",
2049 "settings.set%d.value", i);
2050#elif FREECIV_HAVE_LIBLZMA
2051 secfile_replace_str(loading->file, "XZ",
2052 "settings.set%d.value", i);
2053#elif FREECIV_HAVE_LIBZ
2054 secfile_replace_str(loading->file, "LIBZ",
2055 "settings.set%d.value", i);
2056#else
2057 secfile_replace_str(loading->file, "PLAIN",
2058 "settings.set%d.value", i);
2059#endif
2060 }
2061
2062 if (gamestart_valid) {
2063 val = secfile_lookup_str(loading->file,
2064 "settings.set%d.gamestart", i);
2065 if (!fc_strcasecmp(val, "BZIP2")) {
2066#ifdef FREECIV_HAVE_LIBZSTD
2067 secfile_replace_str(loading->file, "ZSTD",
2068 "settings.set%d.gamestart", i);
2069#elif FREECIV_HAVE_LIBLZMA
2070 secfile_replace_str(loading->file, "XZ",
2071 "settings.set%d.gamestart", i);
2072#elif FREECIV_HAVE_LIBZ
2073 secfile_replace_str(loading->file, "LIBZ",
2074 "settings.set%d.gamestart", i);
2075#else
2076 secfile_replace_str(loading->file, "PLAIN",
2077 "settings.set%d.gamestart", i);
2078#endif
2079 }
2080 }
2081 } else if (!fc_strcasecmp("topology", name)) {
2082 struct setting *pset = setting_by_name(name);
2083 struct sf_cb_data info = { pset, TRUE };
2084 int val;
2085
2086 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2088 "settings.set%d.value", i)) {
2089 char wrap[100];
2090 char buf[100];
2091
2092 if (val & TF_OLD_WRAPX) {
2093 if (val & TF_OLD_WRAPY) {
2094 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2095 } else {
2096 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2097 }
2098 } else if (val & TF_OLD_WRAPY) {
2099 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2100 } else {
2101 fc_strlcpy(wrap, "", sizeof(wrap));
2102 }
2103
2104 if (val & TF_ISO) {
2105 if (val & TF_HEX) {
2106 setting_bitwise_set(pset, "ISO|HEX", nullptr, nullptr, 0);
2107 } else {
2108 setting_bitwise_set(pset, "ISO", nullptr, nullptr, 0);
2109 }
2110 } else if (val & TF_HEX) {
2111 setting_bitwise_set(pset, "HEX", nullptr, nullptr, 0);
2112 } else {
2113 setting_bitwise_set(pset, "", nullptr, nullptr, 0);
2114 }
2115
2116 setting_value_name(pset, FALSE, buf, sizeof(buf));
2118 "settings.set%d.value", i);
2119
2121 "wrap", "settings.set%d.name", set_count);
2123 wrap, "settings.set%d.value", set_count);
2124
2125 if (gamestart_valid) {
2126 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2128 "settings.set%d.gamestart", i)) {
2129 if (val & TF_OLD_WRAPX) {
2130 if (val & TF_OLD_WRAPY) {
2131 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2132 } else {
2133 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2134 }
2135 } else if (val & TF_OLD_WRAPY) {
2136 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2137 } else {
2138 fc_strlcpy(wrap, "", sizeof(wrap));
2139 }
2140
2141 if (val & TF_ISO) {
2142 if (val & TF_HEX) {
2143 setting_bitwise_set(pset, "ISO|HEX", nullptr, nullptr, 0);
2144 } else {
2145 setting_bitwise_set(pset, "ISO", nullptr, nullptr, 0);
2146 }
2147 } else if (val & TF_HEX) {
2148 setting_bitwise_set(pset, "HEX", nullptr, nullptr, 0);
2149 } else {
2150 setting_bitwise_set(pset, "", nullptr, nullptr, 0);
2151 }
2152
2153 setting_value_name(pset, FALSE, buf, sizeof(buf));
2155 "settings.set%d.gamestart", i);
2156
2158 wrap, "settings.set%d.gamestart", set_count);
2159 }
2160 }
2161
2162 set_count++;
2164 }
2165 } else if (!fc_strcasecmp("alltemperate", name)) {
2167 } else if (!fc_strcasecmp("singlepole", name)) {
2168 singlepole_idx = i;
2169 }
2170 }
2171
2172 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2173 int north_latitude, south_latitude;
2174 int north_idx, south_idx;
2176
2177 if (alltemperate_idx < 0
2179 "settings.set%d.value",
2181 /* Infer what would've been the ruleset default */
2183 }
2184
2185 if (singlepole_idx < 0
2187 "settings.set%d.value",
2188 singlepole_idx)) {
2189 /* Infer what would've been the ruleset default */
2191 }
2192
2193 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2194 * changes, that'll have to be handled in later migrations anyway */
2195 north_latitude = alltemperate ? 500 : 1000;
2196 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2197
2198 /* Replace alltemperate with northlatitude, and singlepole with
2199 * southlatitude. If only one of the two was given, add the other
2200 * at the end. */
2203
2204 secfile_replace_str(loading->file, "northlatitude",
2205 "settings.set%d.name", north_idx);
2206 secfile_replace_int(loading->file, north_latitude,
2207 "settings.set%d.value", north_idx);
2208
2209 secfile_replace_str(loading->file, "southlatitude",
2210 "settings.set%d.name", south_idx);
2211 secfile_replace_int(loading->file, south_latitude,
2212 "settings.set%d.value", south_idx);
2213
2214 if (gamestart_valid) {
2215 if (alltemperate_idx < 0
2217 "settings.set%d.gamestart",
2219 alltemperate =
2221 }
2222
2223 if (singlepole_idx < 0
2225 "settings.set%d.gamestart",
2226 singlepole_idx)) {
2228 }
2229
2230 north_latitude = alltemperate ? 500 : 1000;
2231 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2232
2233 secfile_replace_int(loading->file, north_latitude,
2234 "settings.set%d.gamestart", north_idx);
2235 secfile_replace_int(loading->file, south_latitude,
2236 "settings.set%d.gamestart", south_idx);
2237 }
2238
2239 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2240 /* only one was given and replaced ~> we added one new entry */
2241 set_count++;
2243 }
2244 }
2245
2246 if (count_changed) {
2248 "settings.set_count");
2249 }
2250 }
2251 }
2252
2253 {
2254 /* Turn old AI level field to a setting. */
2255 const char *level;
2256 enum ai_level lvl;
2257
2258 level = secfile_lookup_str_default(loading->file, nullptr, "game.level");
2259 if (level != nullptr && !fc_strcasecmp("Handicapped", level)) {
2260 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2262 } else {
2264 }
2265
2266 if (!ai_level_is_valid(lvl)) {
2267 log_sg("Invalid AI level \"%s\". "
2268 "Changed to \"%s\".", level,
2271 }
2272
2273 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2274 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2275
2276 if (gamestart_valid) {
2277 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2278 set_count);
2279 }
2280
2281 set_count++;
2282 secfile_replace_int(loading->file, set_count, "settings.set_count");
2283 }
2284
2285 if (format_class != SAVEGAME_2) {
2286 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2287 /* Older savegames had a bug that got_tech_multi was not saved. */
2288 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2289 for (i = 0; i < count; i++) {
2290 bool got_tech = FALSE;
2291 int bulbs = 0;
2292 bool got_tech_multi
2294 "research.r%d.got_tech_multi", i);
2295
2297 "research.r%d.got_tech", i)
2298 && secfile_lookup_int(loading->file, &bulbs,
2299 "research.r%d.bulbs", i)) {
2301 got_tech || got_tech_multi ? bulbs : 0,
2302 "research.r%d.free_bulbs", i);
2303 }
2304 }
2305 }
2306
2307 /* Older savegames unnecessarily saved diplstate type order.
2308 * Silence "unused entry" warnings about those. */
2309 {
2311 "savefile.diplstate_type_size");
2312
2313 for (i = 0; i < dscount; i++) {
2315 "savefile.diplstate_type_vector,%d", i);
2316 }
2317 }
2318
2319 /* Add wl_max_length entries for players */
2320 {
2321 player_slots_iterate(pslot) {
2322 int plrno = player_slot_index(pslot);
2323 int ncities;
2324 int cnro;
2325 size_t wlist_max_length = 0;
2326 bool first_city;
2327
2328 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2329 continue;
2330 }
2331
2333 "player%d.got_first_city",
2334 plrno);
2335 if (first_city) {
2336 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2337 int flagcount = 0;
2338 const char **flags_sg;
2339 size_t nval;
2340
2342
2344 "player%d.flags", plrno);
2345
2346 for (i = 0; i < nval; i++) {
2349
2351 }
2352
2354 "player%d.flags", plrno);
2355
2357 }
2358
2360 "player%d.ncities", plrno);
2361
2362 for (cnro = 0; cnro < ncities; cnro++) {
2364 "player%d.c%d.wl_length",
2365 plrno, cnro);
2366
2368
2369 if (format_class == SAVEGAME_3) {
2371 "player%d.c%d.original",
2372 plrno, cnro) != plrno) {
2374 "player%d.c%d.acquire_t",
2375 plrno, cnro);
2376 } else {
2378 "player%d.c%d.acquire_t",
2379 plrno, cnro);
2380 }
2381
2383 "player%d.c%d.wlcb",
2384 plrno, cnro);
2385 }
2386 }
2387
2389 "player%d.wl_max_length", plrno);
2390
2391 if (format_class == SAVEGAME_3) {
2392 int nunits;
2393 int unro;
2394 size_t olist_max_length = 0;
2395
2397 "player%d.nunits", plrno);
2398
2399 for (unro = 0; unro < nunits; unro++) {
2401 "player%d.u%d.orders_length",
2402 plrno, unro);
2403
2405 }
2406
2408 "player%d.orders_max_length", plrno);
2409
2411 "player%d.routes_max_length", plrno);
2412 }
2413
2415 }
2416}
2417
2418/************************************************************************/
2426{
2427 /* Check status and return if not OK (sg_success != TRUE). */
2428 sg_check_ret();
2429
2430 log_debug("Upgrading data from savegame to version 3.3.0");
2431
2432 /* World Peace has never started in the old savegame. */
2433 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2434
2435 if (format_class != SAVEGAME_2) {
2436 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2437
2438 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2439 }
2440
2441 /* Last turn change time as a float, not integer multiplied by 100 */
2442 {
2443 float tct = secfile_lookup_int_default(loading->file, 0,
2444 "game.last_turn_change_time") / 100.0;
2445
2446 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2447 }
2448
2449 {
2450 int ssa_count;
2451
2453 "savefile.server_side_agent_size");
2454 if (ssa_count > 0) {
2455 const char **modname;
2456 const char **savemod;
2457 int j;
2458 const char *aw_name = "AutoWorker";
2459
2460 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2461 "savefile.server_side_agent_list");
2462
2463 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2464
2465 for (j = 0; j < ssa_count; j++) {
2466 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2467 savemod[j] = aw_name;
2468 } else {
2469 savemod[j] = modname[j];
2470 }
2471 }
2472
2474 "savefile.server_side_agent_list");
2475
2476 free(savemod);
2477 }
2478 }
2479
2480 {
2481 int action_count;
2482
2484 "savefile.action_size");
2485
2486 if (action_count > 0) {
2487 const char **modname;
2488 const char **savemod;
2489 int j;
2490 const char *cc1_name = "Conquer City Shrink";
2491 const char *cc2_name = "Conquer City Shrink 2";
2492 const char *cc3_name = "Conquer City Shrink 3";
2493 const char *cc4_name = "Conquer City Shrink 4";
2494
2495 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2496 "savefile.action_vector");
2497
2499
2500 for (j = 0; j < action_count; j++) {
2501 if (!fc_strcasecmp("Conquer City", modname[j])) {
2502 savemod[j] = cc1_name;
2503 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
2504 savemod[j] = cc2_name;
2505 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
2506 savemod[j] = cc3_name;
2507 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
2508 savemod[j] = cc4_name;
2509 } else {
2510 savemod[j] = modname[j];
2511 }
2512 }
2513
2515 "savefile.action_vector");
2516
2517 free(savemod);
2518 }
2519 }
2520
2521 /* Add actions for unit activities */
2522 if (format_class == SAVEGAME_3) {
2523 loading->activities.size
2525 "savefile.activities_size");
2526 if (loading->activities.size) {
2527 loading->activities.order
2528 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2529 "savefile.activities_vector");
2530 sg_failure_ret(loading->activities.size != 0,
2531 "Failed to load activity order: %s",
2532 secfile_error());
2533 }
2534
2535 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2536 "savefile.action_size");
2537
2538 sg_failure_ret(loading->action.size > 0,
2539 "Failed to load action order: %s",
2540 secfile_error());
2541
2542 if (loading->action.size) {
2543 const char **modname;
2544 int j;
2545
2546 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2547 "savefile.action_vector");
2548
2549 loading->action.order = fc_calloc(loading->action.size,
2550 sizeof(*loading->action.order));
2551
2552 for (j = 0; j < loading->action.size; j++) {
2554
2555 if (real_action != nullptr) {
2556 loading->action.order[j] = real_action->id;
2557 } else {
2558 log_sg("Unknown action \'%s\'", modname[j]);
2559 loading->action.order[j] = ACTION_NONE;
2560 }
2561 }
2562
2563 free(modname);
2564 }
2565
2566 player_slots_iterate(pslot) {
2567 int plrno = player_slot_index(pslot);
2568 int nunits;
2569 int unro;
2570
2571 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2572 continue;
2573 }
2574
2576 "player%d.nunits", plrno);
2577
2578 for (unro = 0; unro < nunits; unro++) {
2579 int ei;
2580 int i;
2581 enum unit_activity activity;
2582 enum gen_action act;
2583
2585 "player%d.u%d.activity", plrno, unro);
2586
2587 if (ei >= 0 && ei < loading->activities.size) {
2588 bool found = FALSE;
2589
2590 activity = unit_activity_by_name(loading->activities.order[ei],
2592
2593 act = activity_default_action(activity);
2594
2595 for (i = 0; i < loading->action.size; i++) {
2596 if (act == loading->action.order[i]) {
2597 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2598 plrno, unro);
2599 found = TRUE;
2600 break;
2601 }
2602 }
2603
2604 if (!found) {
2605 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
2606 plrno, unro);
2607 }
2608 }
2609 }
2611 }
2612
2613 /* Researches */
2614 {
2615 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2616 int i;
2617
2618 for (i = 0; i < count; i++) {
2619 /* It's ok for old savegames to have these entries. */
2620 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
2621 }
2622 }
2623
2624 player_slots_iterate(pslot) {
2625 int plrno = player_slot_index(pslot);
2626 int ncities;
2627 int cnro;
2628
2629 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2630 continue;
2631 }
2632
2634 "player%d.dc_total", plrno);
2635
2636 for (cnro = 0; cnro < ncities; cnro++) {
2637 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
2638 plrno, cnro);
2639 }
2641}
2642
2643/************************************************************************/
2648{
2649 /* Check status and return if not OK (sg_success FALSE). */
2650 sg_check_ret();
2651
2652 /* Capital information was not saved in older savegames,
2653 * so we have no capital setup at all at the moment.
2654 * Best we can do is to do recalculation now. It might be
2655 * a bit off compared to the situation before the game was saved,
2656 * but definitely better than not setting capitals at all. */
2657 players_iterate_alive(pplayer) {
2658 update_capital(pplayer);
2660}
2661
2662/************************************************************************/
2670{
2671 /* Check status and return if not OK (sg_success != TRUE). */
2672 sg_check_ret();
2673
2674 log_debug("Upgrading data from savegame to version 3.4.0");
2675}
2676
2677/************************************************************************/
2681#ifdef FREECIV_DEV_SAVE_COMPAT
2682static void compat_load_dev(struct loaddata *loading)
2683{
2684 int game_version;
2685
2686 /* Check status and return if not OK (sg_success FALSE). */
2687 sg_check_ret();
2688
2689 log_verbose("Upgrading data between development revisions");
2690
2691 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2692 "No save version found");
2693
2694#ifdef FREECIV_DEV_SAVE_COMPAT_3_4
2695
2696 if (game_version < 3039100) {
2697 /* Before version number bump to 3.3.91 */
2698
2699 } /* Version < 3.3.91 */
2700
2701#endif /* FREECIV_DEV_SAVE_COMPAT_3_4 */
2702}
2703
2704/************************************************************************/
2708static void compat_post_load_dev(struct loaddata *loading)
2709{
2710 int game_version;
2711
2712 /* Check status and return if not OK (sg_success FALSE). */
2713 sg_check_ret();
2714
2715 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
2716 game_version = 2060000;
2717 }
2718
2719#ifdef FREECIV_DEV_SAVE_COMPAT_3_4
2720
2721 if (game_version < 3039100) {
2722 /* Before version number bump to 3.3.91 */
2723
2724 } /* Version < 3.3.91 */
2725
2726#endif /* FREECIV_DEV_SAVE_COMPAT_3_4 */
2727}
2728#endif /* FREECIV_DEV_SAVE_COMPAT */
2729
2730/************************************************************************/
2733enum ai_level ai_level_convert(int old_level)
2734{
2735 switch (old_level) {
2736 case 1:
2737 return AI_LEVEL_AWAY;
2738 case 2:
2739 return AI_LEVEL_NOVICE;
2740 case 3:
2741 return AI_LEVEL_EASY;
2742 case 5:
2743 return AI_LEVEL_NORMAL;
2744 case 7:
2745 return AI_LEVEL_HARD;
2746 case 8:
2747 return AI_LEVEL_CHEATING;
2748 case 10:
2749#ifdef FREECIV_DEBUG
2750 return AI_LEVEL_EXPERIMENTAL;
2751#else /* FREECIV_DEBUG */
2752 return AI_LEVEL_HARD;
2753#endif /* FREECIV_DEBUG */
2754 }
2755
2756 return ai_level_invalid();
2757}
2758
2759/************************************************************************/
2762enum barbarian_type barb_type_convert(int old_type)
2763{
2764 switch (old_type) {
2765 case 0:
2766 return NOT_A_BARBARIAN;
2767 case 1:
2768 return LAND_BARBARIAN;
2769 case 2:
2770 return SEA_BARBARIAN;
2771 }
2772
2773 return barbarian_type_invalid();
2774}
struct action * action_by_rule_name(const char *name)
Definition actions.c:1105
int action_number(const struct action *action)
Definition actions.c:1234
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_iterate_end
Definition actions.h:218
#define action_get_activity(_pact_)
Definition actions.h:464
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_NONE
Definition actions.h:59
struct @130::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:249
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
char * incite_cost
Definition comments.c:77
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define NO_TARGET
Definition fc_types.h:215
#define EC_SPECIAL
Definition fc_types.h:809
revolen_type
Definition fc_types.h:978
@ REVOLEN_RANDOM
Definition fc_types.h:980
@ REVOLEN_RANDQUICK
Definition fc_types.h:982
@ REVOLEN_FIXED
Definition fc_types.h:979
@ REVOLEN_QUICKENING
Definition fc_types.h:981
#define DIR8_ORIGIN
Definition fc_types.h:316
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:743
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_SAVETURNS
Definition game.h:685
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:571
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:703
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c:133
int len
Definition packhand.c:129
int player_slot_count(void)
Definition player.c:415
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
#define ANON_USER_NAME
Definition player.h:48
#define player_slots_iterate(_pslot)
Definition player.h:538
#define players_iterate_alive_end
Definition player.h:562
#define player_slots_iterate_end
Definition player.h:542
#define players_iterate_alive(_pplayer)
Definition player.h:557
void update_capital(struct player *pplayer)
Definition plrhand.c:731
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
bool secfile_entry_delete(struct section_file *secfile, const char *path,...)
bool entry_set_name(struct entry *pentry, const char *name)
bool secfile_lookup_enum_data(const struct section_file *secfile, int *pvalue, bool bitwise, secfile_enum_name_data_fn_t name_fn, secfile_data_t data, const char *path,...)
const struct entry_list * section_entries(const struct section *psection)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct section * secfile_section_by_name(const struct section_file *secfile, const char *name)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_replace_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
entry_type
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_replace_int(secfile, value, path,...)
#define entry_list_iterate_end
#define secfile_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define entry_list_iterate(entlist, pentry)
#define secfile_replace_float(secfile, value, path,...)
#define secfile_replace_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
int current_compat_ver(void)
Definition savecompat.c:233
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:273
bool sg_success
Definition savecompat.c:35
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:557
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:37
static struct compatibility compat[]
Definition savecompat.c:117
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:338
static void upgrade_unit_order_targets(struct unit *act_unit)
static void compat_load_030300(struct loaddata *loading, enum sgf_version format_class)
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:243
static const int compat_num
Definition savecompat.c:144
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:700
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:97
int char2num(char ch)
Definition savecompat.c:279
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:154
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:681
static int increase_secfile_turn_int(struct loaddata *loading, const char *key, int old_def, bool keep_default)
enum ai_level ai_level_convert(int old_level)
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:255
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:320
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:574
static void compat_load_030200(struct loaddata *loading, enum sgf_version format_class)
static void compat_post_load_030300(struct loaddata *loading, enum sgf_version format_class)
enum tile_special_type special_by_rule_name(const char *name)
Definition savecompat.c:294
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:205
static void compat_load_030400(struct loaddata *loading, enum sgf_version format_class)
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:310
static void compat_load_030100(struct loaddata *loading, enum sgf_version format_class)
static void insert_server_side_agent(struct loaddata *loading, enum sgf_version format_class)
#define compat_current
Definition savecompat.c:145
#define sg_check_ret(...)
Definition savecompat.h:148
#define sg_warn(condition, message,...)
Definition savecompat.h:158
tile_special_type
Definition savecompat.h:29
@ S_LAST
Definition savecompat.h:38
#define hex_chars
Definition savecompat.h:203
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:182
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:175
#define MAX_TRADE_ROUTES_OLD
Definition savecompat.h:218
sgf_version
Definition savecompat.h:27
@ SAVEGAME_2
Definition savecompat.h:27
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:144
const char * setcompat_S3_2_name_from_S3_1(const char *old_name)
Definition setcompat.c:62
struct setting * setting_by_name(const char *name)
Definition settings.c:3367
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4329
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4285
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const char * setting_bitwise_secfile_str(secfile_data_t data, int bit)
Definition settings.c:4126
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
struct packet_game_info info
Definition game.h:89
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@44::@46 server
int huts_absolute
Definition map_types.h:108
const load_version_func_t post_load
Definition savecompat.c:102
const load_version_func_t load
Definition savecompat.c:101
struct name_translation name
Definition specialist.h:31
Definition tile.h:50
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:139
int length
Definition unit.h:197
bool has_orders
Definition unit.h:195
enum unit_activity activity
Definition unit.h:158
enum gen_action action
Definition unit.h:159
struct unit::@83 orders
struct extra_type * activity_target
Definition unit.h:166
struct unit_order * list
Definition unit.h:200
enum server_side_agent ssa_controller
Definition unit.h:174
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:742
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:127
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define terrain_type_iterate_end
Definition terrain.h:273
void free_unit_orders(struct unit *punit)
Definition unit.c:1827
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:402
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2943
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
#define unit_tile(_pu)
Definition unit.h:408
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1091
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1274
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1313