Freeciv-3.3
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 "setcompat.h"
29#include "settings.h"
30#include "unittools.h"
31
32#include "savecompat.h"
33
35
36static char *special_names[] =
37 {
38 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
39 "Fallout", NULL
40 };
41
42/*
43 For each savefile format after 2.3.0, compatibility functions are defined
44 which translate secfile structures from previous version to that version;
45 all necessary compat functions are called in order to
46 translate between the file and current version. See sg_load_compat().
47
48 The integer version ID should be increased every time the format is changed.
49 If the change is not backwards compatible, please state the changes in the
50 following list and update the compat functions at the end of this file.
51
52 - what was added / removed
53 - when was it added / removed (date and version)
54 - when can additional capability checks be set to mandatory (version)
55 - which compatibility checks are needed and till when (version)
56
57 freeciv | what | date | id
58 --------+------------------------------------------------+------------+----
59 current | (mapped to current savegame format) | ----/--/-- | 0
60 | first version (svn17538) | 2010/07/05 | -
61 2.3.0 | 2.3.0 release | 2010/11/?? | 3
62 2.4.0 | 2.4.0 release | 201./../.. | 10
63 | * player ai type | |
64 | * delegation | |
65 | * citizens | |
66 | * save player color | |
67 | * "known" info format change | |
68 2.5.0 | 2.5.0 release | 201./../.. | 20
69 2.6.0 | 2.6.0 release | 201./../.. | 30
70 3.0.0 | 3.0.0 release | 201./../.. | 40
71 3.1.0 | 3.1.0 release | 201./../.. | 50
72 3.2.0 | 3.2.0 release | 202./../.. | 60
73 3.3.0 | 3.3.0 release (development) | 202./../.. | 70
74 | | |
75*/
76
84static void compat_post_load_030100(struct loaddata *loading,
86
87#ifdef FREECIV_DEV_SAVE_COMPAT
88static void compat_load_dev(struct loaddata *loading);
89static void compat_post_load_dev(struct loaddata *loading);
90#endif /* FREECIV_DEV_SAVE_COMPAT */
91
93
99
100/* The struct below contains the information about the savegame versions. It
101 * is identified by the version number (first element), which should be
102 * steadily increasing. It is saved as 'savefile.version'. The support
103 * string (first element of 'name') is not saved in the savegame; it is
104 * saved in settings files (so, once assigned, cannot be changed). The
105 * 'pretty' string (second element of 'name') can be changed if necessary
106 * For changes in the development version, edit the definitions above and
107 * add the needed code to load the old version below. Thus, old
108 * savegames can still be loaded while the main definition
109 * represents the current state of the art. */
110/* While developing freeciv 3.3.0, add the compatibility functions to
111 * - compat_load_030300 to load old savegame. */
112static struct compatibility compat[] = {
113 /* dummy; equal to the current version (last element) */
114 { 0, NULL, NULL },
115 /* version 1 and 2 is not used */
116 /* version 3: first savegame2 format, so no compat functions for translation
117 * from previous format */
118 { 3, NULL, NULL },
119 /* version 4 to 9 are reserved for possible changes in 2.3.x */
120 { 10, compat_load_020400, NULL },
121 /* version 11 to 19 are reserved for possible changes in 2.4.x */
122 { 20, compat_load_020500, NULL },
123 /* version 21 to 29 are reserved for possible changes in 2.5.x */
124 { 30, compat_load_020600, NULL },
125 /* version 31 to 39 are reserved for possible changes in 2.6.x */
126 { 40, compat_load_030000, NULL },
127 /* version 41 to 49 are reserved for possible changes in 3.0.x */
129 /* version 51 to 59 are reserved for possible changes in 3.1.x */
130 { 60, compat_load_030200, NULL },
131 /* version 61 to 69 are reserved for possible changes in 3.2.x */
132 { 70, compat_load_030300, NULL },
133 /* Current savefile version is listed above this line; it corresponds to
134 the definitions in this file. */
135};
136
137static const int compat_num = ARRAY_SIZE(compat);
138#define compat_current (compat_num - 1)
139
140/************************************************************************/
148{
149 int i;
150
151 /* Check status and return if not OK (sg_success FALSE). */
152 sg_check_ret();
153
154 loading->version = secfile_lookup_int_default(loading->file, -1,
155 "savefile.version");
156#ifdef FREECIV_DEBUG
157 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
158 loading->version);
159 if (loading->version > compat[compat_current].version) {
160 /* Debug build can (TRY TO!) load newer versions but ... */
161 log_error("Savegame version newer than this build found (%d > %d). "
162 "Trying to load the game nevertheless ...", loading->version,
164 }
165#else /* FREECIV_DEBUG */
166 sg_failure_ret(0 < loading->version
167 && loading->version <= compat[compat_current].version,
168 "Unknown savefile format version (%d).", loading->version);
169#endif /* FREECIV_DEBUG */
170
171
172 for (i = 0; i < compat_num; i++) {
173 if (loading->version < compat[i].version && compat[i].load != NULL) {
174 log_normal(_("Run compatibility function for version: <%d "
175 "(save file: %d; server: %d)."), compat[i].version,
178 }
179 }
180
181#ifdef FREECIV_DEV_SAVE_COMPAT
182 if (loading->version == compat[compat_current].version) {
184 }
185#endif /* FREECIV_DEV_SAVE_COMPAT */
186}
187
188/************************************************************************/
200{
201 int i;
202
203 /* Check status and return if not OK (sg_success FALSE). */
204 sg_check_ret();
205
206 for (i = 0; i < compat_num; i++) {
207 if (loading->version < compat[i].version
208 && compat[i].post_load != NULL) {
209 log_normal(_("Run post load compatibility function for version: <%d "
210 "(save file: %d; server: %d)."), compat[i].version,
213 }
214 }
215
216#ifdef FREECIV_DEV_SAVE_COMPAT
217 if (loading->version == compat[compat_current].version) {
219 }
220#endif /* FREECIV_DEV_SAVE_COMPAT */
221}
222
223/************************************************************************/
227{
229}
230
231/************************************************************************/
236char bin2ascii_hex(int value, int halfbyte_wanted)
237{
238 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
239}
240
241/************************************************************************/
249{
250 const char *pch;
251
252 if (ch == ' ') {
253 /* Sane value. It is unknow if there are savegames out there which
254 * need this fix. Savegame.c doesn't write such savegames
255 * (anymore) since the inclusion into CVS (2000-08-25). */
256 return 0;
257 }
258
260
261 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
262 "Unknown hex value: '%c' %d", ch, ch);
263 return (pch - hex_chars) << (halfbyte * 4);
264}
265
266static const char num_chars[] =
267 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
268
269/************************************************************************/
272int char2num(char ch)
273{
274 const char *pch;
275
277
279 "Unknown ascii value for num: '%c' %d", ch, ch);
280
281 return pch - num_chars;
282}
283
284/************************************************************************/
288{
289 int i;
290
291 for (i = 0; special_names[i] != NULL; i++) {
292 if (!strcmp(name, special_names[i])) {
293 return i;
294 }
295 }
296
297 return S_LAST;
298}
299
300/************************************************************************/
304{
305 fc_assert(type >= 0 && type < S_LAST);
306
307 return special_names[type];
308}
309
310/************************************************************************/
314{
316
319 }
320
321 return NULL;
322}
323
324/************************************************************************/
327struct extra_type *resource_by_identifier(const char identifier)
328{
330 if (presource->data.resource->id_old_save == identifier) {
331 return presource;
332 }
334
335 return NULL;
336}
337
338/* =======================================================================
339 * Compatibility functions for loading a game.
340 * ======================================================================= */
341
342/************************************************************************/
347{
348 /* Check status and return if not OK (sg_success FALSE). */
349 sg_check_ret();
350
351 log_debug("Upgrading data from savegame to version 2.4.0");
352
353 /* Add the default player AI. */
354 player_slots_iterate(pslot) {
355 int ncities, i, plrno = player_slot_index(pslot);
356
357 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
358 continue;
359 }
360
362 "player%d.ai_type", player_slot_index(pslot));
363
364 /* Create dummy citizens informations. We do not know if citizens are
365 * activated due to the fact that this information
366 * (game.info.citizen_nationality) is not available, but adding the
367 * information does no harm. */
369 "player%d.ncities", plrno);
370 if (ncities > 0) {
371 for (i = 0; i < ncities; i++) {
373 "player%d.c%d.size", plrno, i);
374 if (size > 0) {
376 "player%d.c%d.citizen%d", plrno, i, plrno);
377 }
378 }
379 }
380
382
383 /* Player colors are assigned at the end of player loading, as this
384 * needs information not available here. */
385
386 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
387 * workaround in later 2.3.x); see gna bug #19029.
388 * (The structure of this code is odd as it avoids relying on knowledge of
389 * xsize/ysize, which haven't been extracted from the savefile yet.) */
390 {
391 if (has_capability("knownv2",
392 secfile_lookup_str(loading->file, "savefile.options"))) {
393 /* This savefile contains known information in a sane format.
394 * Just move any entries to where 2.4.x+ expect to find them. */
395 struct section *map = secfile_section_by_name(loading->file, "map");
396
397 if (map != NULL) {
399 const char *name = entry_name(pentry);
400
401 if (!fc_strncmp(name, "kvb", 3)) {
402 /* Rename the "kvb..." entry to "k..." */
403 char *name2 = fc_strdup(name), *newname = name2 + 2;
404
405 *newname = 'k';
406 /* Savefile probably contains existing "k" entries, which are bogus
407 * so we trash them. */
408 secfile_entry_delete(loading->file, "map.%s", newname);
410 FC_FREE(name2);
411 }
413 }
414 /* Could remove "knownv2" from savefile.options, but it's doing
415 * no harm there. */
416 } else {
417 /* This savefile only contains known information in the broken
418 * format. Try to recover it to a sane format. */
419 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
420 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
421 const int maxslots = 128, maxmapsize = 512;
422 const int lines = maxslots/32;
423 int xsize = 0, y, l, j, x;
424 unsigned int known_row_old[lines * maxmapsize],
426 /* Process a map row at a time */
427 for (y = 0; y < maxmapsize; y++) {
428 /* Look for broken info to convert */
429 bool found = FALSE;
431 for (l = 0; l < lines; l++) {
432 for (j = 0; j < 8; j++) {
433 const char *s =
435 "map.k%02d_%04d", l * 8 + j, y);
436 if (s) {
437 found = TRUE;
438 if (xsize == 0) {
439 xsize = strlen(s);
440 }
441 sg_failure_ret(xsize == strlen(s),
442 "Inconsistent xsize in map.k%02d_%04d",
443 l * 8 + j, y);
444 for (x = 0; x < xsize; x++) {
445 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
446 }
447 }
448 }
449 }
450 if (found) {
451 /* At least one entry found for this row. Let's hope they were
452 * all there. */
453 /* Attempt to munge into sane format */
454 int p;
455 memset(known_row, 0, sizeof(known_row));
456 /* Iterate over possible player slots */
457 for (p = 0; p < maxslots; p++) {
458 l = p / 32;
459 for (x = 0; x < xsize; x++) {
460 /* This test causes bit-shifts of >=32 (undefined behaviour), but
461 * on common platforms, information happens not to be lost, just
462 * oddly arranged. */
463 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
464 known_row[l * xsize + x] |= (1u << (p - l * 32));
465 }
466 }
467 }
468 /* Save sane format back to memory representation of secfile for
469 * real loading code to pick up */
470 for (l = 0; l < lines; l++) {
471 for (j = 0; j < 8; j++) {
472 /* Save info for all slots (not just used ones). It's only
473 * memory, after all. */
474 char row[xsize+1];
475 for (x = 0; x < xsize; x++) {
476 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
477 }
478 row[xsize] = '\0';
480 "map.k%02d_%04d", l * 8 + j, y);
481 }
482 }
483 }
484 }
485 }
486 }
487
488 /* Server setting migration. */
489 {
490 int set_count;
491
492 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
493 int i, new_opt = set_count;
494 bool gamestart_valid
496 "settings.gamestart_valid");
497
498 for (i = 0; i < set_count; i++) {
499 const char *name
500 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
501
502 if (!name) {
503 continue;
504 }
505
506 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
507 * This is now controlled by the "autosaves" setting. */
508 if (!fc_strcasecmp("saveturns", name)) {
509 /* XXX: hardcodes details from GAME_AUTOSAVES_DEFAULT
510 * and settings.c:autosaves_name() (but these defaults reflect
511 * 2.3's behaviour). */
512 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
513 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
514 int nturns;
515
517 "settings.set%d.value", i)) {
518 if (nturns == 0) {
519 /* Invent a new "autosaves" setting */
521 "settings.set%d.value", new_opt);
522 /* Pick something valid for saveturns */
524 "settings.set%d.value", i);
525 } else {
527 "settings.set%d.value", new_opt);
528 }
529 } else {
530 log_sg("Setting '%s': %s", name, secfile_error());
531 }
532 if (gamestart_valid) {
534 "settings.set%d.gamestart", i)) {
535 if (nturns == 0) {
536 /* Invent a new "autosaves" setting */
538 "settings.set%d.gamestart", new_opt);
539 /* Pick something valid for saveturns */
541 "settings.set%d.gamestart", i);
542 } else {
544 "settings.set%d.gamestart", new_opt);
545 }
546 } else {
547 log_sg("Setting '%s': %s", name, secfile_error());
548 }
549 }
550 } else if (!fc_strcasecmp("autosaves", name)) {
551 /* Sanity check. This won't trigger on an option we've just
552 * invented, as the loop won't include it. */
553 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
554 "savefile. It may have been overridden.");
555 }
556 }
557 }
558 }
559}
560
561/************************************************************************/
564static const char *killcitizen_enum_str(secfile_data_t data, int bit)
565{
566 switch (bit) {
567 case UMT_LAND:
568 return "LAND";
569 case UMT_SEA:
570 return "SEA";
571 case UMT_BOTH:
572 return "BOTH";
573 }
574
575 return NULL;
576}
577
578/************************************************************************/
583{
584 const char *modname[] = { "Road", "Railroad" };
585 const char *old_activities_names[] = {
586 "Idle",
587 "Pollution",
588 "Unused Road",
589 "Mine",
590 "Irrigate",
591 "Mine",
592 "Irrigate",
593 "Fortified",
594 "Fortress",
595 "Sentry",
596 "Unused Railroad",
597 "Pillage",
598 "Goto",
599 "Explore",
600 "Transform",
601 "Unused",
602 "Unused Airbase",
603 "Fortifying",
604 "Fallout",
605 "Unused Patrol",
606 "Base"
607 };
608
609 /* Check status and return if not OK (sg_success FALSE). */
610 sg_check_ret();
611
612 log_debug("Upgrading data from savegame to version 2.5.0");
613
614 secfile_insert_int(loading->file, 2, "savefile.roads_size");
615 secfile_insert_int(loading->file, 0, "savefile.trait_size");
616
618 "savefile.roads_vector");
619
620 secfile_insert_int(loading->file, 19, "savefile.activities_size");
622 "savefile.activities_vector");
623
624 /* Server setting migration. */
625 {
626 int set_count;
627
628 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
629 int i;
630 bool gamestart_valid
632 "settings.gamestart_valid");
633 for (i = 0; i < set_count; i++) {
634 const char *name
635 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
636 if (!name) {
637 continue;
638 }
639 /* In 2.4.x and prior, "killcitizen" listed move types that
640 * killed citizens after successful attack. Now killcitizen
641 * is just boolean and classes affected are defined in ruleset. */
642 if (!fc_strcasecmp("killcitizen", name)) {
643 int value;
644
645 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
647 "settings.set%d.value", i)) {
648 /* Lowest bit of old killcitizen value indicates if
649 * land units should kill citizens. We take that as
650 * new boolean killcitizen value. */
651 if (value & 0x1) {
653 "settings.set%d.value", i);
654 } else {
656 "settings.set%d.value", i);
657 }
658 } else {
659 log_sg("Setting '%s': %s", name, secfile_error());
660 }
661 if (gamestart_valid) {
662 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
664 "settings.set%d.gamestart", i)) {
665 /* Lowest bit of old killcitizen value indicates if
666 * land units should kill citizens. We take that as
667 * new boolean killcitizen value. */
668 if (value & 0x1) {
670 "settings.set%d.gamestart", i);
671 } else {
673 "settings.set%d.gamestart", i);
674 }
675 } else {
676 log_sg("Setting '%s': %s", name, secfile_error());
677 }
678 }
679 }
680 }
681 }
682 }
683}
684
685/************************************************************************/
689{
690 switch (type) {
691 case REVOLEN_FIXED:
692 return "FIXED";
693 case REVOLEN_RANDOM:
694 return "RANDOM";
696 return "QUICKENING";
698 return "RANDQUICK";
699 }
700
701 return "";
702}
703
704/************************************************************************/
709{
710 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
711 int tsize;
712 int ti;
713 int turn;
714
715 /* Check status and return if not OK (sg_success FALSE). */
716 sg_check_ret();
717
718 log_debug("Upgrading data from savegame to version 2.6.0");
719
720 /* Terrain mapping table - use current ruleset as we have no way to know
721 * any other old values. */
722 ti = 0;
724 char buf[2];
725
726 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
728 buf[1] = '\0';
729 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
731
732 /* Server setting migration. */
733 {
734 int set_count;
735
736 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
737 char value_buffer[1024] = "";
738 char gamestart_buffer[1024] = "";
739 int i;
740 int dcost = -1;
741 int dstartcost = -1;
744 bool gamestart_valid
746 "settings.gamestart_valid");
747 int new_set_count;
748
749 for (i = 0; i < set_count; i++) {
750 const char *name
751 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
752 if (!name) {
753 continue;
754 }
755
756 /* In 2.5.x and prior, "spacerace" boolean controlled if
757 * spacerace victory condition was active. */
758 if (!fc_strcasecmp("spacerace", name)) {
759 bool value;
760
761 if (secfile_lookup_bool(loading->file, &value,
762 "settings.set%d.value", i)) {
763 if (value) {
764 if (value_buffer[0] != '\0') {
766 }
767 sz_strlcat(value_buffer, "SPACERACE");
768 }
769 } else {
770 log_sg("Setting '%s': %s", name, secfile_error());
771 }
772 if (secfile_lookup_bool(loading->file, &value,
773 "settings.set%d.gamestart", i)) {
774 if (value) {
775 if (gamestart_buffer[0] != '\0') {
777 }
778 sz_strlcat(gamestart_buffer, "SPACERACE");
779 }
780 } else {
781 log_sg("Setting '%s': %s", name, secfile_error());
782 }
783
784 /* We cannot delete old values from the secfile, or rather cannot
785 * change index of the later settings. Renumbering them is not easy as
786 * we don't know type of each setting we would encounter.
787 * So we keep old setting values and only add new "victories" setting. */
788 } else if (!fc_strcasecmp("alliedvictory", name)) {
789 bool value;
790
791 if (secfile_lookup_bool(loading->file, &value,
792 "settings.set%d.value", i)) {
793 if (value) {
794 if (value_buffer[0] != '\0') {
796 }
797 sz_strlcat(value_buffer, "ALLIED");
798 }
799 } else {
800 log_sg("Setting '%s': %s", name, secfile_error());
801 }
802 if (secfile_lookup_bool(loading->file, &value,
803 "settings.set%d.gamestart", i)) {
804 if (value) {
805 if (gamestart_buffer[0] != '\0') {
807 }
808 sz_strlcat(gamestart_buffer, "ALLIED");
809 }
810 } else {
811 log_sg("Setting '%s': %s", name, secfile_error());
812 }
813 } else if (!fc_strcasecmp("revolen", name)) {
814 int value;
815
816 if (secfile_lookup_int(loading->file, &value,
817 "settings.set%d.value", i)) {
818 /* 0 meant RANDOM 1-5 */
819 if (value == 0) {
822 "settings.set%d.value", i);
823 } else {
825 }
826 } else {
827 log_sg("Setting '%s': %s", name, secfile_error());
828 }
829 if (secfile_lookup_int(loading->file, &value,
830 "settings.set%d.gamestart", i)) {
831 /* 0 meant RANDOM 1-5 */
832 if (value == 0) {
835 "settings.set%d.gamestart", i);
836 } else {
838 }
839 } else {
840 log_sg("Setting '%s': %s", name, secfile_error());
841 }
842 } else if (!fc_strcasecmp("happyborders", name)) {
843 bool value;
844
845 if (secfile_lookup_bool(loading->file, &value,
846 "settings.set%d.value", i)) {
847 secfile_entry_delete(loading->file, "settings.set%d.value", i);
848 if (value) {
849 secfile_insert_str(loading->file, "NATIONAL",
850 "settings.set%d.value", i);
851 } else {
852 secfile_insert_str(loading->file, "DISABLED",
853 "settings.set%d.value", i);
854 }
855 } else {
856 log_sg("Setting '%s': %s", name, secfile_error());
857 }
858 if (secfile_lookup_bool(loading->file, &value,
859 "settings.set%d.gamestart", i)) {
860 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
861 if (value) {
862 secfile_insert_str(loading->file, "NATIONAL",
863 "settings.set%d.gamestart", i);
864 } else {
865 secfile_insert_str(loading->file, "DISABLED",
866 "settings.set%d.gamestart", i);
867 }
868 } else {
869 log_sg("Setting '%s': %s", name, secfile_error());
870 }
871 } else if (!fc_strcasecmp("team_pooled_research", name)) {
873 &team_pooled_research,
874 "settings.set%d.value", i),
875 "%s", secfile_error());
876 } else if (!fc_strcasecmp("diplcost", name)) {
877 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
878 if (secfile_lookup_int(loading->file, &dcost,
879 "settings.set%d.value", i)) {
880 } else {
881 log_sg("Setting '%s': %s", name, secfile_error());
882 }
883
885 "settings.set%d.gamestart", i)) {
886 } else {
887 log_sg("Setting '%s': %s", name, secfile_error());
888 }
889 } else if (!fc_strcasecmp("huts", name)) {
890 /* Scale of 'huts' changed. */
891 int hcount;
892
894 "settings.set%d.value", i)) {
895 } else {
896 log_sg("Setting '%s': %s", name, secfile_error());
897 }
898
899 /* Store old-style absolute value. */
901 }
902 }
903
904 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
905
906 if (dcost >= 0) {
907 new_set_count += 2;
908 }
909
910 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
911
912 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
913 set_count);
914 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
915 set_count);
916 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
917 set_count + 1);
918 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
919 set_count + 1);
920
921 if (dcost >= 0) {
922 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
923 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
924 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
925 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
926 }
927
928 if (gamestart_valid) {
929 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
930 set_count);
931 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
932 set_count + 1);
933
934 if (dcost >= 0) {
935 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
936 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
937 }
938 }
939 }
940 }
941
942 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
943 "Trait size: %s", secfile_error());
944
945 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
946
947 player_slots_iterate(pslot) {
948 int plrno = player_slot_index(pslot);
949 bool got_first_city;
950 int old_barb_type;
951 enum barbarian_type new_barb_type;
952 int i;
953 const char *name;
954 int score;
955 int units_num;
956
957 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
958 continue;
959 }
960
961 /* Renamed 'capital' to 'got_first_city'. */
963 "player%d.capital", plrno)) {
965 "player%d.got_first_city", plrno);
966 }
967
968 /* Add 'anonymous' qualifiers for user names */
969 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
971 "player%d.unassigned_user", plrno);
972
973 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
975 "player%d.unassigned_ranked", plrno);
976
977 /* Convert numeric barbarian type to textual */
979 "player%d.ai.is_barbarian", plrno);
982 "player%d.ai.barb_type", plrno);
983
984 /* Pre-2.6 didn't record when a player was created or died, so we have
985 * to assume they lived from the start of the game until last turn */
986 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
987
988 /* As if there never has been a war. */
989 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
990
991 /* Assume people were playing until current reload */
992 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
993
994 for (i = 0; i < tsize; i++) {
995 int val;
996
997 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
998 plrno, i);
999 if (val != -1) {
1000 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
1001 }
1002
1004 "player%d.trait.mod%d", plrno, i),
1005 "Trait mod: %s", secfile_error());
1006 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1007 }
1008
1009 score = secfile_lookup_int_default(loading->file, -1,
1010 "player%d.units_built", plrno);
1011 if (score >= 0) {
1012 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1013 }
1014
1015 score = secfile_lookup_int_default(loading->file, -1,
1016 "player%d.units_killed", plrno);
1017 if (score >= 0) {
1018 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1019 }
1020
1021 score = secfile_lookup_int_default(loading->file, -1,
1022 "player%d.units_lost", plrno);
1023 if (score >= 0) {
1024 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1025 }
1026
1027 /* Units orders. */
1029 "player%d.nunits",
1030 plrno);
1031
1032 for (i = 0; i < units_num; i++) {
1033 int len;
1034
1036 "player%d.u%d.orders_last_move_safe",
1037 plrno, i)) {
1038 continue;
1039 }
1040
1042 "player%d.u%d.orders_length",
1043 plrno, i);
1044 if (len > 0) {
1045 char orders_str[len + 1];
1046 char *p;
1047
1050 "player%d.u%d.orders_list",
1051 plrno, i));
1052 if ((p = strrchr(orders_str, 'm'))
1053 || (p = strrchr(orders_str, 'M'))) {
1054 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1056 "player%d.u%d.orders_list", plrno, i);
1057 }
1058 }
1059 }
1061
1062 /* Add specialist order - loading time order is ok here, as we will use
1063 * that when we in later part of compatibility conversion use the specialist
1064 * values */
1066 "savefile.specialists_size");
1067 {
1068 const char **modname;
1069 int i = 0;
1070
1072
1076
1078 "savefile.specialists_vector");
1079
1080 free(modname);
1081 }
1082
1083 /* Replace all city specialist count fields with correct names */
1084 player_slots_iterate(pslot) {
1085 int plrno = player_slot_index(pslot);
1086 int ncities;
1087 int i;
1088
1089 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1090 continue;
1091 }
1092
1093 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1094
1095 for (i = 0; i < ncities; i++) {
1096 int k = 0;
1097
1099 struct specialist *psp = specialist_by_number(sp);
1100 int count;
1101
1103 "player%d.c%d.n%s",
1105 "specialist error: %s", secfile_error());
1106 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1108 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1109 plrno, i, k++);
1111 }
1113
1114 /* Build [research]. */
1115 {
1116 const struct {
1117 const char *name;
1118 enum entry_type type;
1119 } entries[] = {
1120 { "goal_name", ENTRY_STR },
1121 { "techs", ENTRY_INT },
1122 { "futuretech", ENTRY_INT },
1123 { "bulbs_before", ENTRY_INT },
1124 { "saved_name", ENTRY_STR },
1125 { "bulbs", ENTRY_INT },
1126 { "now_name", ENTRY_STR },
1127 { "got_tech", ENTRY_BOOL },
1128 { "done", ENTRY_STR }
1129 };
1130
1132 int count = 0;
1133 int i;
1134
1135 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1136 researches[i] = -1;
1137 }
1138
1139 player_slots_iterate(pslot) {
1140 int plrno = player_slot_index(pslot);
1141 int ival;
1142 bool bval;
1143 const char *sval;
1144 int j;
1145
1146 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1147 continue;
1148 }
1149
1150 /* Get the research number. */
1151 if (team_pooled_research) {
1153 "player%d.team_no", plrno);
1154 } else {
1155 i = plrno;
1156 }
1157
1159 "Research out of bounds (%d)!", i);
1160
1161 /* Find the index in [research] section. */
1162 if (researches[i] == -1) {
1163 /* This is the first player for this research. */
1164 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1165 researches[i] = count;
1166 count++;
1167 }
1168 i = researches[i];
1169
1170 /* Move entries. */
1171 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1172 switch (entries[j].type) {
1173 case ENTRY_BOOL:
1174 if (secfile_lookup_bool(loading->file, &bval,
1175 "player%d.research.%s",
1176 plrno, entries[j].name)) {
1177 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1178 i, entries[j].name);
1179 }
1180 break;
1181 case ENTRY_INT:
1182 if (secfile_lookup_int(loading->file, &ival,
1183 "player%d.research.%s",
1184 plrno, entries[j].name)) {
1185 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1186 i, entries[j].name);
1187 }
1188 break;
1189 case ENTRY_STR:
1190 if ((sval = secfile_lookup_str(loading->file,
1191 "player%d.research.%s",
1192 plrno, entries[j].name))) {
1193 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1194 i, entries[j].name);
1195 }
1196 break;
1197 case ENTRY_FLOAT:
1199 "Research related entry marked as float.");
1200 break;
1203 break;
1204 case ENTRY_LONG_COMMENT:
1206 break;
1207 case ENTRY_ILLEGAL:
1209 break;
1210 }
1211 }
1213 secfile_insert_int(loading->file, count, "research.count");
1214 }
1215
1216 /* Add diplstate type order. */
1218 "savefile.diplstate_type_size");
1219 if (DS_LAST > 0) {
1220 const char **modname;
1221 int i;
1222 int j;
1223
1224 i = 0;
1225 modname = fc_calloc(DS_LAST, sizeof(*modname));
1226
1227 for (j = 0; j < DS_LAST; j++) {
1229 }
1230
1232 DS_LAST,
1233 "savefile.diplstate_type_vector");
1234 free(modname);
1235 }
1236
1237 /* Fix save games from Freeciv versions with a bug that made it view
1238 * "Never met" as closer than "Peace" or "Alliance". */
1239 player_slots_iterate(pslot) {
1240 int plrno = player_slot_index(pslot);
1241
1242 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1243 continue;
1244 }
1245
1247 int i = player_slot_index(pslot2);
1248 char buf[32];
1249 int current;
1250 int closest;
1251
1252 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1253 continue;
1254 }
1255
1256 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1257
1258 /* Read the current diplomatic state. */
1260 "%s.type",
1261 buf);
1262
1263 /* Read the closest diplomatic state. */
1265 "%s.max_state",
1266 buf);
1267
1268 if (closest == DS_NO_CONTACT
1269 && (current == DS_PEACE
1270 || current == DS_ALLIANCE)) {
1271 const char *name1 = secfile_lookup_str_default(loading->file, "",
1272 "player%d.name", plrno);
1273 const char *name2 = secfile_lookup_str_default(loading->file, "",
1274 "player%d.name", i);
1275 /* The current relationship is closer than what the save game
1276 * claims is the closes relationship ever. */
1277
1278 log_sg(_("The save game is wrong about what the closest"
1279 " relationship %s (player %d) and %s (player %d) have had is."
1280 " Fixing it..."),
1281 name1, plrno, name2, i);
1282
1283 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1284 }
1287}
1288
1289/************************************************************************/
1292static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1293 int old_def, bool keep_default)
1294{
1295 int value;
1296
1297 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1298
1299 if (value != old_def || !keep_default) {
1300 value++;
1301 secfile_replace_int(loading->file, value, "%s", key);
1302 }
1303
1304 return value;
1305}
1306
1307/************************************************************************/
1315{
1316 bool randsaved;
1317 int num_settings;
1318 bool started;
1319 int old_turn;
1320 int event_count;
1321 int i;
1322
1323 /* Check status and return if not OK (sg_success FALSE). */
1324 sg_check_ret();
1325
1326 log_debug("Upgrading data from savegame to version 3.0.0");
1327
1328 /* Rename "random.save" as "random.saved"
1329 * Note that it's not an error if a scenario does not have [random] at all. */
1330 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1331 secfile_insert_bool(loading->file, randsaved, "random.saved");
1332 }
1333
1334 /* Already started games should have their turn counts increased by 1 */
1335 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1336 started = TRUE;
1337
1338 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1340 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1341 } else {
1342 started = FALSE;
1343 }
1344
1345 player_slots_iterate(pslot) {
1346 int plrno = player_slot_index(pslot);
1347 const char *flag_names[1];
1348
1349 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1350 continue;
1351 }
1352
1353 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1354 plrno)) {
1356
1358 "player%d.flags", plrno);
1359 }
1360
1361 if (started) {
1362 int num = secfile_lookup_int_default(loading->file, 0,
1363 "player%d.nunits",
1364 plrno);
1365
1366 for (i = 0; i < num; i++) {
1367 char buf[64];
1368
1369 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1370
1372 }
1373
1374 num = secfile_lookup_int_default(loading->file, 0,
1375 "player%d.ncities", plrno);
1376
1377 for (i = 0; i < num; i++) {
1378 char buf[64];
1379
1380 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1381
1383 }
1384 }
1386
1387 /* Settings */
1389 "settings.set_count");
1390
1391 /* User meta server message is now a setting. */
1393 "game.meta_usermessage")) {
1394 const char *metamessage;
1395
1397 "game.meta_message");
1398
1399 /* Insert the meta message as a setting */
1400 secfile_insert_str(loading->file, "metamessage",
1401 "settings.set%d.name", num_settings);
1403 "settings.set%d.value", num_settings);
1404 secfile_insert_str(loading->file, "",
1405 "settings.set%d.gamestart", num_settings);
1406 num_settings++;
1407 }
1408
1409 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1410
1411 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1412
1413 for (i = 0; i < event_count; i++) {
1414 const char *etype;
1415
1416 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1417
1418 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1419 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1420 "event_cache.events%d.event", i);
1421 }
1422 }
1423}
1424
1425/************************************************************************/
1430{
1431 int ssa_size;
1432
1433 if (format_class == SAVEGAME_2) {
1434 /* Handled in savegame2 */
1435 return;
1436 }
1437
1439 "savefile.server_side_agent_size");
1440
1441 if (ssa_size != 0) {
1442 /* Already inserted. */
1443 return;
1444 }
1445
1446 /* Add server side agent order. */
1448 "savefile.server_side_agent_size");
1449 if (SSA_COUNT > 0) {
1450 const char **modname;
1451 int i;
1452 int j;
1453
1454 i = 0;
1455 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1456
1457 for (j = 0; j < SSA_COUNT; j++) {
1459 }
1460
1462 SSA_COUNT,
1463 "savefile.server_side_agent_list");
1464 free(modname);
1465 }
1466
1467 /* Insert server_side_agent unit field. */
1468 player_slots_iterate(pslot) {
1469 int unit;
1470 int units_num;
1471 int plrno = player_slot_index(pslot);
1472
1473 if (secfile_section_lookup(loading->file, "player%d", plrno)
1474 == NULL) {
1475 continue;
1476 }
1477
1478 /* Number of units the player has. */
1480 "player%d.nunits",
1481 plrno);
1482
1483 for (unit = 0; unit < units_num; unit++) {
1484 bool ai;
1485
1487 "player%d.u%d.server_side_agent",
1488 plrno, unit)
1489 != NULL) {
1490 /* Already updated? */
1491 continue;
1492 }
1493
1495 "player%d.u%d.ai",
1496 plrno, unit);
1497
1498 if (ai) {
1499 /* Autoworker and Autoexplore are separated by
1500 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1502 "player%d.u%d.server_side_agent",
1503 plrno, unit);
1504 } else {
1506 "player%d.u%d.server_side_agent",
1507 plrno, unit);
1508 }
1509 }
1511}
1512
1513/************************************************************************/
1521{
1522 /* Check status and return if not OK (sg_success FALSE). */
1523 sg_check_ret();
1524
1525 log_debug("Upgrading data from savegame to version 3.1.0");
1526
1527 /* Actions are now stored by number. */
1528 player_slots_iterate(pslot) {
1529 int unit;
1530 int units_num;
1531 int plrno = player_slot_index(pslot);
1532
1533 if (secfile_section_lookup(loading->file, "player%d", plrno)
1534 == NULL) {
1535 continue;
1536 }
1537
1538 /* Number of units the player has. */
1540 "player%d.nunits",
1541 plrno);
1542
1543 for (unit = 0; unit < units_num; unit++) {
1544 const char *action_unitstr;
1545 int order_len;
1546
1548 "player%d.u%d.orders_length",
1549 plrno, unit);
1550
1552 "player%d.u%d.action_list",
1553 plrno, unit))) {
1554 int order_num;
1555
1558 }
1559
1560 for (order_num = 0; order_num < order_len; order_num++) {
1562
1563 if (action_unitstr[order_num] == '?') {
1565 } else {
1567 }
1568
1569 if (order_num == 0) {
1570 /* The start of a vector has no number. */
1572 "player%d.u%d.action_vec",
1573 plrno, unit);
1574 } else {
1576 "player%d.u%d.action_vec,%d",
1577 plrno, unit, order_num);
1578 }
1579 }
1580 }
1581 }
1583
1584 {
1585 int action_count;
1586
1588 "savefile.action_size");
1589
1590 if (action_count > 0) {
1591 const char **modname;
1592 const char **savemod;
1593 int j;
1594 const char *dur_name = "Disband Unit Recover";
1595
1596 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1597 "savefile.action_vector");
1598
1600
1601 for (j = 0; j < action_count; j++) {
1602 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1603 savemod[j] = dur_name;
1604 } else {
1605 savemod[j] = modname[j];
1606 }
1607 }
1608
1610 "savefile.action_vector");
1611
1612 free(savemod);
1613 }
1614 }
1615
1616 /* Server setting migration. */
1617 {
1618 int set_count;
1619
1620 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1621 int i;
1622 bool gamestart_valid
1624 "settings.gamestart_valid");
1625
1626 /* Only add gamesetdef if gamestart is valid at all */
1627 if (gamestart_valid) {
1628 for (i = 0; i < set_count; i++) {
1629 const char *name
1630 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1631
1632 if (!name) {
1633 continue;
1634 }
1635
1637 "settings.set%d.gamesetdef", i);
1638 }
1639 }
1640 }
1641 }
1642
1643 /* Explicit server side agent was new in 3.1 */
1645}
1646
1647/************************************************************************/
1651{
1652 int i;
1653
1654 for (i = 0; i < act_unit->orders.length; i++) {
1655 struct unit_order *order = &act_unit->orders.list[i];
1656
1657 if (order->order != ORDER_ACTIVITY) {
1658 continue;
1659 }
1660
1661 switch (order->activity) {
1662 case ACTIVITY_CLEAN:
1663 case ACTIVITY_MINE:
1664 case ACTIVITY_IRRIGATE:
1665 case ACTIVITY_PLANT:
1666 case ACTIVITY_CULTIVATE:
1667 case ACTIVITY_TRANSFORM:
1668 case ACTIVITY_CONVERT:
1670 case ACTIVITY_BASE:
1671 case ACTIVITY_GEN_ROAD:
1672 case ACTIVITY_PILLAGE:
1673 action_iterate(act_id) {
1674 struct action *paction = action_by_number(act_id);
1675
1676 if (action_get_activity(paction) == order->activity) {
1677 order->order = ORDER_PERFORM_ACTION;
1678 order->action = action_number(paction);
1679 order->activity = ACTIVITY_LAST;
1680 break;
1681 }
1683 break;
1684 case ACTIVITY_SENTRY:
1685 /* Not an action */
1686 break;
1687 case ACTIVITY_EXPLORE:
1688 case ACTIVITY_IDLE:
1689 case ACTIVITY_GOTO:
1690 case ACTIVITY_FORTIFIED:
1691 case ACTIVITY_LAST:
1692 log_error("Activity %d is not supposed to appear in unit orders",
1693 order->activity);
1694 break;
1695 }
1696 }
1697}
1698
1699/************************************************************************/
1703{
1704 switch (dir) {
1705 case DIR8_NORTH:
1706 return DIR8_SOUTH;
1707 case DIR8_NORTHEAST:
1708 return DIR8_SOUTHWEST;
1709 case DIR8_EAST:
1710 return DIR8_WEST;
1711 case DIR8_SOUTHEAST:
1712 return DIR8_NORTHWEST;
1713 case DIR8_SOUTH:
1714 return DIR8_NORTH;
1715 case DIR8_SOUTHWEST:
1716 return DIR8_NORTHEAST;
1717 case DIR8_WEST:
1718 return DIR8_EAST;
1719 case DIR8_NORTHWEST:
1720 return DIR8_SOUTHEAST;
1721 }
1722
1723 return DIR8_ORIGIN;
1724}
1725
1726/************************************************************************/
1730{
1731 int i;
1732 struct tile *current_tile;
1733 struct tile *tgt_tile;
1734
1735 if (!unit_has_orders(act_unit)) {
1736 return;
1737 }
1738
1739 /* The order index is for the unit at its current tile. */
1740 current_tile = unit_tile(act_unit);
1741
1742 /* Rewind to the beginning of the orders */
1743 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1744 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1745
1746 if (!(prev_order->order == ORDER_PERFORM_ACTION
1750 current_tile = mapstep(&(wld.map), current_tile,
1751 dir_opposite(prev_order->dir));
1752 }
1753 }
1754
1755 /* Upgrade to explicit target tile */
1756 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1757 struct unit_order *order = &act_unit->orders.list[i];
1758
1759 if (order->order == ORDER_PERFORM_ACTION
1760 && order->target != NO_TARGET) {
1761 /* The target is already specified in the new format. */
1762
1763 /* The index_to_tile() call has no side-effects that we
1764 * would want also in NDEBUG builds. */
1765 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1766 return;
1767 }
1768
1769 if (!direction8_is_valid(order->dir)) {
1770 /* The target of the action is on the actor's tile. */
1771 tgt_tile = current_tile;
1772 } else {
1773 /* The target of the action is on a tile next to the actor. */
1774 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1775 }
1776
1777 if (order->order == ORDER_PERFORM_ACTION) {
1778 if (tgt_tile != NULL) {
1779 struct action *paction = action_by_number(order->action);
1780
1781 order->target = tgt_tile->index;
1782 /* Leave no traces. */
1783 order->dir = DIR8_ORIGIN;
1784
1786 /* The action moves the unit to the target tile (unless this is the
1787 * final order) */
1790 || i == act_unit->orders.length - 1);
1791 current_tile = tgt_tile;
1792 }
1793 } else {
1794 current_tile = NULL;
1795 }
1796 } else {
1797 current_tile = tgt_tile;
1798 }
1799 }
1800
1801 if (current_tile == NULL) {
1802 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1804 }
1805}
1806
1807/************************************************************************/
1811{
1812 players_iterate_alive(pplayer) {
1813 unit_list_iterate(pplayer->units, punit) {
1816 }
1819}
1820
1821/************************************************************************/
1826{
1827 /* Check status and return if not OK (sg_success FALSE). */
1828 sg_check_ret();
1829
1830 /* Action orders were new in 3.0 */
1831 if (format_class == SAVEGAME_3) {
1832 /* Only 3.0 savegames may have "Attack" action orders. */
1833 players_iterate_alive(pplayer) {
1834 unit_list_iterate(pplayer->units, punit) {
1835 int i;
1836
1837 if (!punit->has_orders) {
1838 continue;
1839 }
1840
1842 || punit->orders.list != NULL, continue);
1843
1844 for (i = 0; i < punit->orders.length; i++) {
1845 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1851 }
1852
1853 /* Production targeted actions were split from building targeted
1854 * actions in 3.1. The building sub target encoding changed. */
1856 && ((punit->orders.list[i].action
1858 || (punit->orders.list[i].action
1860 punit->orders.list[i].sub_target -= 1;
1861 }
1863 && (punit->orders.list[i].action
1865 && punit->orders.list[i].sub_target == -1) {
1868 }
1870 && (punit->orders.list[i].action
1872 && punit->orders.list[i].sub_target == -1) {
1875 }
1876 }
1879 }
1880
1881 /* Explicit server side agent was new in 3.1 */
1883
1884 /* Some activities should only be ordered in action orders. */
1885 players_iterate_alive(pplayer) {
1886 unit_list_iterate(pplayer->units, punit) {
1890
1891 /* Unit order action target isn't dir anymore */
1892 players_iterate_alive(pplayer) {
1893 unit_list_iterate(pplayer->units, punit) {
1897
1898 /* Backward compatibility: if we had any open-ended orders (pillage)
1899 * in the savegame, assign specific targets now */
1900 players_iterate_alive(pplayer) {
1901 unit_list_iterate(pplayer->units, punit) {
1903 &punit->activity,
1907}
1908
1909/************************************************************************/
1917{
1918 int i;
1919 int count;
1920 int set_count;
1921 bool gamestart_valid = FALSE;
1922
1923 /* Check status and return if not OK (sg_success FALSE). */
1924 sg_check_ret();
1925
1926 log_debug("Upgrading data from savegame to version 3.2.0");
1927
1928 {
1929 const char *str = secfile_lookup_str_default(loading->file, NULL,
1930 "savefile.orig_version");
1931
1932 if (str == NULL) {
1933 /* Make sure CURRENTLY running version does not
1934 * end as orig_version when we resave. */
1935 if (format_class == SAVEGAME_3) {
1936 secfile_insert_str(loading->file, "old savegame3, or older",
1937 "savefile.orig_version");
1938 } else {
1940
1941 secfile_insert_str(loading->file, "savegame2, or older",
1942 "savefile.orig_version");
1943 }
1944 }
1945 }
1946
1947 {
1948 int action_count;
1949
1951 "savefile.action_size");
1952
1953 if (action_count > 0) {
1954 const char **modname;
1955 const char **savemod;
1956 int j;
1957 const char *dur_name = "Transport Deboard";
1958 const char *clean_name = "Clean";
1959
1960 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1961 "savefile.action_vector");
1962
1964
1965 for (j = 0; j < action_count; j++) {
1966 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1967 savemod[j] = dur_name;
1968 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1969 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1970 savemod[j] = clean_name;
1971 } else {
1972 savemod[j] = modname[j];
1973 }
1974 }
1975
1977 "savefile.action_vector");
1978
1979 free(savemod);
1980 }
1981 }
1982
1983 {
1984 int activities_count;
1985
1987 "savefile.activities_size");
1988
1989 if (activities_count > 0) {
1990 const char **modname;
1991 const char **savemod;
1992 int j;
1993 const char *clean_name = "Clean";
1994
1995 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1996 "savefile.activities_vector");
1997
1999
2000 for (j = 0; j < activities_count; j++) {
2001 if (!fc_strcasecmp("Pollution", modname[j])
2002 || !fc_strcasecmp("Fallout", modname[j])) {
2003 savemod[j] = clean_name;
2004 } else {
2005 savemod[j] = modname[j];
2006 }
2007 }
2008
2010 "savefile.activities_vector");
2011
2012 free(savemod);
2013 }
2014 }
2015
2016 /* Server setting migration. */
2017 {
2018 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2019 int alltemperate_idx = -1, singlepole_idx = -1;
2020 bool count_changed = FALSE;
2021
2024 "settings.gamestart_valid");
2025
2026 for (i = 0; i < set_count; i++) {
2027 const char *old_name
2028 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2029 const char *name;
2030
2031 if (!old_name) {
2032 continue;
2033 }
2034
2036
2037 if (fc_strcasecmp(old_name, name)) {
2038 /* Setting's name changed */
2039 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2040 }
2041
2042 if (!gamestart_valid) {
2043 /* Older savegames saved these values even when they were not valid.
2044 * Silence warnings caused by them. */
2045 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2046 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2047 }
2048
2049 if (!fc_strcasecmp("compresstype", name)) {
2050 const char *val = secfile_lookup_str(loading->file,
2051 "settings.set%d.value", i);
2052 if (!fc_strcasecmp(val, "BZIP2")) {
2053#ifdef FREECIV_HAVE_LIBZSTD
2054 secfile_replace_str(loading->file, "ZSTD",
2055 "settings.set%d.value", i);
2056#elif FREECIV_HAVE_LIBLZMA
2057 secfile_replace_str(loading->file, "XZ",
2058 "settings.set%d.value", i);
2059#elif FREECIV_HAVE_LIBZ
2060 secfile_replace_str(loading->file, "LIBZ",
2061 "settings.set%d.value", i);
2062#else
2063 secfile_replace_str(loading->file, "PLAIN",
2064 "settings.set%d.value", i);
2065#endif
2066 }
2067
2068 if (gamestart_valid) {
2069 val = secfile_lookup_str(loading->file,
2070 "settings.set%d.gamestart", i);
2071 if (!fc_strcasecmp(val, "BZIP2")) {
2072#ifdef FREECIV_HAVE_LIBZSTD
2073 secfile_replace_str(loading->file, "ZSTD",
2074 "settings.set%d.gamestart", i);
2075#elif FREECIV_HAVE_LIBLZMA
2076 secfile_replace_str(loading->file, "XZ",
2077 "settings.set%d.gamestart", i);
2078#elif FREECIV_HAVE_LIBZ
2079 secfile_replace_str(loading->file, "LIBZ",
2080 "settings.set%d.gamestart", i);
2081#else
2082 secfile_replace_str(loading->file, "PLAIN",
2083 "settings.set%d.gamestart", i);
2084#endif
2085 }
2086 }
2087 } else if (!fc_strcasecmp("topology", name)) {
2088 struct setting *pset = setting_by_name(name);
2089 struct sf_cb_data info = { pset, TRUE };
2090 int val;
2091
2092 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2094 "settings.set%d.value", i)) {
2095 char wrap[100];
2096 char buf[100];
2097
2098 if (val & TF_OLD_WRAPX) {
2099 if (val & TF_OLD_WRAPY) {
2100 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2101 } else {
2102 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2103 }
2104 } else if (val & TF_OLD_WRAPY) {
2105 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2106 } else {
2107 fc_strlcpy(wrap, "", sizeof(wrap));
2108 }
2109
2110 if (val & TF_ISO) {
2111 if (val & TF_HEX) {
2112 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2113 } else {
2114 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2115 }
2116 } else if (val & TF_HEX) {
2117 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2118 } else {
2120 }
2121
2122 setting_value_name(pset, FALSE, buf, sizeof(buf));
2124 "settings.set%d.value", i);
2125
2127 "wrap", "settings.set%d.name", set_count);
2129 wrap, "settings.set%d.value", set_count);
2130
2131 if (gamestart_valid) {
2132 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2134 "settings.set%d.gamestart", i)) {
2135 if (val & TF_OLD_WRAPX) {
2136 if (val & TF_OLD_WRAPY) {
2137 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2138 } else {
2139 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2140 }
2141 } else if (val & TF_OLD_WRAPY) {
2142 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2143 } else {
2144 fc_strlcpy(wrap, "", sizeof(wrap));
2145 }
2146
2147 if (val & TF_ISO) {
2148 if (val & TF_HEX) {
2149 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2150 } else {
2151 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2152 }
2153 } else if (val & TF_HEX) {
2154 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2155 } else {
2157 }
2158
2159 setting_value_name(pset, FALSE, buf, sizeof(buf));
2161 "settings.set%d.gamestart", i);
2162
2164 wrap, "settings.set%d.gamestart", set_count);
2165 }
2166 }
2167
2168 set_count++;
2170 }
2171 } else if (!fc_strcasecmp("alltemperate", name)) {
2173 } else if (!fc_strcasecmp("singlepole", name)) {
2174 singlepole_idx = i;
2175 }
2176 }
2177
2178 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2179 int north_latitude, south_latitude;
2180 int north_idx, south_idx;
2182
2183 if (alltemperate_idx < 0
2185 "settings.set%d.value",
2187 /* Infer what would've been the ruleset default */
2189 }
2190
2191 if (singlepole_idx < 0
2193 "settings.set%d.value",
2194 singlepole_idx)) {
2195 /* Infer what would've been the ruleset default */
2197 }
2198
2199 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2200 * changes, that'll have to be handled in later migrations anyway */
2201 north_latitude = alltemperate ? 500 : 1000;
2202 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2203
2204 /* Replace alltemperate with northlatitude, and singlepole with
2205 * southlatitude. If only one of the two was given, add the other
2206 * at the end. */
2209
2210 secfile_replace_str(loading->file, "northlatitude",
2211 "settings.set%d.name", north_idx);
2212 secfile_replace_int(loading->file, north_latitude,
2213 "settings.set%d.value", north_idx);
2214
2215 secfile_replace_str(loading->file, "southlatitude",
2216 "settings.set%d.name", south_idx);
2217 secfile_replace_int(loading->file, south_latitude,
2218 "settings.set%d.value", south_idx);
2219
2220 if (gamestart_valid) {
2221 if (alltemperate_idx < 0
2223 "settings.set%d.gamestart",
2225 alltemperate =
2227 }
2228
2229 if (singlepole_idx < 0
2231 "settings.set%d.gamestart",
2232 singlepole_idx)) {
2234 }
2235
2236 north_latitude = alltemperate ? 500 : 1000;
2237 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2238
2239 secfile_replace_int(loading->file, north_latitude,
2240 "settings.set%d.gamestart", north_idx);
2241 secfile_replace_int(loading->file, south_latitude,
2242 "settings.set%d.gamestart", south_idx);
2243 }
2244
2245 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2246 /* only one was given and replaced ~> we added one new entry */
2247 set_count++;
2249 }
2250 }
2251
2252 if (count_changed) {
2254 "settings.set_count");
2255 }
2256 }
2257 }
2258
2259 {
2260 /* Turn old AI level field to a setting. */
2261 const char *level;
2262 enum ai_level lvl;
2263
2264 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2265 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2266 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2268 } else {
2270 }
2271
2272 if (!ai_level_is_valid(lvl)) {
2273 log_sg("Invalid AI level \"%s\". "
2274 "Changed to \"%s\".", level,
2277 }
2278
2279 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2280 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2281
2282 if (gamestart_valid) {
2283 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2284 set_count);
2285 }
2286
2287 set_count++;
2288 secfile_replace_int(loading->file, set_count, "settings.set_count");
2289 }
2290
2291 if (format_class != SAVEGAME_2) {
2292 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2293 /* Older savegames had a bug that got_tech_multi was not saved. */
2294 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2295 for (i = 0; i < count; i++) {
2296 bool got_tech = FALSE;
2297 int bulbs = 0;
2298 bool got_tech_multi
2300 "research.r%d.got_tech_multi", i);
2301
2303 "research.r%d.got_tech", i)
2304 && secfile_lookup_int(loading->file, &bulbs,
2305 "research.r%d.bulbs", i)) {
2307 got_tech || got_tech_multi ? bulbs : 0,
2308 "research.r%d.free_bulbs", i);
2309 }
2310 }
2311 }
2312
2313 /* Older savegames unnecessarily saved diplstate type order.
2314 * Silence "unused entry" warnings about those. */
2315 {
2317 "savefile.diplstate_type_size");
2318
2319 for (i = 0; i < dscount; i++) {
2321 "savefile.diplstate_type_vector,%d", i);
2322 }
2323 }
2324
2325 /* Add wl_max_length entries for players */
2326 {
2327 player_slots_iterate(pslot) {
2328 int plrno = player_slot_index(pslot);
2329 int ncities;
2330 int cnro;
2331 size_t wlist_max_length = 0;
2332 bool first_city;
2333
2334 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2335 continue;
2336 }
2337
2339 "player%d.got_first_city",
2340 plrno);
2341 if (first_city) {
2342 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2343 int flagcount = 0;
2344 const char **flags_sg;
2345 size_t nval;
2346
2348
2350 "player%d.flags", plrno);
2351
2352 for (i = 0; i < nval; i++) {
2355
2357 }
2358
2360 "player%d.flags", plrno);
2361
2363 }
2364
2366 "player%d.ncities", plrno);
2367
2368 for (cnro = 0; cnro < ncities; cnro++) {
2370 "player%d.c%d.wl_length",
2371 plrno, cnro);
2372
2374
2375 if (format_class == SAVEGAME_3) {
2377 "player%d.c%d.original",
2378 plrno, cnro) != plrno) {
2380 "player%d.c%d.acquire_t",
2381 plrno, cnro);
2382 } else {
2384 "player%d.c%d.acquire_t",
2385 plrno, cnro);
2386 }
2387
2389 "player%d.c%d.wlcb",
2390 plrno, cnro);
2391 }
2392 }
2393
2395 "player%d.wl_max_length", plrno);
2396
2397 if (format_class == SAVEGAME_3) {
2398 int nunits;
2399 int unro;
2400 size_t olist_max_length = 0;
2401
2403 "player%d.nunits", plrno);
2404
2405 for (unro = 0; unro < nunits; unro++) {
2407 "player%d.u%d.orders_length",
2408 plrno, unro);
2409
2411 }
2412
2414 "player%d.orders_max_length", plrno);
2415
2417 "player%d.routes_max_length", plrno);
2418 }
2419
2421 }
2422}
2423
2424/************************************************************************/
2432{
2433 /* Check status and return if not OK (sg_success != TRUE). */
2434 sg_check_ret();
2435
2436 log_debug("Upgrading data from savegame to version 3.3.0");
2437
2438 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2439
2440 /* World Peace has never started in the old savegame. */
2441 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2442 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2443
2444 {
2445 int ssa_count;
2446
2448 "savefile.server_side_agent_size");
2449 if (ssa_count > 0) {
2450 const char **modname;
2451 const char **savemod;
2452 int j;
2453 const char *aw_name = "AutoWorker";
2454
2455 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2456 "savefile.server_side_agent_list");
2457
2458 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2459
2460 for (j = 0; j < ssa_count; j++) {
2461 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2462 savemod[j] = aw_name;
2463 } else {
2464 savemod[j] = modname[j];
2465 }
2466 }
2467
2469 "savefile.server_side_agent_list");
2470
2471 free(savemod);
2472 }
2473 }
2474
2475 /* Add actions for unit activities */
2476 if (format_class == SAVEGAME_3) {
2477 loading->activities.size
2479 "savefile.activities_size");
2480 if (loading->activities.size) {
2481 loading->activities.order
2482 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2483 "savefile.activities_vector");
2484 sg_failure_ret(loading->activities.size != 0,
2485 "Failed to load activity order: %s",
2486 secfile_error());
2487 }
2488
2489 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2490 "savefile.action_size");
2491
2492 sg_failure_ret(loading->action.size > 0,
2493 "Failed to load action order: %s",
2494 secfile_error());
2495
2496 if (loading->action.size) {
2497 const char **modname;
2498 int j;
2499
2500 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2501 "savefile.action_vector");
2502
2503 loading->action.order = fc_calloc(loading->action.size,
2504 sizeof(*loading->action.order));
2505
2506 for (j = 0; j < loading->action.size; j++) {
2508
2509 if (real_action) {
2510 loading->action.order[j] = real_action->id;
2511 } else {
2512 log_sg("Unknown action \'%s\'", modname[j]);
2513 loading->action.order[j] = ACTION_NONE;
2514 }
2515 }
2516
2517 free(modname);
2518 }
2519
2520 player_slots_iterate(pslot) {
2521 int plrno = player_slot_index(pslot);
2522 int nunits;
2523 int unro;
2524
2525 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2526 continue;
2527 }
2528
2530 "player%d.nunits", plrno);
2531
2532 for (unro = 0; unro < nunits; unro++) {
2533 int ei;
2534 int i;
2535 enum unit_activity activity;
2536 enum gen_action act;
2537
2539 "player%d.u%d.activity", plrno, unro);
2540
2541 if (ei >= 0 && ei < loading->activities.size) {
2542 activity = unit_activity_by_name(loading->activities.order[ei],
2544 act = activity_default_action(activity);
2545
2546 for (i = 0; i < loading->action.size; i++) {
2547 if (act == loading->action.order[i]) {
2548 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2549 plrno, unro);
2550 break;
2551 }
2552 }
2553 }
2554 }
2556 }
2557}
2558
2559/************************************************************************/
2563#ifdef FREECIV_DEV_SAVE_COMPAT
2564static void compat_load_dev(struct loaddata *loading)
2565{
2566 int game_version;
2567
2568 /* Check status and return if not OK (sg_success FALSE). */
2569 sg_check_ret();
2570
2571 log_verbose("Upgrading data between development revisions");
2572
2573 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2574 "No save version found");
2575
2576#ifdef FREECIV_DEV_SAVE_COMPAT_3_2
2577
2578 if (game_version < 3019100) {
2579 /* Before version number bump to 3.1.91 */
2580 int i;
2581 int count;
2582
2583 /* Older savegames had a bug that got_tech_multi was not saved.
2584 * Insert the entry to such savegames */
2585
2586 /* May be unsaved (e.g. scenario case). */
2587 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2588 for (i = 0; i < count; i++) {
2589 if (secfile_entry_lookup(loading->file,
2590 "research.r%d.got_tech_multi", i) == NULL) {
2591 /* Default to FALSE */
2593 "research.r%d.got_tech_multi", i);
2594 }
2595 }
2596 } /* Version < 3.1.91 */
2597
2598 if (game_version < 3019200) {
2599 /* Before version number bump to 3.1.92, August 2022 */
2600 int set_count;
2601 bool gamestart_valid = FALSE;
2602 bool al_set_already = FALSE;
2603 bool wrap_set_already = FALSE;
2604 const char *level;
2605 bool count_changed = FALSE;
2606 bool topo_defined = FALSE;
2607 char wrap[100];
2608 char wrap_gs[100];
2609
2610 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2611 int i;
2614 "settings.gamestart_valid");
2615
2616 for (i = 0; i < set_count; i++) {
2617 const char *old_name
2618 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2619 const char *name;
2620
2621 if (!old_name) {
2622 continue;
2623 }
2624
2626
2627 if (fc_strcasecmp(old_name, name)) {
2628 /* Setting's name changed */
2629 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2630 }
2631
2632 if (!fc_strcasecmp("compresstype", name)) {
2633 const char *val = secfile_lookup_str(loading->file,
2634 "settings.set%d.value", i);
2635
2636 if (!fc_strcasecmp(val, "BZIP2")) {
2637#ifdef FREECIV_HAVE_LIBZSTD
2638 secfile_replace_str(loading->file, "ZSTD",
2639 "settings.set%d.value", i);
2640#elif FREECIV_HAVE_LIBLZMA
2641 secfile_replace_str(loading->file, "XZ",
2642 "settings.set%d.value", i);
2643#elif FREECIV_HAVE_LIBZ
2644 secfile_replace_str(loading->file, "LIBZ",
2645 "settings.set%d.value", i);
2646#else
2647 secfile_replace_str(loading->file, "PLAIN",
2648 "settings.set%d.value", i);
2649#endif
2650 }
2651
2652 if (gamestart_valid) {
2653 val = secfile_lookup_str(loading->file,
2654 "settings.set%d.gamestart", i);
2655 if (!fc_strcasecmp(val, "BZIP2")) {
2656#ifdef FREECIV_HAVE_LIBZSTD
2657 secfile_replace_str(loading->file, "ZSTD",
2658 "settings.set%d.gamestart", i);
2659#elif FREECIV_HAVE_LIBLZMA
2660 secfile_replace_str(loading->file, "XZ",
2661 "settings.set%d.gamestart", i);
2662#elif FREECIV_HAVE_LIBZ
2663 secfile_replace_str(loading->file, "LIBZ",
2664 "settings.set%d.gamestart", i);
2665#else
2666 secfile_replace_str(loading->file, "PLAIN",
2667 "settings.set%d.gamestart", i);
2668#endif
2669 }
2670 }
2671 } else if (!fc_strcasecmp("ailevel", name)) {
2673 } else if (!fc_strcasecmp("topology", name)) {
2674 struct setting *pset = setting_by_name(name);
2675 struct sf_cb_data info = { pset, TRUE };
2676 int val;
2677
2678 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2680 "settings.set%d.value", i)) {
2681 bool topo_changed = TRUE;
2682
2683 if (val & TF_OLD_WRAPX) {
2684 if (val & TF_OLD_WRAPY) {
2685 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2686 } else {
2687 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2688 }
2689 } else if (val & TF_OLD_WRAPY) {
2690 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2691 } else {
2692 fc_strlcpy(wrap, "", sizeof(wrap));
2694 }
2695
2696 if (topo_changed) {
2697 char buf[100];
2698
2699 if (val & TF_ISO) {
2700 if (val & TF_HEX) {
2701 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2702 } else {
2703 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2704 }
2705 } else if (val & TF_HEX) {
2706 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2707 } else {
2709 }
2710
2711 setting_value_name(pset, FALSE, buf, sizeof(buf));
2713 "settings.set%d.value", i);
2714 }
2715
2716 if (gamestart_valid) {
2717 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2719 "settings.set%d.gamestart", i)) {
2721
2722 if (val & TF_OLD_WRAPX) {
2723 if (val & TF_OLD_WRAPY) {
2724 fc_strlcpy(wrap_gs, "WrapX|WrapY", sizeof(wrap));
2725 } else {
2726 fc_strlcpy(wrap_gs, "WrapX", sizeof(wrap));
2727 }
2728 } else if (val & TF_OLD_WRAPY) {
2729 fc_strlcpy(wrap_gs, "WrapY", sizeof(wrap));
2730 } else {
2731 fc_strlcpy(wrap_gs, "", sizeof(wrap));
2733 }
2734
2735 if (topo_changed) {
2736 char buf[100];
2737
2738 if (val & TF_ISO) {
2739 if (val & TF_HEX) {
2740 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2741 } else {
2742 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2743 }
2744 } else if (val & TF_HEX) {
2745 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2746 } else {
2748 }
2749
2750 setting_value_name(pset, FALSE, buf, sizeof(buf));
2752 "settings.set%d.gamestart", i);
2753 }
2754 }
2755 }
2756
2758 }
2759 } else if (!fc_strcasecmp("wrap", name)) {
2761 }
2762 }
2763 }
2764
2765 if (!al_set_already) {
2766 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2767 if (level == NULL) {
2768 /* Assume that this was a new format savegame after all,
2769 * setting just has not been explicitly saved for containing default value. */
2771 }
2772 }
2773
2774 if (!al_set_already) {
2775 /* Turn old AI level field to a setting. */
2776 enum ai_level lvl;
2777
2778 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2779 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2781 } else {
2783 }
2784
2785 if (!ai_level_is_valid(lvl)) {
2786 log_sg("Invalid AI level \"%s\". "
2787 "Changed to \"%s\".", level,
2790 }
2791
2792 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2793 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2794
2795 if (gamestart_valid) {
2796 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2797 set_count);
2798 }
2799
2800 set_count++;
2802 }
2803
2805 secfile_insert_str(loading->file, "wrap", "settings.set%d.name", set_count);
2806 secfile_insert_str(loading->file, wrap, "settings.set%d.value", set_count);
2807
2808 if (gamestart_valid) {
2809 secfile_insert_str(loading->file, wrap_gs, "settings.set%d.value", set_count);
2810 }
2811
2812 set_count++;
2814 }
2815
2816 if (count_changed) {
2817 secfile_replace_int(loading->file, set_count, "settings.set_count");
2818 }
2819
2820 {
2821 int action_count;
2822
2824 "savefile.action_size");
2825
2826 if (action_count > 0) {
2827 const char **modname;
2828 const char **savemod;
2829 int j;
2830 const char *dur_name = "Disband Unit Recover";
2831
2832 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2833 "savefile.action_vector");
2834
2836
2837 for (j = 0; j < action_count; j++) {
2838 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
2839 savemod[j] = dur_name;
2840 } else {
2841 savemod[j] = modname[j];
2842 }
2843 }
2844
2846 "savefile.action_vector");
2847
2848 free(savemod);
2849 }
2850 }
2851
2852 player_slots_iterate(pslot) {
2853 int plrno = player_slot_index(pslot);
2854 int wonder_city = secfile_lookup_int_default(loading->file, -1,
2855 "player%d.adv.wonder_city",
2856 plrno);
2857 if (wonder_city < 0) {
2858 /* No wonder_city saved with the new name. Check for the old name */
2859 wonder_city = secfile_lookup_int_default(loading->file, -1,
2860 "player%d.wonder_city",
2861 plrno);
2862 if (wonder_city >= 0) {
2863 secfile_replace_int(loading->file, wonder_city,
2864 "player%d.adv.wonder_city", plrno);
2865 }
2866 }
2868 } /* Version < 3.1.92 */
2869
2870 if (game_version < 3019300) {
2871 /* Before version number bump to 3.1.93 */
2872
2873 /* Older savegames unnecessarily saved diplstate type order.
2874 * Silence "unused entry" warnings about those. */
2875 {
2877 "savefile.diplstate_type_size");
2878 int i;
2879
2880 for (i = 0; i < dscount; i++) {
2882 "savefile.diplstate_type_vector,%d", i);
2883 }
2884 }
2885
2886 (void) secfile_entry_lookup(loading->file, "game.hardcoded_counters");
2887
2888 /* Add wl_max_length entries for players */
2889 {
2890 player_slots_iterate(pslot) {
2891 int plrno = player_slot_index(pslot);
2892 int ncities;
2893 int cnro;
2894 int wlist_max_length = 0;
2895
2896 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2897 continue;
2898 }
2899
2901 "player%d.ncities", plrno);
2902
2903 for (cnro = 0; cnro < ncities; cnro++) {
2905 "player%d.c%d.wl_length",
2906 plrno, cnro);
2907
2909 }
2910
2912 "player%d.wl_max_length", plrno);
2914 "player%d.routes_max_length", plrno);
2915
2917 }
2918
2919 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2920 {
2921 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2922
2923 for (int i = 0; i < count; i++) {
2924 bool got_tech = FALSE;
2925 int bulbs = 0;
2926 bool got_tech_multi
2928 "research.r%d.got_tech_multi", i);
2929
2931 "research.r%d.got_tech", i)
2932 && secfile_lookup_int(loading->file, &bulbs,
2933 "research.r%d.bulbs", i)) {
2935 got_tech || got_tech_multi ? bulbs : 0,
2936 "research.r%d.free_bulbs", i);
2937 }
2938 }
2939 }
2940
2941 /* Convert 'alltemperate' and 'singlepole' into 'northlatitude' and
2942 * 'southlatitude' server settings */
2943 {
2944 int i;
2946 "settings.set_count");
2947 int alltemperate_idx = -1, singlepole_idx = -1;
2948
2949 for (i = 0; i < set_count; i++) {
2950 const char *name
2951 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2952
2953 if (!name) {
2954 continue;
2955 }
2956
2957 if (!fc_strcasecmp("northlatitude", name)
2958 || !fc_strcasecmp("southlatitude", name)) {
2959 /* this savegame is recent enough to already have latitude
2960 * settings ~> no change necessary */
2962 break;
2963 }
2964
2965 if (!fc_strcasecmp("alltemperate", name)) {
2967 } else if (!fc_strcasecmp("singlepole", name)) {
2968 singlepole_idx = i;
2969 }
2970 }
2971
2972 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2973 int north_latitude, south_latitude;
2974 int north_idx, south_idx;
2976
2977 if (alltemperate_idx < 0
2979 "settings.set%d.value",
2981 /* infer what would've been the ruleset default */
2983 }
2984
2985 if (singlepole_idx < 0
2987 "settings.set%d.value",
2988 singlepole_idx)) {
2989 /* infer what would've been the ruleset default */
2991 }
2992
2993 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2994 * changes, that'll have to be handled in later migrations anyway */
2995 north_latitude = alltemperate ? 500 : 1000;
2996 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2997
2998 /* Replace alltemperate with northlatitude, and singlepole with
2999 * southlatitude. If only one of the two was given, add the other
3000 * at the end. */
3003
3004 secfile_replace_str(loading->file, "northlatitude",
3005 "settings.set%d.name", north_idx);
3006 secfile_replace_int(loading->file, north_latitude,
3007 "settings.set%d.value", north_idx);
3008
3009 secfile_replace_str(loading->file, "southlatitude",
3010 "settings.set%d.name", south_idx);
3011 secfile_replace_int(loading->file, south_latitude,
3012 "settings.set%d.value", south_idx);
3013
3015 "settings.gamestart_valid")) {
3016 if (alltemperate_idx < 0
3018 "settings.set%d.gamestart",
3020 alltemperate =
3022 }
3023
3024 if (singlepole_idx < 0
3026 "settings.set%d.gamestart",
3027 singlepole_idx)) {
3029 }
3030
3031 north_latitude = alltemperate ? 500 : 1000;
3032 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
3033
3034 secfile_replace_int(loading->file, north_latitude,
3035 "settings.set%d.gamestart", north_idx);
3036 secfile_replace_int(loading->file, south_latitude,
3037 "settings.set%d.gamestart", south_idx);
3038 }
3039
3040 if (alltemperate_idx < 0 || singlepole_idx < 0) {
3041 /* only one was given and replaced ~> we added one new entry */
3042 set_count++;
3044 "settings.set_count");
3045 }
3046 }
3047 }
3048
3049 {
3050 int action_count;
3051
3053 "savefile.action_size");
3054
3055 if (action_count > 0) {
3056 const char **modname;
3057 const char **savemod;
3058 int j;
3059 const char *dur_name = "Transport Deboard";
3060
3061 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3062 "savefile.action_vector");
3063
3065
3066 for (j = 0; j < action_count; j++) {
3067 if (!fc_strcasecmp("Transport Alight", modname[j])) {
3068 savemod[j] = dur_name;
3069 } else {
3070 savemod[j] = modname[j];
3071 }
3072 }
3073
3075 "savefile.action_vector");
3076
3077 free(savemod);
3078 }
3079 }
3080
3081 } /* Version < 3.1.93 */
3082
3083#endif /* FREECIV_DEV_SAVE_COMPAT_3_2 */
3084
3085#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
3086
3087 if (game_version < 3029100) {
3088 /* Before version number bump to 3.2.91, September 2023 */
3089
3090 {
3091 const char *str = secfile_lookup_str_default(loading->file, NULL,
3092 "savefile.orig_version");
3093
3094 if (str == NULL) {
3095 /* Make sure CURRENTLY running version does not
3096 * end as orig_version when we resave. */
3097 secfile_insert_str(loading->file, "old savegame3, or older",
3098 "savefile.orig_version");
3099 }
3100 }
3101
3102 /* Add acquire_t entries for cities */
3103 {
3104 player_slots_iterate(pslot) {
3105 int plrno = player_slot_index(pslot);
3106 int ncities;
3107 int cnro;
3108 bool first_city;
3109
3110 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
3111 continue;
3112 }
3113
3115 "player%d.got_first_city",
3116 plrno);
3117 if (first_city) {
3118 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
3119 int flagcount = 0;
3120 const char **flags_sg;
3121 size_t nval;
3122 int i;
3123
3125
3127 "player%d.flags", plrno);
3128
3129 for (i = 0; i < nval; i++) {
3132
3134 }
3135
3137 "player%d.flags", plrno);
3138
3140 }
3141
3143 "player%d.ncities", plrno);
3144
3145 for (cnro = 0; cnro < ncities; cnro++) {
3146 if (secfile_entry_lookup(loading->file,
3147 "player%d.c%d.acquire_t",
3148 plrno, cnro) == NULL) {
3150 "player%d.c%d.original",
3151 plrno, cnro) != plrno) {
3153 "player%d.c%d.acquire_t",
3154 plrno, cnro);
3155 } else {
3157 "player%d.c%d.acquire_t",
3158 plrno, cnro);
3159 }
3160 }
3161 if (secfile_entry_lookup(loading->file,
3162 "player%d.c%d.wlcb",
3163 plrno, cnro) == NULL) {
3165 "player%d.c%d.wlcb",
3166 plrno, cnro);
3167 }
3168 }
3170 }
3171
3172 /* Add orders_max_length entries for players */
3173 {
3174 player_slots_iterate(pslot) {
3175 int plrno = player_slot_index(pslot);
3176
3177 if (secfile_section_lookup(loading->file, "player%d", plrno) != NULL
3179 "player%d.orders_max_length", plrno)
3180 == NULL) {
3181 size_t nunits;
3182 int unro;
3183 size_t olist_max_length = 0;
3184
3186 "player%d.nunits", plrno);
3187
3188 for (unro = 0; unro < nunits; unro++) {
3189 int ol_length
3191 "player%d.u%d.orders_length",
3192 plrno, unro);
3193
3195 }
3196
3198 "player%d.orders_max_length", plrno);
3199 }
3201 }
3202
3203 {
3204 int action_count;
3205
3207 "savefile.action_size");
3208
3209 if (action_count > 0) {
3210 const char **modname;
3211 const char **savemod;
3212 int j;
3213 const char *clean_name = "Clean";
3214
3215 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3216 "savefile.action_vector");
3217
3219
3220 for (j = 0; j < action_count; j++) {
3221 if (!fc_strcasecmp("Clean Pollution", modname[j])
3222 || !fc_strcasecmp("Clean Fallout", modname[j])) {
3223 savemod[j] = clean_name;
3224 } else {
3225 savemod[j] = modname[j];
3226 }
3227 }
3228
3230 "savefile.action_vector");
3231
3232 free(savemod);
3233 }
3234 }
3235
3236 {
3237 int activities_count;
3238
3240 "savefile.activities_size");
3241
3242 if (activities_count > 0) {
3243 const char **modname;
3244 const char **savemod;
3245 int j;
3246 const char *clean_name = "Clean";
3247
3248 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
3249 "savefile.activities_vector");
3250
3252
3253 for (j = 0; j < activities_count; j++) {
3254 if (!fc_strcasecmp("Pollution", modname[j])
3255 || !fc_strcasecmp("Fallout", modname[j])) {
3256 savemod[j] = clean_name;
3257 } else {
3258 savemod[j] = modname[j];
3259 }
3260 }
3261
3263 "savefile.activities_vector");
3264
3265 free(savemod);
3266 }
3267 }
3268
3269 /* Server setting migration. */
3270 {
3271 int set_count;
3272
3273 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
3274 bool gamestart_valid = FALSE;
3275
3278 "settings.gamestart_valid");
3279
3280 if (!gamestart_valid) {
3281 int i;
3282
3283 /* Older savegames saved gamestart values even when they were not valid.
3284 * Silence warnings caused by them. */
3285 for (i = 0; i < set_count; i++) {
3286 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
3287 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
3288 }
3289 }
3290 }
3291 }
3292
3293 {
3294 int ssa_count;
3295
3297 "savefile.server_side_agent_size");
3298 if (ssa_count > 0) {
3299 const char **modname;
3300 const char **savemod;
3301 int j;
3302 const char *aw_name = "AutoWorker";
3303
3304 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
3305 "savefile.server_side_agent_list");
3306
3307 savemod = fc_calloc(ssa_count, sizeof(*savemod));
3308
3309 for (j = 0; j < ssa_count; j++) {
3310 if (!fc_strcasecmp("Autosettlers", modname[j])) {
3311 savemod[j] = aw_name;
3312 } else {
3313 savemod[j] = modname[j];
3314 }
3315 }
3316
3318 "savefile.server_side_agent_list");
3319
3320 free(savemod);
3321 }
3322 }
3323
3324 } /* Version < 3.2.91 */
3325
3326 if (game_version < 3029200) {
3327 /* Before version number bump to 3.2.92 */
3328
3329 secfile_insert_bool(loading->file, FALSE, "map.altitude");
3330
3331 /* World Peace has never started in the old savegame. */
3332 game.info.turn
3333 = secfile_lookup_int_default(loading->file, 0, "game.turn");
3336 "game.world_peace_start");
3338 "game.world_peace_start");
3339
3340 /* Add actions for unit activities */
3341 loading->activities.size
3343 "savefile.activities_size");
3344 if (loading->activities.size) {
3345 loading->activities.order
3346 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
3347 "savefile.activities_vector");
3348 sg_failure_ret(loading->activities.size != 0,
3349 "Failed to load activity order: %s",
3350 secfile_error());
3351 }
3352
3353 loading->action.size = secfile_lookup_int_default(loading->file, 0,
3354 "savefile.action_size");
3355
3356 sg_failure_ret(loading->action.size > 0,
3357 "Failed to load action order: %s",
3358 secfile_error());
3359
3360 if (loading->action.size) {
3361 const char **modname;
3362 int j;
3363
3364 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3365 "savefile.action_vector");
3366
3367 loading->action.order = fc_calloc(loading->action.size,
3368 sizeof(*loading->action.order));
3369
3370 for (j = 0; j < loading->action.size; j++) {
3372
3373 if (real_action) {
3374 loading->action.order[j] = real_action->id;
3375 } else {
3376 log_sg("Unknown action \'%s\'", modname[j]);
3377 loading->action.order[j] = ACTION_NONE;
3378 }
3379 }
3380
3381 free(modname);
3382 }
3383
3384 player_slots_iterate(pslot) {
3385 int plrno = player_slot_index(pslot);
3386 int nunits;
3387 int unro;
3388
3389 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3390 continue;
3391 }
3392
3394 "player%d.nunits", plrno);
3395
3396 for (unro = 0; unro < nunits; unro++) {
3397 int ei;
3398 int i;
3399 enum unit_activity activity;
3400 enum gen_action act;
3401
3403 "player%d.u%d.activity", plrno, unro);
3404
3405 if (ei >= 0 && ei < loading->activities.size) {
3406 activity = unit_activity_by_name(loading->activities.order[ei],
3408 act = activity_default_action(activity);
3409
3410 for (i = 0; i < loading->action.size; i++) {
3411 if (act == loading->action.order[i]) {
3412 secfile_insert_int(loading->file, i, "player%d.u%d.action",
3413 plrno, unro);
3414 break;
3415 }
3416 }
3417 }
3418 }
3420
3421 } /* Version < 3.2.92 */
3422
3423#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3424}
3425
3426/************************************************************************/
3430static void compat_post_load_dev(struct loaddata *loading)
3431{
3432 int game_version;
3433
3434 /* Check status and return if not OK (sg_success FALSE). */
3435 sg_check_ret();
3436
3437 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
3438 game_version = 2060000;
3439 }
3440
3441#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
3442
3443 if (game_version < 3029100) {
3444 /* Before version number bump to 3.2.91 */
3445
3446 } /* Version < 3.2.91 */
3447
3448#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3449}
3450#endif /* FREECIV_DEV_SAVE_COMPAT */
3451
3452/************************************************************************/
3455enum ai_level ai_level_convert(int old_level)
3456{
3457 switch (old_level) {
3458 case 1:
3459 return AI_LEVEL_AWAY;
3460 case 2:
3461 return AI_LEVEL_NOVICE;
3462 case 3:
3463 return AI_LEVEL_EASY;
3464 case 5:
3465 return AI_LEVEL_NORMAL;
3466 case 7:
3467 return AI_LEVEL_HARD;
3468 case 8:
3469 return AI_LEVEL_CHEATING;
3470 case 10:
3471#ifdef FREECIV_DEBUG
3472 return AI_LEVEL_EXPERIMENTAL;
3473#else /* FREECIV_DEBUG */
3474 return AI_LEVEL_HARD;
3475#endif /* FREECIV_DEBUG */
3476 }
3477
3478 return ai_level_invalid();
3479}
3480
3481/************************************************************************/
3484enum barbarian_type barb_type_convert(int old_type)
3485{
3486 switch (old_type) {
3487 case 0:
3488 return NOT_A_BARBARIAN;
3489 case 1:
3490 return LAND_BARBARIAN;
3491 case 2:
3492 return SEA_BARBARIAN;
3493 }
3494
3495 return barbarian_type_invalid();
3496}
struct action * action_by_rule_name(const char *name)
Definition actions.c:1054
int action_number(const struct action *action)
Definition actions.c:1183
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
#define action_iterate_end
Definition actions.h:209
#define action_get_activity(_pact_)
Definition actions.h:454
#define action_iterate(_act_)
Definition actions.h:205
#define ACTION_NONE
Definition actions.h:55
struct @126::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:264
#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:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define NO_TARGET
Definition fc_types.h:358
#define EC_SPECIAL
Definition fc_types.h:1094
revolen_type
Definition fc_types.h:1263
@ REVOLEN_RANDOM
Definition fc_types.h:1265
@ REVOLEN_RANDQUICK
Definition fc_types.h:1267
@ REVOLEN_FIXED
Definition fc_types.h:1264
@ REVOLEN_QUICKENING
Definition fc_types.h:1266
#define DIR8_ORIGIN
Definition fc_types.h:459
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:735
#define GAME_DEFAULT_SCORETURN
Definition game.h:579
#define GAME_DEFAULT_SAVETURNS
Definition game.h:677
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:563
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:695
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:462
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:375
#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:131
int len
Definition packhand.c:127
int player_slot_count(void)
Definition player.c:418
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
#define ANON_USER_NAME
Definition player.h:48
#define player_slots_iterate(_pslot)
Definition player.h:525
#define players_iterate_alive_end
Definition player.h:549
#define player_slots_iterate_end
Definition player.h:529
#define players_iterate_alive(_pplayer)
Definition player.h:544
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)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
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_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_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
struct extra_type * resource_by_identifier(const char identifier)
Definition savecompat.c:327
int current_compat_ver(void)
Definition savecompat.c:226
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:266
bool sg_success
Definition savecompat.c:34
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:564
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:36
static struct compatibility compat[]
Definition savecompat.c:112
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:345
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:236
static const int compat_num
Definition savecompat.c:137
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:707
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:92
int char2num(char ch)
Definition savecompat.c:272
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:147
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:688
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:248
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:313
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:581
static void compat_load_030200(struct loaddata *loading, enum sgf_version format_class)
enum tile_special_type special_by_rule_name(const char *name)
Definition savecompat.c:287
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:198
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:303
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:138
#define sg_check_ret(...)
Definition savecompat.h:150
#define sg_warn(condition, message,...)
Definition savecompat.h:160
tile_special_type
Definition savecompat.h:29
@ S_LAST
Definition savecompat.h:38
#define hex_chars
Definition savecompat.h:205
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
#define MAX_TRADE_ROUTES_OLD
Definition savecompat.h:222
sgf_version
Definition savecompat.h:27
@ SAVEGAME_2
Definition savecompat.h:27
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:146
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:3302
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4260
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4216
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:4058
#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:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
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
int world_peace_start
Definition game.h:238
struct packet_game_info info
Definition game.h:89
struct civ_game::@31::@35 server
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@42::@44 server
int huts_absolute
Definition map_types.h:96
const load_version_func_t post_load
Definition savecompat.c:97
const load_version_func_t load
Definition savecompat.c:96
struct name_translation name
Definition specialist.h:31
Definition tile.h:50
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int length
Definition unit.h:198
bool has_orders
Definition unit.h:196
struct unit::@80 orders
enum unit_activity activity
Definition unit.h:159
struct extra_type * activity_target
Definition unit.h:167
struct unit_order * list
Definition unit.h:201
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define sz_strlcpy(dest, src)
Definition support.h:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:190
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:154
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define terrain_type_iterate_end
Definition terrain.h:272
void free_unit_orders(struct unit *punit)
Definition unit.c:1807
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:386
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2911
bool unit_has_orders(const struct unit *punit)
Definition unit.c:205
#define unit_tile(_pu)
Definition unit.h:397
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#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, struct extra_type **target)
Definition unittools.c:1083
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1249
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1288