Freeciv-3.4
Loading...
Searching...
No Matches
savecompat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "capability.h"
20#include "log.h"
21
22/* common */
23#include "map.h"
24#include "specialist.h"
25
26/* server */
27#include "aiiface.h"
28#include "plrhand.h"
29#include "setcompat.h"
30#include "settings.h"
31#include "unittools.h"
32
33#include "savecompat.h"
34
36
37static char *special_names[] =
38 {
39 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
40 "Fallout", nullptr
41 };
42
43/*
44 For each savefile format after 2.3.0, compatibility functions are defined
45 which translate secfile structures from previous version to that version;
46 all necessary compat functions are called in order to
47 translate between the file and current version. See sg_load_compat().
48
49 The integer version ID should be increased every time the format is changed.
50 If the change is not backwards compatible, please state the changes in the
51 following list and update the compat functions at the end of this file.
52
53 - what was added / removed
54 - when was it added / removed (date and version)
55 - when can additional capability checks be set to mandatory (version)
56 - which compatibility checks are needed and till when (version)
57
58 freeciv | what | date | id
59 --------+------------------------------------------------+------------+----
60 current | (mapped to current savegame format) | ----/--/-- | 0
61 | first version (svn17538) | 2010/07/05 | -
62 2.3.0 | 2.3.0 release | 2010/11/?? | 3
63 2.4.0 | 2.4.0 release | 201./../.. | 10
64 | * player ai type | |
65 | * delegation | |
66 | * citizens | |
67 | * save player color | |
68 | * "known" info format change | |
69 2.5.0 | 2.5.0 release | 201./../.. | 20
70 2.6.0 | 2.6.0 release | 201./../.. | 30
71 3.0.0 | 3.0.0 release | 201./../.. | 40
72 3.1.0 | 3.1.0 release | 201./../.. | 50
73 3.2.0 | 3.2.0 release | 202./../.. | 60
74 3.3.0 | 3.3.0 release | 202./../.. | 70
75 3.4.0 | 3.4.0 release (development) | 202./../.. | 80
76 | | |
77*/
78
87static void compat_post_load_030100(struct loaddata *loading,
89static void compat_post_load_030300(struct loaddata *loading,
91
92#ifdef FREECIV_DEV_SAVE_COMPAT
93static void compat_load_dev(struct loaddata *loading);
94static void compat_post_load_dev(struct loaddata *loading);
95#endif /* FREECIV_DEV_SAVE_COMPAT */
96
98
104
105/* The struct below contains the information about the savegame versions. It
106 * is identified by the version number (first element), which should be
107 * steadily increasing. It is saved as 'savefile.version'. The support
108 * string (first element of 'name') is not saved in the savegame; it is
109 * saved in settings files (so, once assigned, cannot be changed). The
110 * 'pretty' string (second element of 'name') can be changed if necessary
111 * For changes in the development version, edit the definitions above and
112 * add the needed code to load the old version below. Thus, old
113 * savegames can still be loaded while the main definition
114 * represents the current state of the art. */
115/* While developing freeciv 3.4.0, add the compatibility functions to
116 * - compat_load_030400 to load old savegame. */
117static struct compatibility compat[] = {
118 /* Dummy; equal to the current version (last element) */
119 { 0, nullptr, nullptr },
120 /* Version 1 and 2 are not used */
121 /* Version 3: first savegame2 format, so no compat functions for translation
122 * from previous format */
123 { 3, nullptr, nullptr },
124 /* Version 4 to 9 are reserved for possible changes in 2.3.x */
125 { 10, compat_load_020400, nullptr },
126 /* Version 11 to 19 are reserved for possible changes in 2.4.x */
127 { 20, compat_load_020500, nullptr },
128 /* Version 21 to 29 are reserved for possible changes in 2.5.x */
129 { 30, compat_load_020600, nullptr },
130 /* Version 31 to 39 are reserved for possible changes in 2.6.x */
131 { 40, compat_load_030000, nullptr },
132 /* Version 41 to 49 are reserved for possible changes in 3.0.x */
134 /* Version 51 to 59 are reserved for possible changes in 3.1.x */
135 { 60, compat_load_030200, nullptr },
136 /* Version 61 to 69 are reserved for possible changes in 3.2.x */
138 /* Version 71 to 79 are reserved for possible changes in 3.3.x */
139 { 80, compat_load_030400, nullptr },
140 /* Current savefile version is listed above this line; it corresponds to
141 the definitions in this file. */
142};
143
144static const int compat_num = ARRAY_SIZE(compat);
145#define compat_current (compat_num - 1)
146
147/************************************************************************/
155{
156 int i;
157
158 /* Check status and return if not OK (sg_success FALSE). */
159 sg_check_ret();
160
161 loading->version = secfile_lookup_int_default(loading->file, -1,
162 "savefile.version");
163#ifdef FREECIV_DEBUG
164 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
165 loading->version);
166 if (loading->version > compat[compat_current].version) {
167 /* Debug build can (TRY TO!) load newer versions but ... */
168 log_error("Savegame version newer than this build found (%d > %d). "
169 "Trying to load the game nevertheless ...", loading->version,
171 }
172#else /* FREECIV_DEBUG */
173 sg_failure_ret(0 < loading->version
174 && loading->version <= compat[compat_current].version,
175 "Unknown savefile format version (%d).", loading->version);
176#endif /* FREECIV_DEBUG */
177
178
179 for (i = 0; i < compat_num; i++) {
180 if (loading->version < compat[i].version && compat[i].load != nullptr) {
181 log_normal(_("Run compatibility function for version: <%d "
182 "(save file: %d; server: %d)."), compat[i].version,
185 }
186 }
187
188#ifdef FREECIV_DEV_SAVE_COMPAT
189 if (loading->version == compat[compat_current].version) {
191 }
192#endif /* FREECIV_DEV_SAVE_COMPAT */
193}
194
195/************************************************************************/
207{
208 int i;
209
210 /* Check status and return if not OK (sg_success FALSE). */
211 sg_check_ret();
212
213 for (i = 0; i < compat_num; i++) {
214 if (loading->version < compat[i].version
215 && compat[i].post_load != nullptr) {
216 log_normal(_("Run post load compatibility function for version: <%d "
217 "(save file: %d; server: %d)."), compat[i].version,
220 }
221 }
222
223#ifdef FREECIV_DEV_SAVE_COMPAT
224 if (loading->version == compat[compat_current].version) {
226 }
227#endif /* FREECIV_DEV_SAVE_COMPAT */
228}
229
230/************************************************************************/
234{
236}
237
238/************************************************************************/
243char bin2ascii_hex(int value, int halfbyte_wanted)
244{
245 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
246}
247
248/************************************************************************/
256{
257 const char *pch;
258
259 if (ch == ' ') {
260 /* Sane value. It is unknown if there are savegames out there which
261 * need this fix. Savegame.c doesn't write such savegames
262 * (anymore) since the inclusion into CVS (2000-08-25). */
263 return 0;
264 }
265
267
268 sg_failure_ret_val(pch != nullptr && '\0' != ch, 0,
269 "Unknown hex value: '%c' %d", ch, ch);
270 return (pch - hex_chars) << (halfbyte * 4);
271}
272
273static const char num_chars[] =
274 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
275
276/************************************************************************/
279int char2num(char ch)
280{
281 const char *pch;
282
284
285 sg_failure_ret_val(pch != nullptr, 0,
286 "Unknown ascii value for num: '%c' %d", ch, ch);
287
288 return pch - num_chars;
289}
290
291/************************************************************************/
295{
296 int i;
297
298 for (i = 0; special_names[i] != nullptr; i++) {
299 if (!strcmp(name, special_names[i])) {
300 return i;
301 }
302 }
303
304 return S_LAST;
305}
306
307/************************************************************************/
311{
312 fc_assert(type >= 0 && type < S_LAST);
313
314 return special_names[type];
315}
316
317/************************************************************************/
321{
323
326 }
327
328 return nullptr;
329}
330
331/************************************************************************/
335struct extra_type *resource_by_identifier(const char identifier)
336{
338 if (presource->data.resource->id_old_save == identifier) {
339 return presource;
340 }
342
343 return nullptr;
344}
345
346/* =======================================================================
347 * Compatibility functions for loading a game.
348 * ======================================================================= */
349
350/************************************************************************/
355{
356 /* Check status and return if not OK (sg_success FALSE). */
357 sg_check_ret();
358
359 log_debug("Upgrading data from savegame to version 2.4.0");
360
361 /* Add the default player AI. */
362 player_slots_iterate(pslot) {
363 int ncities, i, plrno = player_slot_index(pslot);
364
365 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
366 continue;
367 }
368
370 "player%d.ai_type", player_slot_index(pslot));
371
372 /* Create dummy citizens information. We do not know if citizens are
373 * activated due to the fact that this information
374 * (game.info.citizen_nationality) is not available, but adding the
375 * information does no harm. */
377 "player%d.ncities", plrno);
378 if (ncities > 0) {
379 for (i = 0; i < ncities; i++) {
381 "player%d.c%d.size", plrno, i);
382 if (size > 0) {
384 "player%d.c%d.citizen%d", plrno, i, plrno);
385 }
386 }
387 }
388
390
391 /* Player colors are assigned at the end of player loading, as this
392 * needs information not available here. */
393
394 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
395 * workaround in later 2.3.x); see gna bug #19029.
396 * (The structure of this code is odd as it avoids relying on knowledge of
397 * xsize/ysize, which haven't been extracted from the savefile yet.) */
398 {
399 if (has_capability("knownv2",
400 secfile_lookup_str(loading->file, "savefile.options"))) {
401 /* This savefile contains known information in a sane format.
402 * Just move any entries to where 2.4.x+ expect to find them. */
403 struct section *map = secfile_section_by_name(loading->file, "map");
404
405 if (map != nullptr) {
407 const char *name = entry_name(pentry);
408
409 if (!fc_strncmp(name, "kvb", 3)) {
410 /* Rename the "kvb..." entry to "k..." */
411 char *name2 = fc_strdup(name), *newname = name2 + 2;
412
413 *newname = 'k';
414 /* Savefile probably contains existing "k" entries, which are bogus
415 * so we trash them. */
416 secfile_entry_delete(loading->file, "map.%s", newname);
418 FC_FREE(name2);
419 }
421 }
422 /* Could remove "knownv2" from savefile.options, but it's doing
423 * no harm there. */
424 } else {
425 /* This savefile only contains known information in the broken
426 * format. Try to recover it to a sane format. */
427 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
428 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
429 const int maxslots = 128, maxmapsize = 512;
430 const int lines = maxslots/32;
431 int xsize = 0, y, l, j, x;
432 unsigned int known_row_old[lines * maxmapsize],
434 /* Process a map row at a time */
435 for (y = 0; y < maxmapsize; y++) {
436 /* Look for broken info to convert */
437 bool found = FALSE;
439 for (l = 0; l < lines; l++) {
440 for (j = 0; j < 8; j++) {
441 const char *s =
442 secfile_lookup_str_default(loading->file, nullptr,
443 "map.k%02d_%04d", l * 8 + j, y);
444 if (s) {
445 found = TRUE;
446 if (xsize == 0) {
447 xsize = strlen(s);
448 }
449 sg_failure_ret(xsize == strlen(s),
450 "Inconsistent xsize in map.k%02d_%04d",
451 l * 8 + j, y);
452 for (x = 0; x < xsize; x++) {
453 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
454 }
455 }
456 }
457 }
458 if (found) {
459 /* At least one entry found for this row. Let's hope they were
460 * all there. */
461 /* Attempt to munge into sane format */
462 int p;
463 memset(known_row, 0, sizeof(known_row));
464 /* Iterate over possible player slots */
465 for (p = 0; p < maxslots; p++) {
466 l = p / 32;
467 for (x = 0; x < xsize; x++) {
468 /* This test causes bit-shifts of >=32 (undefined behavior), but
469 * on common platforms, information happens not to be lost, just
470 * oddly arranged. */
471 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
472 known_row[l * xsize + x] |= (1u << (p - l * 32));
473 }
474 }
475 }
476 /* Save sane format back to memory representation of secfile for
477 * real loading code to pick up */
478 for (l = 0; l < lines; l++) {
479 for (j = 0; j < 8; j++) {
480 /* Save info for all slots (not just used ones). It's only
481 * memory, after all. */
482 char row[xsize+1];
483 for (x = 0; x < xsize; x++) {
484 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
485 }
486 row[xsize] = '\0';
488 "map.k%02d_%04d", l * 8 + j, y);
489 }
490 }
491 }
492 }
493 }
494 }
495
496 /* Server setting migration. */
497 {
498 int set_count;
499
500 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
501 int i, new_opt = set_count;
502 bool gamestart_valid
504 "settings.gamestart_valid");
505
506 for (i = 0; i < set_count; i++) {
507 const char *name
508 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
509
510 if (!name) {
511 continue;
512 }
513
514 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
515 * This is now controlled by the "autosaves" setting. */
516 if (!fc_strcasecmp("saveturns", name)) {
517 /* XXX: Hardcodes details from GAME_AUTOSAVES_DEFAULT
518 * and settings.c:autosaves_name() (but these defaults reflect
519 * 2.3's behavior). */
520 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
521 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
522 int nturns;
523
525 "settings.set%d.value", i)) {
526 if (nturns == 0) {
527 /* Invent a new "autosaves" setting */
529 "settings.set%d.value", new_opt);
530 /* Pick something valid for saveturns */
532 "settings.set%d.value", i);
533 } else {
535 "settings.set%d.value", new_opt);
536 }
537 } else {
538 log_sg("Setting '%s': %s", name, secfile_error());
539 }
540 if (gamestart_valid) {
542 "settings.set%d.gamestart", i)) {
543 if (nturns == 0) {
544 /* Invent a new "autosaves" setting */
546 "settings.set%d.gamestart", new_opt);
547 /* Pick something valid for saveturns */
549 "settings.set%d.gamestart", i);
550 } else {
552 "settings.set%d.gamestart", new_opt);
553 }
554 } else {
555 log_sg("Setting '%s': %s", name, secfile_error());
556 }
557 }
558 } else if (!fc_strcasecmp("autosaves", name)) {
559 /* Sanity check. This won't trigger on an option we've just
560 * invented, as the loop won't include it. */
561 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
562 "savefile. It may have been overridden.");
563 }
564 }
565 }
566 }
567}
568
569/************************************************************************/
572static const char *killcitizen_enum_str(secfile_data_t data, int bit)
573{
574 switch (bit) {
575 case UMT_LAND:
576 return "LAND";
577 case UMT_SEA:
578 return "SEA";
579 case UMT_BOTH:
580 return "BOTH";
581 }
582
583 return nullptr;
584}
585
586/************************************************************************/
591{
592 const char *modname[] = { "Road", "Railroad" };
593 const char *old_activities_names[] = {
594 "Idle",
595 "Pollution",
596 "Unused Road",
597 "Mine",
598 "Irrigate",
599 "Mine",
600 "Irrigate",
601 "Fortified",
602 "Fortress",
603 "Sentry",
604 "Unused Railroad",
605 "Pillage",
606 "Goto",
607 "Explore",
608 "Transform",
609 "Unused",
610 "Unused Airbase",
611 "Fortifying",
612 "Fallout",
613 "Unused Patrol",
614 "Base"
615 };
616
617 /* Check status and return if not OK (sg_success FALSE). */
618 sg_check_ret();
619
620 log_debug("Upgrading data from savegame to version 2.5.0");
621
622 secfile_insert_int(loading->file, 2, "savefile.roads_size");
623 secfile_insert_int(loading->file, 0, "savefile.trait_size");
624
626 "savefile.roads_vector");
627
628 secfile_insert_int(loading->file, 19, "savefile.activities_size");
630 "savefile.activities_vector");
631
632 /* Server setting migration. */
633 {
634 int set_count;
635
636 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
637 int i;
638 bool gamestart_valid
640 "settings.gamestart_valid");
641 for (i = 0; i < set_count; i++) {
642 const char *name
643 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
644 if (!name) {
645 continue;
646 }
647 /* In 2.4.x and prior, "killcitizen" listed move types that
648 * killed citizens after successful attack. Now killcitizen
649 * is just boolean and classes affected are defined in ruleset. */
650 if (!fc_strcasecmp("killcitizen", name)) {
651 int value;
652
653 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
654 killcitizen_enum_str, nullptr,
655 "settings.set%d.value", i)) {
656 /* Lowest bit of old killcitizen value indicates if
657 * land units should kill citizens. We take that as
658 * new boolean killcitizen value. */
659 if (value & 0x1) {
661 "settings.set%d.value", i);
662 } else {
664 "settings.set%d.value", i);
665 }
666 } else {
667 log_sg("Setting '%s': %s", name, secfile_error());
668 }
669 if (gamestart_valid) {
670 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
671 killcitizen_enum_str, nullptr,
672 "settings.set%d.gamestart", i)) {
673 /* Lowest bit of old killcitizen value indicates if
674 * land units should kill citizens. We take that as
675 * new boolean killcitizen value. */
676 if (value & 0x1) {
678 "settings.set%d.gamestart", i);
679 } else {
681 "settings.set%d.gamestart", i);
682 }
683 } else {
684 log_sg("Setting '%s': %s", name, secfile_error());
685 }
686 }
687 }
688 }
689 }
690 }
691}
692
693/************************************************************************/
697{
698 switch (type) {
699 case REVOLEN_FIXED:
700 return "FIXED";
701 case REVOLEN_RANDOM:
702 return "RANDOM";
704 return "QUICKENING";
706 return "RANDQUICK";
707 }
708
709 return "";
710}
711
712/************************************************************************/
717{
718 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
719 int tsize;
720 int ti;
721 int turn;
722
723 /* Check status and return if not OK (sg_success FALSE). */
724 sg_check_ret();
725
726 log_debug("Upgrading data from savegame to version 2.6.0");
727
728 /* Terrain mapping table - use current ruleset as we have no way to know
729 * any other old values. */
730 ti = 0;
732 char buf[2];
733
734 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
736 buf[1] = '\0';
737 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
739
740 /* Server setting migration. */
741 {
742 int set_count;
743
744 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
745 char value_buffer[1024] = "";
746 char gamestart_buffer[1024] = "";
747 int i;
748 int dcost = -1;
749 int dstartcost = -1;
752 bool gamestart_valid
754 "settings.gamestart_valid");
755 int new_set_count;
756
757 for (i = 0; i < set_count; i++) {
758 const char *name
759 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
760 if (!name) {
761 continue;
762 }
763
764 /* In 2.5.x and prior, "spacerace" boolean controlled if
765 * spacerace victory condition was active. */
766 if (!fc_strcasecmp("spacerace", name)) {
767 bool value;
768
769 if (secfile_lookup_bool(loading->file, &value,
770 "settings.set%d.value", i)) {
771 if (value) {
772 if (value_buffer[0] != '\0') {
774 }
775 sz_strlcat(value_buffer, "SPACERACE");
776 }
777 } else {
778 log_sg("Setting '%s': %s", name, secfile_error());
779 }
780 if (secfile_lookup_bool(loading->file, &value,
781 "settings.set%d.gamestart", i)) {
782 if (value) {
783 if (gamestart_buffer[0] != '\0') {
785 }
786 sz_strlcat(gamestart_buffer, "SPACERACE");
787 }
788 } else {
789 log_sg("Setting '%s': %s", name, secfile_error());
790 }
791
792 /* We cannot delete old values from the secfile, or rather cannot
793 * change index of the later settings. Renumbering them is not easy as
794 * we don't know type of each setting we would encounter.
795 * So we keep old setting values and only add new "victories" setting. */
796 } else if (!fc_strcasecmp("alliedvictory", name)) {
797 bool value;
798
799 if (secfile_lookup_bool(loading->file, &value,
800 "settings.set%d.value", i)) {
801 if (value) {
802 if (value_buffer[0] != '\0') {
804 }
805 sz_strlcat(value_buffer, "ALLIED");
806 }
807 } else {
808 log_sg("Setting '%s': %s", name, secfile_error());
809 }
810 if (secfile_lookup_bool(loading->file, &value,
811 "settings.set%d.gamestart", i)) {
812 if (value) {
813 if (gamestart_buffer[0] != '\0') {
815 }
816 sz_strlcat(gamestart_buffer, "ALLIED");
817 }
818 } else {
819 log_sg("Setting '%s': %s", name, secfile_error());
820 }
821 } else if (!fc_strcasecmp("revolen", name)) {
822 int value;
823
824 if (secfile_lookup_int(loading->file, &value,
825 "settings.set%d.value", i)) {
826 /* 0 meant RANDOM 1-5 */
827 if (value == 0) {
830 "settings.set%d.value", i);
831 } else {
833 }
834 } else {
835 log_sg("Setting '%s': %s", name, secfile_error());
836 }
837 if (secfile_lookup_int(loading->file, &value,
838 "settings.set%d.gamestart", i)) {
839 /* 0 meant RANDOM 1-5 */
840 if (value == 0) {
843 "settings.set%d.gamestart", i);
844 } else {
846 }
847 } else {
848 log_sg("Setting '%s': %s", name, secfile_error());
849 }
850 } else if (!fc_strcasecmp("happyborders", name)) {
851 bool value;
852
853 if (secfile_lookup_bool(loading->file, &value,
854 "settings.set%d.value", i)) {
855 secfile_entry_delete(loading->file, "settings.set%d.value", i);
856 if (value) {
857 secfile_insert_str(loading->file, "NATIONAL",
858 "settings.set%d.value", i);
859 } else {
860 secfile_insert_str(loading->file, "DISABLED",
861 "settings.set%d.value", i);
862 }
863 } else {
864 log_sg("Setting '%s': %s", name, secfile_error());
865 }
866 if (secfile_lookup_bool(loading->file, &value,
867 "settings.set%d.gamestart", i)) {
868 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
869 if (value) {
870 secfile_insert_str(loading->file, "NATIONAL",
871 "settings.set%d.gamestart", i);
872 } else {
873 secfile_insert_str(loading->file, "DISABLED",
874 "settings.set%d.gamestart", i);
875 }
876 } else {
877 log_sg("Setting '%s': %s", name, secfile_error());
878 }
879 } else if (!fc_strcasecmp("team_pooled_research", name)) {
881 &team_pooled_research,
882 "settings.set%d.value", i),
883 "%s", secfile_error());
884 } else if (!fc_strcasecmp("diplcost", name)) {
885 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
886 if (secfile_lookup_int(loading->file, &dcost,
887 "settings.set%d.value", i)) {
888 } else {
889 log_sg("Setting '%s': %s", name, secfile_error());
890 }
891
893 "settings.set%d.gamestart", i)) {
894 } else {
895 log_sg("Setting '%s': %s", name, secfile_error());
896 }
897 } else if (!fc_strcasecmp("huts", name)) {
898 /* Scale of 'huts' changed. */
899 int hcount;
900
902 "settings.set%d.value", i)) {
903 } else {
904 log_sg("Setting '%s': %s", name, secfile_error());
905 }
906
907 /* Store old-style absolute value. */
909 }
910 }
911
912 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
913
914 if (dcost >= 0) {
915 new_set_count += 2;
916 }
917
918 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
919
920 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
921 set_count);
922 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
923 set_count);
924 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
925 set_count + 1);
926 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
927 set_count + 1);
928
929 if (dcost >= 0) {
930 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
931 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
932 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
933 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
934 }
935
936 if (gamestart_valid) {
937 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
938 set_count);
939 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
940 set_count + 1);
941
942 if (dcost >= 0) {
943 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
944 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
945 }
946 }
947 }
948 }
949
950 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
951 "Trait size: %s", secfile_error());
952
953 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
954
955 player_slots_iterate(pslot) {
956 int plrno = player_slot_index(pslot);
957 bool got_first_city;
958 int old_barb_type;
959 enum barbarian_type new_barb_type;
960 int i;
961 const char *name;
962 int score;
963 int units_num;
964
965 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
966 continue;
967 }
968
969 /* Renamed 'capital' to 'got_first_city'. */
971 "player%d.capital", plrno)) {
973 "player%d.got_first_city", plrno);
974 }
975
976 /* Add 'anonymous' qualifiers for user names */
977 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
979 "player%d.unassigned_user", plrno);
980
981 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
983 "player%d.unassigned_ranked", plrno);
984
985 /* Convert numeric barbarian type to textual */
987 "player%d.ai.is_barbarian", plrno);
990 "player%d.ai.barb_type", plrno);
991
992 /* Pre-2.6 didn't record when a player was created or died, so we have
993 * to assume they lived from the start of the game until last turn */
994 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
995
996 /* As if there never has been a war. */
997 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
998
999 /* Assume people were playing until current reload */
1000 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
1001
1002 for (i = 0; i < tsize; i++) {
1003 int val;
1004
1005 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
1006 plrno, i);
1007 if (val != -1) {
1008 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
1009 }
1010
1012 "player%d.trait.mod%d", plrno, i),
1013 "Trait mod: %s", secfile_error());
1014 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1015 }
1016
1017 score = secfile_lookup_int_default(loading->file, -1,
1018 "player%d.units_built", plrno);
1019 if (score >= 0) {
1020 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1021 }
1022
1023 score = secfile_lookup_int_default(loading->file, -1,
1024 "player%d.units_killed", plrno);
1025 if (score >= 0) {
1026 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1027 }
1028
1029 score = secfile_lookup_int_default(loading->file, -1,
1030 "player%d.units_lost", plrno);
1031 if (score >= 0) {
1032 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1033 }
1034
1035 /* Units orders. */
1037 "player%d.nunits",
1038 plrno);
1039
1040 for (i = 0; i < units_num; i++) {
1041 int len;
1042
1044 "player%d.u%d.orders_last_move_safe",
1045 plrno, i)) {
1046 continue;
1047 }
1048
1050 "player%d.u%d.orders_length",
1051 plrno, i);
1052 if (len > 0) {
1053 char orders_str[len + 1];
1054 char *p;
1055
1058 "player%d.u%d.orders_list",
1059 plrno, i));
1060 if ((p = strrchr(orders_str, 'm'))
1061 || (p = strrchr(orders_str, 'M'))) {
1062 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1064 "player%d.u%d.orders_list", plrno, i);
1065 }
1066 }
1067 }
1069
1070 /* Add specialist order - loading time order is ok here, as we will use
1071 * that when we in later part of compatibility conversion use the specialist
1072 * values */
1074 "savefile.specialists_size");
1075 {
1076 const char **modname;
1077 int i = 0;
1078
1080
1084
1086 "savefile.specialists_vector");
1087
1088 free(modname);
1089 }
1090
1091 /* Replace all city specialist count fields with correct names */
1092 player_slots_iterate(pslot) {
1093 int plrno = player_slot_index(pslot);
1094 int ncities;
1095 int i;
1096
1097 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1098 continue;
1099 }
1100
1101 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1102
1103 for (i = 0; i < ncities; i++) {
1104 int k = 0;
1105
1107 struct specialist *psp = specialist_by_number(sp);
1108 int count;
1109
1111 "player%d.c%d.n%s",
1113 "specialist error: %s", secfile_error());
1114 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1116 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1117 plrno, i, k++);
1119 }
1121
1122 /* Build [research]. */
1123 {
1124 const struct {
1125 const char *name;
1126 enum entry_type type;
1127 } entries[] = {
1128 { "goal_name", ENTRY_STR },
1129 { "techs", ENTRY_INT },
1130 { "futuretech", ENTRY_INT },
1131 { "bulbs_before", ENTRY_INT },
1132 { "saved_name", ENTRY_STR },
1133 { "bulbs", ENTRY_INT },
1134 { "now_name", ENTRY_STR },
1135 { "got_tech", ENTRY_BOOL },
1136 { "done", ENTRY_STR }
1137 };
1138
1140 int count = 0;
1141 int i;
1142
1143 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1144 researches[i] = -1;
1145 }
1146
1147 player_slots_iterate(pslot) {
1148 int plrno = player_slot_index(pslot);
1149 int ival;
1150 bool bval;
1151 const char *sval;
1152 int j;
1153
1154 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1155 continue;
1156 }
1157
1158 /* Get the research number. */
1159 if (team_pooled_research) {
1161 "player%d.team_no", plrno);
1162 } else {
1163 i = plrno;
1164 }
1165
1167 "Research out of bounds (%d)!", i);
1168
1169 /* Find the index in [research] section. */
1170 if (researches[i] == -1) {
1171 /* This is the first player for this research. */
1172 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1173 researches[i] = count;
1174 count++;
1175 }
1176 i = researches[i];
1177
1178 /* Move entries. */
1179 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1180 switch (entries[j].type) {
1181 case ENTRY_BOOL:
1182 if (secfile_lookup_bool(loading->file, &bval,
1183 "player%d.research.%s",
1184 plrno, entries[j].name)) {
1185 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1186 i, entries[j].name);
1187 }
1188 break;
1189 case ENTRY_INT:
1190 if (secfile_lookup_int(loading->file, &ival,
1191 "player%d.research.%s",
1192 plrno, entries[j].name)) {
1193 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1194 i, entries[j].name);
1195 }
1196 break;
1197 case ENTRY_STR:
1198 if ((sval = secfile_lookup_str(loading->file,
1199 "player%d.research.%s",
1200 plrno, entries[j].name))) {
1201 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1202 i, entries[j].name);
1203 }
1204 break;
1205 case ENTRY_FLOAT:
1207 "Research related entry marked as float.");
1208 break;
1211 break;
1212 case ENTRY_LONG_COMMENT:
1214 break;
1215 case ENTRY_ILLEGAL:
1217 break;
1218 }
1219 }
1221 secfile_insert_int(loading->file, count, "research.count");
1222 }
1223
1224 /* Add diplstate type order. */
1226 "savefile.diplstate_type_size");
1227 if (DS_LAST > 0) {
1228 const char **modname;
1229 int i;
1230 int j;
1231
1232 i = 0;
1233 modname = fc_calloc(DS_LAST, sizeof(*modname));
1234
1235 for (j = 0; j < DS_LAST; j++) {
1237 }
1238
1240 DS_LAST,
1241 "savefile.diplstate_type_vector");
1242 free(modname);
1243 }
1244
1245 /* Fix save games from Freeciv versions with a bug that made it view
1246 * "Never met" as closer than "Peace" or "Alliance". */
1247 player_slots_iterate(pslot) {
1248 int plrno = player_slot_index(pslot);
1249
1250 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1251 continue;
1252 }
1253
1255 int i = player_slot_index(pslot2);
1256 char buf[32];
1257 int current;
1258 int closest;
1259
1260 if (secfile_section_lookup(loading->file, "player%d", i) == nullptr) {
1261 continue;
1262 }
1263
1264 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1265
1266 /* Read the current diplomatic state. */
1268 "%s.type",
1269 buf);
1270
1271 /* Read the closest diplomatic state. */
1273 "%s.max_state",
1274 buf);
1275
1276 if (closest == DS_NO_CONTACT
1277 && (current == DS_PEACE
1278 || current == DS_ALLIANCE)) {
1279 const char *name1 = secfile_lookup_str_default(loading->file, "",
1280 "player%d.name", plrno);
1281 const char *name2 = secfile_lookup_str_default(loading->file, "",
1282 "player%d.name", i);
1283 /* The current relationship is closer than what the save game
1284 * claims is the closes relationship ever. */
1285
1286 log_sg(_("The save game is wrong about what the closest"
1287 " relationship %s (player %d) and %s (player %d) have had is."
1288 " Fixing it..."),
1289 name1, plrno, name2, i);
1290
1291 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1292 }
1295}
1296
1297/************************************************************************/
1300static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1301 int old_def, bool keep_default)
1302{
1303 int value;
1304
1305 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1306
1307 if (value != old_def || !keep_default) {
1308 value++;
1309 secfile_replace_int(loading->file, value, "%s", key);
1310 }
1311
1312 return value;
1313}
1314
1315/************************************************************************/
1323{
1324 bool randsaved;
1325 int num_settings;
1326 bool started;
1327 int old_turn;
1328 int event_count;
1329 int i;
1330
1331 /* Check status and return if not OK (sg_success FALSE). */
1332 sg_check_ret();
1333
1334 log_debug("Upgrading data from savegame to version 3.0.0");
1335
1336 /* Rename "random.save" as "random.saved"
1337 * Note that it's not an error if a scenario does not have [random] at all. */
1338 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1339 secfile_insert_bool(loading->file, randsaved, "random.saved");
1340 }
1341
1342 /* Already started games should have their turn counts increased by 1 */
1343 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1344 started = TRUE;
1345
1346 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1348 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1349 } else {
1350 started = FALSE;
1351 }
1352
1353 player_slots_iterate(pslot) {
1354 int plrno = player_slot_index(pslot);
1355 const char *flag_names[1];
1356
1357 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
1358 continue;
1359 }
1360
1361 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1362 plrno)) {
1364
1366 "player%d.flags", plrno);
1367 }
1368
1369 if (started) {
1370 int num = secfile_lookup_int_default(loading->file, 0,
1371 "player%d.nunits",
1372 plrno);
1373
1374 for (i = 0; i < num; i++) {
1375 char buf[64];
1376
1377 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1378
1380 }
1381
1382 num = secfile_lookup_int_default(loading->file, 0,
1383 "player%d.ncities", plrno);
1384
1385 for (i = 0; i < num; i++) {
1386 char buf[64];
1387
1388 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1389
1391 }
1392 }
1394
1395 /* Settings */
1397 "settings.set_count");
1398
1399 /* User meta server message is now a setting. */
1401 "game.meta_usermessage")) {
1402 const char *metamessage;
1403
1405 "game.meta_message");
1406
1407 /* Insert the meta message as a setting */
1408 secfile_insert_str(loading->file, "metamessage",
1409 "settings.set%d.name", num_settings);
1411 "settings.set%d.value", num_settings);
1412 secfile_insert_str(loading->file, "",
1413 "settings.set%d.gamestart", num_settings);
1414 num_settings++;
1415 }
1416
1417 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1418
1419 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1420
1421 for (i = 0; i < event_count; i++) {
1422 const char *etype;
1423
1424 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1425
1426 if (etype != nullptr && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1427 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1428 "event_cache.events%d.event", i);
1429 }
1430 }
1431}
1432
1433/************************************************************************/
1438{
1439 int ssa_size;
1440
1441 if (format_class == SAVEGAME_2) {
1442 /* Handled in savegame2 */
1443 return;
1444 }
1445
1447 "savefile.server_side_agent_size");
1448
1449 if (ssa_size != 0) {
1450 /* Already inserted. */
1451 return;
1452 }
1453
1454 /* Add server side agent order. */
1456 "savefile.server_side_agent_size");
1457 if (SSA_COUNT > 0) {
1458 const char **modname;
1459 int i;
1460 int j;
1461
1462 i = 0;
1463 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1464
1465 for (j = 0; j < SSA_COUNT; j++) {
1467 }
1468
1470 SSA_COUNT,
1471 "savefile.server_side_agent_list");
1472 free(modname);
1473 }
1474
1475 /* Insert server_side_agent unit field. */
1476 player_slots_iterate(pslot) {
1477 int unit;
1478 int units_num;
1479 int plrno = player_slot_index(pslot);
1480
1481 if (secfile_section_lookup(loading->file, "player%d", plrno)
1482 == nullptr) {
1483 continue;
1484 }
1485
1486 /* Number of units the player has. */
1488 "player%d.nunits",
1489 plrno);
1490
1491 for (unit = 0; unit < units_num; unit++) {
1492 bool ai;
1493
1495 "player%d.u%d.server_side_agent",
1496 plrno, unit)
1497 != nullptr) {
1498 /* Already updated? */
1499 continue;
1500 }
1501
1503 "player%d.u%d.ai",
1504 plrno, unit);
1505
1506 if (ai) {
1507 /* Autoworker and Autoexplore are separated by
1508 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1510 "player%d.u%d.server_side_agent",
1511 plrno, unit);
1512 } else {
1514 "player%d.u%d.server_side_agent",
1515 plrno, unit);
1516 }
1517 }
1519}
1520
1521/************************************************************************/
1529{
1530 /* Check status and return if not OK (sg_success FALSE). */
1531 sg_check_ret();
1532
1533 log_debug("Upgrading data from savegame to version 3.1.0");
1534
1535 /* Actions are now stored by number. */
1536 player_slots_iterate(pslot) {
1537 int unit;
1538 int units_num;
1539 int plrno = player_slot_index(pslot);
1540
1541 if (secfile_section_lookup(loading->file, "player%d", plrno)
1542 == nullptr) {
1543 continue;
1544 }
1545
1546 /* Number of units the player has. */
1548 "player%d.nunits",
1549 plrno);
1550
1551 for (unit = 0; unit < units_num; unit++) {
1552 const char *action_unitstr;
1553 int order_len;
1554
1556 "player%d.u%d.orders_length",
1557 plrno, unit);
1558
1560 "player%d.u%d.action_list",
1561 plrno, unit))) {
1562 int order_num;
1563
1566 }
1567
1568 for (order_num = 0; order_num < order_len; order_num++) {
1570
1571 if (action_unitstr[order_num] == '?') {
1573 } else {
1575 }
1576
1577 if (order_num == 0) {
1578 /* The start of a vector has no number. */
1580 "player%d.u%d.action_vec",
1581 plrno, unit);
1582 } else {
1584 "player%d.u%d.action_vec,%d",
1585 plrno, unit, order_num);
1586 }
1587 }
1588 }
1589 }
1591
1592 {
1593 int action_count;
1594
1596 "savefile.action_size");
1597
1598 if (action_count > 0) {
1599 const char **modname;
1600 const char **savemod;
1601 int j;
1602 const char *dur_name = "Disband Unit Recover";
1603
1604 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1605 "savefile.action_vector");
1606
1608
1609 for (j = 0; j < action_count; j++) {
1610 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1611 savemod[j] = dur_name;
1612 } else {
1613 savemod[j] = modname[j];
1614 }
1615 }
1616
1618 "savefile.action_vector");
1619
1620 free(savemod);
1621 }
1622 }
1623
1624 /* Server setting migration. */
1625 {
1626 int set_count;
1627
1628 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1629 int i;
1630 bool gamestart_valid
1632 "settings.gamestart_valid");
1633
1634 /* Only add gamesetdef if gamestart is valid at all */
1635 if (gamestart_valid) {
1636 for (i = 0; i < set_count; i++) {
1637 const char *name
1638 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1639
1640 if (!name) {
1641 continue;
1642 }
1643
1645 "settings.set%d.gamesetdef", i);
1646 }
1647 }
1648 }
1649 }
1650
1651 /* Explicit server side agent was new in 3.1 */
1653}
1654
1655/************************************************************************/
1659{
1660 int i;
1661
1662 for (i = 0; i < act_unit->orders.length; i++) {
1663 struct unit_order *order = &act_unit->orders.list[i];
1664
1665 if (order->order != ORDER_ACTIVITY) {
1666 continue;
1667 }
1668
1669 switch (order->activity) {
1670 case ACTIVITY_CLEAN:
1671 case ACTIVITY_MINE:
1672 case ACTIVITY_IRRIGATE:
1673 case ACTIVITY_PLANT:
1674 case ACTIVITY_CULTIVATE:
1675 case ACTIVITY_TRANSFORM:
1676 case ACTIVITY_CONVERT:
1678 case ACTIVITY_BASE:
1679 case ACTIVITY_GEN_ROAD:
1680 case ACTIVITY_PILLAGE:
1681 action_iterate(act_id) {
1682 struct action *paction = action_by_number(act_id);
1683
1684 if (action_get_activity(paction) == order->activity) {
1685 order->order = ORDER_PERFORM_ACTION;
1686 order->action = action_number(paction);
1687 order->activity = ACTIVITY_LAST;
1688 break;
1689 }
1691 break;
1692 case ACTIVITY_SENTRY:
1693 /* Not an action */
1694 break;
1695 case ACTIVITY_EXPLORE:
1696 case ACTIVITY_IDLE:
1697 case ACTIVITY_GOTO:
1698 case ACTIVITY_FORTIFIED:
1699 case ACTIVITY_LAST:
1700 log_error("Activity %d is not supposed to appear in unit orders",
1701 order->activity);
1702 break;
1703 }
1704 }
1705}
1706
1707/************************************************************************/
1711{
1712 switch (dir) {
1713 case DIR8_NORTH:
1714 return DIR8_SOUTH;
1715 case DIR8_NORTHEAST:
1716 return DIR8_SOUTHWEST;
1717 case DIR8_EAST:
1718 return DIR8_WEST;
1719 case DIR8_SOUTHEAST:
1720 return DIR8_NORTHWEST;
1721 case DIR8_SOUTH:
1722 return DIR8_NORTH;
1723 case DIR8_SOUTHWEST:
1724 return DIR8_NORTHEAST;
1725 case DIR8_WEST:
1726 return DIR8_EAST;
1727 case DIR8_NORTHWEST:
1728 return DIR8_SOUTHEAST;
1729 }
1730
1731 return DIR8_ORIGIN;
1732}
1733
1734/************************************************************************/
1738{
1739 int i;
1740 struct tile *current_tile;
1741 struct tile *tgt_tile;
1742
1743 if (!unit_has_orders(act_unit)) {
1744 return;
1745 }
1746
1747 /* The order index is for the unit at its current tile. */
1748 current_tile = unit_tile(act_unit);
1749
1750 /* Rewind to the beginning of the orders */
1751 for (i = act_unit->orders.index; i > 0 && current_tile != nullptr; i--) {
1752 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1753
1754 if (!(prev_order->order == ORDER_PERFORM_ACTION
1758 current_tile = mapstep(&(wld.map), current_tile,
1759 dir_opposite(prev_order->dir));
1760 }
1761 }
1762
1763 /* Upgrade to explicit target tile */
1764 for (i = 0; i < act_unit->orders.length && current_tile != nullptr; i++) {
1765 struct unit_order *order = &act_unit->orders.list[i];
1766
1767 if (order->order == ORDER_PERFORM_ACTION
1768 && order->target != NO_TARGET) {
1769 /* The target is already specified in the new format. */
1770
1771 /* The index_to_tile() call has no side-effects that we
1772 * would want also in NDEBUG builds. */
1773 fc_assert(index_to_tile(&(wld.map), order->target) != nullptr);
1774 return;
1775 }
1776
1777 if (!direction8_is_valid(order->dir)) {
1778 /* The target of the action is on the actor's tile. */
1779 tgt_tile = current_tile;
1780 } else {
1781 /* The target of the action is on a tile next to the actor. */
1782 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1783 }
1784
1785 if (order->order == ORDER_PERFORM_ACTION) {
1786 if (tgt_tile != nullptr) {
1787 struct action *paction = action_by_number(order->action);
1788
1789 order->target = tgt_tile->index;
1790 /* Leave no traces. */
1791 order->dir = DIR8_ORIGIN;
1792
1794 /* The action moves the unit to the target tile (unless this is the
1795 * final order) */
1798 || i == act_unit->orders.length - 1);
1799 current_tile = tgt_tile;
1800 }
1801 } else {
1802 current_tile = nullptr;
1803 }
1804 } else {
1805 current_tile = tgt_tile;
1806 }
1807 }
1808
1809 if (current_tile == nullptr) {
1810 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1812 }
1813}
1814
1815/************************************************************************/
1819{
1820 players_iterate_alive(pplayer) {
1821 unit_list_iterate(pplayer->units, punit) {
1824 }
1827}
1828
1829/************************************************************************/
1834{
1835 /* Check status and return if not OK (sg_success FALSE). */
1836 sg_check_ret();
1837
1838 /* Action orders were new in 3.0 */
1839 if (format_class == SAVEGAME_3) {
1840 /* Only 3.0 savegames may have "Attack" action orders. */
1841 players_iterate_alive(pplayer) {
1842 unit_list_iterate(pplayer->units, punit) {
1843 int i;
1844
1845 if (!punit->has_orders) {
1846 continue;
1847 }
1848
1850 || punit->orders.list != nullptr, continue);
1851
1852 for (i = 0; i < punit->orders.length; i++) {
1853 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1859 }
1860
1861 /* Production targeted actions were split from building targeted
1862 * actions in 3.1. The building sub target encoding changed. */
1864 && ((punit->orders.list[i].action
1866 || (punit->orders.list[i].action
1868 punit->orders.list[i].sub_target -= 1;
1869 }
1871 && (punit->orders.list[i].action
1873 && punit->orders.list[i].sub_target == -1) {
1876 }
1878 && (punit->orders.list[i].action
1880 && punit->orders.list[i].sub_target == -1) {
1883 }
1884 }
1887 }
1888
1889 /* Explicit server side agent was new in 3.1 */
1891
1892 /* Some activities should only be ordered in action orders. */
1893 players_iterate_alive(pplayer) {
1894 unit_list_iterate(pplayer->units, punit) {
1898
1899 /* Unit order action target isn't dir anymore */
1900 players_iterate_alive(pplayer) {
1901 unit_list_iterate(pplayer->units, punit) {
1905
1906 /* Backward compatibility: if we had any open-ended orders (pillage)
1907 * in the savegame, assign specific targets now */
1908 players_iterate_alive(pplayer) {
1909 unit_list_iterate(pplayer->units, punit) {
1911 &punit->activity,
1912 punit->action,
1916}
1917
1918/************************************************************************/
1926{
1927 int i;
1928 int count;
1929 int set_count;
1930 bool gamestart_valid = FALSE;
1931
1932 /* Check status and return if not OK (sg_success FALSE). */
1933 sg_check_ret();
1934
1935 log_debug("Upgrading data from savegame to version 3.2.0");
1936
1937 {
1938 const char *str = secfile_lookup_str_default(loading->file, nullptr,
1939 "savefile.orig_version");
1940
1941 if (str == nullptr) {
1942 /* Make sure CURRENTLY running version does not
1943 * end as orig_version when we resave. */
1944 if (format_class == SAVEGAME_3) {
1945 secfile_insert_str(loading->file, "old savegame3, or older",
1946 "savefile.orig_version");
1947 } else {
1949
1950 secfile_insert_str(loading->file, "savegame2, or older",
1951 "savefile.orig_version");
1952 }
1953 }
1954 }
1955
1956 {
1957 int action_count;
1958
1960 "savefile.action_size");
1961
1962 if (action_count > 0) {
1963 const char **modname;
1964 const char **savemod;
1965 int j;
1966 const char *dur_name = "Transport Deboard";
1967 const char *clean_name = "Clean";
1968
1969 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1970 "savefile.action_vector");
1971
1973
1974 for (j = 0; j < action_count; j++) {
1975 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1976 savemod[j] = dur_name;
1977 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1978 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1979 savemod[j] = clean_name;
1980 } else {
1981 savemod[j] = modname[j];
1982 }
1983 }
1984
1986 "savefile.action_vector");
1987
1988 free(savemod);
1989 }
1990 }
1991
1992 {
1993 int activities_count;
1994
1996 "savefile.activities_size");
1997
1998 if (activities_count > 0) {
1999 const char **modname;
2000 const char **savemod;
2001 int j;
2002 const char *clean_name = "Clean";
2003
2004 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2005 "savefile.activities_vector");
2006
2008
2009 for (j = 0; j < activities_count; j++) {
2010 if (!fc_strcasecmp("Pollution", modname[j])
2011 || !fc_strcasecmp("Fallout", modname[j])) {
2012 savemod[j] = clean_name;
2013 } else {
2014 savemod[j] = modname[j];
2015 }
2016 }
2017
2019 "savefile.activities_vector");
2020
2021 free(savemod);
2022 }
2023 }
2024
2025 /* Server setting migration. */
2026 {
2027 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2028 int alltemperate_idx = -1, singlepole_idx = -1;
2029 bool count_changed = FALSE;
2030
2033 "settings.gamestart_valid");
2034
2035 for (i = 0; i < set_count; i++) {
2036 const char *old_name
2037 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2038 const char *name;
2039
2040 if (!old_name) {
2041 continue;
2042 }
2043
2045
2046 if (fc_strcasecmp(old_name, name)) {
2047 /* Setting's name changed */
2048 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2049 }
2050
2051 if (!gamestart_valid) {
2052 /* Older savegames saved these values even when they were not valid.
2053 * Silence warnings caused by them. */
2054 secfile_entry_ignore(loading->file, "settings.set%d.gamestart", i);
2055 secfile_entry_ignore(loading->file, "settings.set%d.gamesetdef", i);
2056 }
2057
2058 if (!fc_strcasecmp("compresstype", name)) {
2059 const char *val = secfile_lookup_str(loading->file,
2060 "settings.set%d.value", i);
2061 if (!fc_strcasecmp(val, "BZIP2")) {
2062#ifdef FREECIV_HAVE_LIBZSTD
2063 secfile_replace_str(loading->file, "ZSTD",
2064 "settings.set%d.value", i);
2065#elif FREECIV_HAVE_LIBLZMA
2066 secfile_replace_str(loading->file, "XZ",
2067 "settings.set%d.value", i);
2068#elif FREECIV_HAVE_LIBZ
2069 secfile_replace_str(loading->file, "LIBZ",
2070 "settings.set%d.value", i);
2071#else
2072 secfile_replace_str(loading->file, "PLAIN",
2073 "settings.set%d.value", i);
2074#endif
2075 }
2076
2077 if (gamestart_valid) {
2078 val = secfile_lookup_str(loading->file,
2079 "settings.set%d.gamestart", i);
2080 if (!fc_strcasecmp(val, "BZIP2")) {
2081#ifdef FREECIV_HAVE_LIBZSTD
2082 secfile_replace_str(loading->file, "ZSTD",
2083 "settings.set%d.gamestart", i);
2084#elif FREECIV_HAVE_LIBLZMA
2085 secfile_replace_str(loading->file, "XZ",
2086 "settings.set%d.gamestart", i);
2087#elif FREECIV_HAVE_LIBZ
2088 secfile_replace_str(loading->file, "LIBZ",
2089 "settings.set%d.gamestart", i);
2090#else
2091 secfile_replace_str(loading->file, "PLAIN",
2092 "settings.set%d.gamestart", i);
2093#endif
2094 }
2095 }
2096 } else if (!fc_strcasecmp("topology", name)) {
2097 struct setting *pset = setting_by_name(name);
2098 struct sf_cb_data info = { pset, TRUE };
2099 int val;
2100
2101 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2103 "settings.set%d.value", i)) {
2104 char wrap[100];
2105 char buf[100];
2106
2107 if (val & TF_OLD_WRAPX) {
2108 if (val & TF_OLD_WRAPY) {
2109 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2110 } else {
2111 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2112 }
2113 } else if (val & TF_OLD_WRAPY) {
2114 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2115 } else {
2116 fc_strlcpy(wrap, "", sizeof(wrap));
2117 }
2118
2119 if (val & TF_ISO) {
2120 if (val & TF_HEX) {
2121 setting_bitwise_set(pset, "ISO|HEX", nullptr, nullptr, 0);
2122 } else {
2123 setting_bitwise_set(pset, "ISO", nullptr, nullptr, 0);
2124 }
2125 } else if (val & TF_HEX) {
2126 setting_bitwise_set(pset, "HEX", nullptr, nullptr, 0);
2127 } else {
2128 setting_bitwise_set(pset, "", nullptr, nullptr, 0);
2129 }
2130
2131 setting_value_name(pset, FALSE, buf, sizeof(buf));
2133 "settings.set%d.value", i);
2134
2136 "wrap", "settings.set%d.name", set_count);
2138 wrap, "settings.set%d.value", set_count);
2139
2140 if (gamestart_valid) {
2141 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2143 "settings.set%d.gamestart", i)) {
2144 if (val & TF_OLD_WRAPX) {
2145 if (val & TF_OLD_WRAPY) {
2146 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2147 } else {
2148 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2149 }
2150 } else if (val & TF_OLD_WRAPY) {
2151 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2152 } else {
2153 fc_strlcpy(wrap, "", sizeof(wrap));
2154 }
2155
2156 if (val & TF_ISO) {
2157 if (val & TF_HEX) {
2158 setting_bitwise_set(pset, "ISO|HEX", nullptr, nullptr, 0);
2159 } else {
2160 setting_bitwise_set(pset, "ISO", nullptr, nullptr, 0);
2161 }
2162 } else if (val & TF_HEX) {
2163 setting_bitwise_set(pset, "HEX", nullptr, nullptr, 0);
2164 } else {
2165 setting_bitwise_set(pset, "", nullptr, nullptr, 0);
2166 }
2167
2168 setting_value_name(pset, FALSE, buf, sizeof(buf));
2170 "settings.set%d.gamestart", i);
2171
2173 wrap, "settings.set%d.gamestart", set_count);
2174 }
2175 }
2176
2177 set_count++;
2179 }
2180 } else if (!fc_strcasecmp("alltemperate", name)) {
2182 } else if (!fc_strcasecmp("singlepole", name)) {
2183 singlepole_idx = i;
2184 }
2185 }
2186
2187 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2188 int north_latitude, south_latitude;
2189 int north_idx, south_idx;
2191
2192 if (alltemperate_idx < 0
2194 "settings.set%d.value",
2196 /* Infer what would've been the ruleset default */
2198 }
2199
2200 if (singlepole_idx < 0
2202 "settings.set%d.value",
2203 singlepole_idx)) {
2204 /* Infer what would've been the ruleset default */
2206 }
2207
2208 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2209 * changes, that'll have to be handled in later migrations anyway */
2210 north_latitude = alltemperate ? 500 : 1000;
2211 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2212
2213 /* Replace alltemperate with northlatitude, and singlepole with
2214 * southlatitude. If only one of the two was given, add the other
2215 * at the end. */
2218
2219 secfile_replace_str(loading->file, "northlatitude",
2220 "settings.set%d.name", north_idx);
2221 secfile_replace_int(loading->file, north_latitude,
2222 "settings.set%d.value", north_idx);
2223
2224 secfile_replace_str(loading->file, "southlatitude",
2225 "settings.set%d.name", south_idx);
2226 secfile_replace_int(loading->file, south_latitude,
2227 "settings.set%d.value", south_idx);
2228
2229 if (gamestart_valid) {
2230 if (alltemperate_idx < 0
2232 "settings.set%d.gamestart",
2234 alltemperate =
2236 }
2237
2238 if (singlepole_idx < 0
2240 "settings.set%d.gamestart",
2241 singlepole_idx)) {
2243 }
2244
2245 north_latitude = alltemperate ? 500 : 1000;
2246 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2247
2248 secfile_replace_int(loading->file, north_latitude,
2249 "settings.set%d.gamestart", north_idx);
2250 secfile_replace_int(loading->file, south_latitude,
2251 "settings.set%d.gamestart", south_idx);
2252 }
2253
2254 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2255 /* only one was given and replaced ~> we added one new entry */
2256 set_count++;
2258 }
2259 }
2260
2261 if (count_changed) {
2263 "settings.set_count");
2264 }
2265 }
2266 }
2267
2268 {
2269 /* Turn old AI level field to a setting. */
2270 const char *level;
2271 enum ai_level lvl;
2272
2273 level = secfile_lookup_str_default(loading->file, nullptr, "game.level");
2274 if (level != nullptr && !fc_strcasecmp("Handicapped", level)) {
2275 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2277 } else {
2279 }
2280
2281 if (!ai_level_is_valid(lvl)) {
2282 log_sg("Invalid AI level \"%s\". "
2283 "Changed to \"%s\".", level,
2286 }
2287
2288 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2289 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2290
2291 if (gamestart_valid) {
2292 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2293 set_count);
2294 }
2295
2296 set_count++;
2297 secfile_replace_int(loading->file, set_count, "settings.set_count");
2298 }
2299
2300 if (format_class != SAVEGAME_2) {
2301 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2302 /* Older savegames had a bug that got_tech_multi was not saved. */
2303 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2304 for (i = 0; i < count; i++) {
2305 bool got_tech = FALSE;
2306 int bulbs = 0;
2307 bool got_tech_multi
2309 "research.r%d.got_tech_multi", i);
2310
2312 "research.r%d.got_tech", i)
2313 && secfile_lookup_int(loading->file, &bulbs,
2314 "research.r%d.bulbs", i)) {
2316 got_tech || got_tech_multi ? bulbs : 0,
2317 "research.r%d.free_bulbs", i);
2318 }
2319 }
2320 }
2321
2322 /* Older savegames unnecessarily saved diplstate type order.
2323 * Silence "unused entry" warnings about those. */
2324 {
2326 "savefile.diplstate_type_size");
2327
2328 for (i = 0; i < dscount; i++) {
2330 "savefile.diplstate_type_vector,%d", i);
2331 }
2332 }
2333
2334 /* Add wl_max_length entries for players */
2335 {
2336 player_slots_iterate(pslot) {
2337 int plrno = player_slot_index(pslot);
2338 int ncities;
2339 int cnro;
2340 size_t wlist_max_length = 0;
2341 bool first_city;
2342
2343 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2344 continue;
2345 }
2346
2348 "player%d.got_first_city",
2349 plrno);
2350 if (first_city) {
2351 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2352 int flagcount = 0;
2353 const char **flags_sg;
2354 size_t nval;
2355
2357
2359 "player%d.flags", plrno);
2360
2361 for (i = 0; i < nval; i++) {
2364
2366 }
2367
2369 "player%d.flags", plrno);
2370
2372 }
2373
2375 "player%d.ncities", plrno);
2376
2377 for (cnro = 0; cnro < ncities; cnro++) {
2379 "player%d.c%d.wl_length",
2380 plrno, cnro);
2381
2383
2384 if (format_class == SAVEGAME_3) {
2386 "player%d.c%d.original",
2387 plrno, cnro) != plrno) {
2389 "player%d.c%d.acquire_t",
2390 plrno, cnro);
2391 } else {
2393 "player%d.c%d.acquire_t",
2394 plrno, cnro);
2395 }
2396
2398 "player%d.c%d.wlcb",
2399 plrno, cnro);
2400 }
2401 }
2402
2404 "player%d.wl_max_length", plrno);
2405
2406 if (format_class == SAVEGAME_3) {
2407 int nunits;
2408 int unro;
2409 size_t olist_max_length = 0;
2410
2412 "player%d.nunits", plrno);
2413
2414 for (unro = 0; unro < nunits; unro++) {
2416 "player%d.u%d.orders_length",
2417 plrno, unro);
2418
2420 }
2421
2423 "player%d.orders_max_length", plrno);
2424
2426 "player%d.routes_max_length", plrno);
2427 }
2428
2430 }
2431}
2432
2433/************************************************************************/
2441{
2442 /* Check status and return if not OK (sg_success != TRUE). */
2443 sg_check_ret();
2444
2445 log_debug("Upgrading data from savegame to version 3.3.0");
2446
2447 /* World Peace has never started in the old savegame. */
2448 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2449
2450 if (format_class != SAVEGAME_2) {
2451 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2452
2453 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2454 }
2455
2456 /* Last turn change time as a float, not integer multiplied by 100 */
2457 {
2458 float tct = secfile_lookup_int_default(loading->file, 0,
2459 "game.last_turn_change_time") / 100.0;
2460
2461 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2462 }
2463
2464 {
2465 int ssa_count;
2466
2468 "savefile.server_side_agent_size");
2469 if (ssa_count > 0) {
2470 const char **modname;
2471 const char **savemod;
2472 int j;
2473 const char *aw_name = "AutoWorker";
2474
2475 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2476 "savefile.server_side_agent_list");
2477
2478 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2479
2480 for (j = 0; j < ssa_count; j++) {
2481 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2482 savemod[j] = aw_name;
2483 } else {
2484 savemod[j] = modname[j];
2485 }
2486 }
2487
2489 "savefile.server_side_agent_list");
2490
2491 free(savemod);
2492 }
2493 }
2494
2495 {
2496 int action_count;
2497
2499 "savefile.action_size");
2500
2501 if (action_count > 0) {
2502 const char **modname;
2503 const char **savemod;
2504 int j;
2505 const char *cc1_name = "Conquer City Shrink";
2506 const char *cc2_name = "Conquer City Shrink 2";
2507 const char *cc3_name = "Conquer City Shrink 3";
2508 const char *cc4_name = "Conquer City Shrink 4";
2509
2510 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2511 "savefile.action_vector");
2512
2514
2515 for (j = 0; j < action_count; j++) {
2516 if (!fc_strcasecmp("Conquer City", modname[j])) {
2517 savemod[j] = cc1_name;
2518 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
2519 savemod[j] = cc2_name;
2520 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
2521 savemod[j] = cc3_name;
2522 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
2523 savemod[j] = cc4_name;
2524 } else {
2525 savemod[j] = modname[j];
2526 }
2527 }
2528
2530 "savefile.action_vector");
2531
2532 free(savemod);
2533 }
2534 }
2535
2536 /* Add actions for unit activities */
2537 if (format_class == SAVEGAME_3) {
2538 loading->activities.size
2540 "savefile.activities_size");
2541 if (loading->activities.size) {
2542 loading->activities.order
2543 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2544 "savefile.activities_vector");
2545 sg_failure_ret(loading->activities.size != 0,
2546 "Failed to load activity order: %s",
2547 secfile_error());
2548 }
2549
2550 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2551 "savefile.action_size");
2552
2553 sg_failure_ret(loading->action.size > 0,
2554 "Failed to load action order: %s",
2555 secfile_error());
2556
2557 if (loading->action.size) {
2558 const char **modname;
2559 int j;
2560
2561 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2562 "savefile.action_vector");
2563
2564 loading->action.order = fc_calloc(loading->action.size,
2565 sizeof(*loading->action.order));
2566
2567 for (j = 0; j < loading->action.size; j++) {
2569
2570 if (real_action != nullptr) {
2571 loading->action.order[j] = real_action->id;
2572 } else {
2573 log_sg("Unknown action \'%s\'", modname[j]);
2574 loading->action.order[j] = ACTION_NONE;
2575 }
2576 }
2577
2578 free(modname);
2579 }
2580
2581 player_slots_iterate(pslot) {
2582 int plrno = player_slot_index(pslot);
2583 int nunits;
2584 int unro;
2585
2586 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2587 continue;
2588 }
2589
2591 "player%d.nunits", plrno);
2592
2593 for (unro = 0; unro < nunits; unro++) {
2594 int ei;
2595 int i;
2596 enum unit_activity activity;
2597 enum gen_action act;
2598
2600 "player%d.u%d.activity", plrno, unro);
2601
2602 if (ei >= 0 && ei < loading->activities.size) {
2603 bool found = FALSE;
2604
2605 activity = unit_activity_by_name(loading->activities.order[ei],
2607
2608 act = activity_default_action(activity);
2609
2610 for (i = 0; i < loading->action.size; i++) {
2611 if (act == loading->action.order[i]) {
2612 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2613 plrno, unro);
2614 found = TRUE;
2615 break;
2616 }
2617 }
2618
2619 if (!found) {
2620 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
2621 plrno, unro);
2622 }
2623 }
2624 }
2626 }
2627
2628 /* Researches */
2629 {
2630 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2631 int i;
2632
2633 for (i = 0; i < count; i++) {
2634 /* It's ok for old savegames to have these entries. */
2635 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
2636 }
2637 }
2638
2639 player_slots_iterate(pslot) {
2640 int plrno = player_slot_index(pslot);
2641 int ncities;
2642 int cnro;
2643
2644 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2645 continue;
2646 }
2647
2649 "player%d.dc_total", plrno);
2650
2651 for (cnro = 0; cnro < ncities; cnro++) {
2652 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
2653 plrno, cnro);
2654 }
2656}
2657
2658/************************************************************************/
2663{
2664 /* Check status and return if not OK (sg_success FALSE). */
2665 sg_check_ret();
2666
2667 /* Capital information was not saved in older savegames,
2668 * so we have no capital setup at all at the moment.
2669 * Best we can do is to do recalculation now. It might be
2670 * a bit off compared to the situation before the game was saved,
2671 * but definitely better than not setting capitals at all. */
2672 players_iterate_alive(pplayer) {
2673 update_capital(pplayer);
2675}
2676
2677/************************************************************************/
2685{
2686 /* Check status and return if not OK (sg_success != TRUE). */
2687 sg_check_ret();
2688
2689 log_debug("Upgrading data from savegame to version 3.4.0");
2690}
2691
2692/************************************************************************/
2696#ifdef FREECIV_DEV_SAVE_COMPAT
2697static void compat_load_dev(struct loaddata *loading)
2698{
2699 int game_version;
2700
2701 /* Check status and return if not OK (sg_success FALSE). */
2702 sg_check_ret();
2703
2704 log_verbose("Upgrading data between development revisions");
2705
2706 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2707 "No save version found");
2708
2709#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
2710
2711 if (game_version < 3029100) {
2712 /* Before version number bump to 3.2.91, September 2023 */
2713
2714 {
2715 const char *str = secfile_lookup_str_default(loading->file, nullptr,
2716 "savefile.orig_version");
2717
2718 if (str == nullptr) {
2719 /* Make sure CURRENTLY running version does not
2720 * end as orig_version when we resave. */
2721 secfile_insert_str(loading->file, "old savegame3, or older",
2722 "savefile.orig_version");
2723 }
2724 }
2725
2726 /* Add acquire_t entries for cities */
2727 {
2728 player_slots_iterate(pslot) {
2729 int plrno = player_slot_index(pslot);
2730 int ncities;
2731 int cnro;
2732 bool first_city;
2733
2734 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2735 continue;
2736 }
2737
2739 "player%d.got_first_city",
2740 plrno);
2741 if (first_city) {
2742 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2743 int flagcount = 0;
2744 const char **flags_sg;
2745 size_t nval;
2746 int i;
2747
2749
2751 "player%d.flags", plrno);
2752
2753 for (i = 0; i < nval; i++) {
2756
2758 }
2759
2761 "player%d.flags", plrno);
2762
2764 }
2765
2767 "player%d.ncities", plrno);
2768
2769 for (cnro = 0; cnro < ncities; cnro++) {
2770 if (secfile_entry_lookup(loading->file,
2771 "player%d.c%d.acquire_t",
2772 plrno, cnro) == nullptr) {
2774 "player%d.c%d.original",
2775 plrno, cnro) != plrno) {
2777 "player%d.c%d.acquire_t",
2778 plrno, cnro);
2779 } else {
2781 "player%d.c%d.acquire_t",
2782 plrno, cnro);
2783 }
2784 }
2785 if (secfile_entry_lookup(loading->file,
2786 "player%d.c%d.wlcb",
2787 plrno, cnro) == nullptr) {
2789 "player%d.c%d.wlcb",
2790 plrno, cnro);
2791 }
2792 }
2794 }
2795
2796 /* Add orders_max_length entries for players */
2797 {
2798 player_slots_iterate(pslot) {
2799 int plrno = player_slot_index(pslot);
2800
2801 if (secfile_section_lookup(loading->file, "player%d", plrno) != nullptr
2803 "player%d.orders_max_length", plrno)
2804 == nullptr) {
2805 size_t nunits;
2806 int unro;
2807 size_t olist_max_length = 0;
2808
2810 "player%d.nunits", plrno);
2811
2812 for (unro = 0; unro < nunits; unro++) {
2813 int ol_length
2815 "player%d.u%d.orders_length",
2816 plrno, unro);
2817
2819 }
2820
2822 "player%d.orders_max_length", plrno);
2823 }
2825 }
2826
2827 {
2828 int action_count;
2829
2831 "savefile.action_size");
2832
2833 if (action_count > 0) {
2834 const char **modname;
2835 const char **savemod;
2836 int j;
2837 const char *clean_name = "Clean";
2838
2839 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2840 "savefile.action_vector");
2841
2843
2844 for (j = 0; j < action_count; j++) {
2845 if (!fc_strcasecmp("Clean Pollution", modname[j])
2846 || !fc_strcasecmp("Clean Fallout", modname[j])) {
2847 savemod[j] = clean_name;
2848 } else {
2849 savemod[j] = modname[j];
2850 }
2851 }
2852
2854 "savefile.action_vector");
2855
2856 free(savemod);
2857 }
2858 }
2859
2860 {
2861 int activities_count;
2862
2864 "savefile.activities_size");
2865
2866 if (activities_count > 0) {
2867 const char **modname;
2868 const char **savemod;
2869 int j;
2870 const char *clean_name = "Clean";
2871
2872 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2873 "savefile.activities_vector");
2874
2876
2877 for (j = 0; j < activities_count; j++) {
2878 if (!fc_strcasecmp("Pollution", modname[j])
2879 || !fc_strcasecmp("Fallout", modname[j])) {
2880 savemod[j] = clean_name;
2881 } else {
2882 savemod[j] = modname[j];
2883 }
2884 }
2885
2887 "savefile.activities_vector");
2888
2889 free(savemod);
2890 }
2891 }
2892
2893 /* Server setting migration. */
2894 {
2895 int set_count;
2896
2897 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2898 bool gamestart_valid = FALSE;
2899
2902 "settings.gamestart_valid");
2903
2904 if (!gamestart_valid) {
2905 int i;
2906
2907 /* Older savegames saved gamestart values even when they were not valid.
2908 * Silence warnings caused by them. */
2909 for (i = 0; i < set_count; i++) {
2910 secfile_entry_ignore(loading->file, "settings.set%d.gamestart", i);
2911 secfile_entry_ignore(loading->file, "settings.set%d.gamesetdef", i);
2912 }
2913 }
2914 }
2915 }
2916
2917 {
2918 int ssa_count;
2919
2921 "savefile.server_side_agent_size");
2922 if (ssa_count > 0) {
2923 const char **modname;
2924 const char **savemod;
2925 int j;
2926 const char *aw_name = "AutoWorker";
2927
2928 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2929 "savefile.server_side_agent_list");
2930
2931 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2932
2933 for (j = 0; j < ssa_count; j++) {
2934 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2935 savemod[j] = aw_name;
2936 } else {
2937 savemod[j] = modname[j];
2938 }
2939 }
2940
2942 "savefile.server_side_agent_list");
2943
2944 free(savemod);
2945 }
2946 }
2947
2948 } /* Version < 3.2.91 */
2949
2950 if (game_version < 3029200) {
2951 /* Before version number bump to 3.2.92, June 2024 */
2952
2953 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2954
2955 /* World Peace has never started in the old savegame. */
2956 game.info.turn
2957 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2960 "game.world_peace_start");
2962 "game.world_peace_start");
2963
2964 /* Last turn change time as a float, not integer multiplied by 100 */
2965 {
2966 float tct = secfile_lookup_int_default(loading->file, 0,
2967 "game.last_turn_change_time") / 100.0;
2968
2969 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2970 }
2971
2972 /* Add actions for unit activities */
2973 loading->activities.size
2975 "savefile.activities_size");
2976 if (loading->activities.size) {
2977 loading->activities.order
2978 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2979 "savefile.activities_vector");
2980 sg_failure_ret(loading->activities.size != 0,
2981 "Failed to load activity order: %s",
2982 secfile_error());
2983 }
2984
2985 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2986 "savefile.action_size");
2987
2988 sg_failure_ret(loading->action.size > 0,
2989 "Failed to load action order: %s",
2990 secfile_error());
2991
2992 if (loading->action.size) {
2993 const char **modname;
2994 int j;
2995
2996 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2997 "savefile.action_vector");
2998
2999 loading->action.order = fc_calloc(loading->action.size,
3000 sizeof(*loading->action.order));
3001
3002 for (j = 0; j < loading->action.size; j++) {
3004
3005 if (real_action) {
3006 loading->action.order[j] = real_action->id;
3007 } else {
3008 log_sg("Unknown action \'%s\'", modname[j]);
3009 loading->action.order[j] = ACTION_NONE;
3010 }
3011 }
3012
3013 free(modname);
3014 }
3015
3016 player_slots_iterate(pslot) {
3017 int plrno = player_slot_index(pslot);
3018 int nunits;
3019 int unro;
3020
3021 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3022 continue;
3023 }
3024
3026 "player%d.nunits", plrno);
3027
3028 for (unro = 0; unro < nunits; unro++) {
3029 int ei;
3030 int i;
3031 enum unit_activity activity;
3032 enum gen_action act;
3033
3035 "player%d.u%d.activity", plrno, unro);
3036
3037 if (ei >= 0 && ei < loading->activities.size) {
3038 bool found = FALSE;
3039
3040 activity = unit_activity_by_name(loading->activities.order[ei],
3042 act = activity_default_action(activity);
3043
3044 for (i = 0; i < loading->action.size; i++) {
3045 if (act == loading->action.order[i]) {
3046 secfile_insert_int(loading->file, i, "player%d.u%d.action",
3047 plrno, unro);
3048 found = TRUE;
3049 break;
3050 }
3051 }
3052
3053 if (!found) {
3054 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
3055 plrno, unro);
3056 }
3057 }
3058 }
3060
3061 /* Researches */
3062 {
3063 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
3064 int i;
3065
3066 for (i = 0; i < count; i++) {
3067 /* It's ok for old savegames to have these entries. */
3068 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
3069 }
3070 }
3071
3072 } /* Version < 3.2.92 */
3073
3074 if (game_version < 3029300) {
3075 /* Before version number bump to 3.2.93 */
3076
3077 {
3078 int action_count;
3079
3081 "savefile.action_size");
3082
3083 if (action_count > 0) {
3084 const char **modname;
3085 const char **savemod;
3086 int j;
3087 const char *cc1_name = "Conquer City Shrink";
3088 const char *cc2_name = "Conquer City Shrink 2";
3089 const char *cc3_name = "Conquer City Shrink 3";
3090 const char *cc4_name = "Conquer City Shrink 4";
3091
3092 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3093 "savefile.action_vector");
3094
3096
3097 for (j = 0; j < action_count; j++) {
3098 if (!fc_strcasecmp("Conquer City", modname[j])) {
3099 savemod[j] = cc1_name;
3100 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
3101 savemod[j] = cc2_name;
3102 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
3103 savemod[j] = cc3_name;
3104 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
3105 savemod[j] = cc4_name;
3106 } else {
3107 savemod[j] = modname[j];
3108 }
3109 }
3110
3112 "savefile.action_vector");
3113
3114 free(savemod);
3115 }
3116 }
3117
3118 player_slots_iterate(pslot) {
3119 int plrno = player_slot_index(pslot);
3120 int ncities;
3121 int cnro;
3122
3123 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3124 continue;
3125 }
3126
3128 "player%d.dc_total", plrno);
3129
3130 for (cnro = 0; cnro < ncities; cnro++) {
3131 if (!secfile_entry_lookup(loading->file, "player%d.dc%d.original",
3132 plrno, cnro)) {
3133 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
3134 plrno, cnro);
3135 }
3136 }
3138 } /* Version < 3.2.93 */
3139
3140#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3141
3142#ifdef FREECIV_DEV_SAVE_COMPAT_3_4
3143
3144 if (game_version < 3039100) {
3145 /* Before version number bump to 3.3.91 */
3146
3147 } /* Version < 3.3.91 */
3148
3149#endif /* FREECIV_DEV_SAVE_COMPAT_3_4 */
3150}
3151
3152/************************************************************************/
3156static void compat_post_load_dev(struct loaddata *loading)
3157{
3158 int game_version;
3159
3160 /* Check status and return if not OK (sg_success FALSE). */
3161 sg_check_ret();
3162
3163 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
3164 game_version = 2060000;
3165 }
3166
3167#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
3168
3169 if (game_version < 3029100) {
3170 /* Before version number bump to 3.2.91 */
3171
3172 } /* Version < 3.2.91 */
3173
3174#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3175}
3176#endif /* FREECIV_DEV_SAVE_COMPAT */
3177
3178/************************************************************************/
3181enum ai_level ai_level_convert(int old_level)
3182{
3183 switch (old_level) {
3184 case 1:
3185 return AI_LEVEL_AWAY;
3186 case 2:
3187 return AI_LEVEL_NOVICE;
3188 case 3:
3189 return AI_LEVEL_EASY;
3190 case 5:
3191 return AI_LEVEL_NORMAL;
3192 case 7:
3193 return AI_LEVEL_HARD;
3194 case 8:
3195 return AI_LEVEL_CHEATING;
3196 case 10:
3197#ifdef FREECIV_DEBUG
3198 return AI_LEVEL_EXPERIMENTAL;
3199#else /* FREECIV_DEBUG */
3200 return AI_LEVEL_HARD;
3201#endif /* FREECIV_DEBUG */
3202 }
3203
3204 return ai_level_invalid();
3205}
3206
3207/************************************************************************/
3210enum barbarian_type barb_type_convert(int old_type)
3211{
3212 switch (old_type) {
3213 case 0:
3214 return NOT_A_BARBARIAN;
3215 case 1:
3216 return LAND_BARBARIAN;
3217 case 2:
3218 return SEA_BARBARIAN;
3219 }
3220
3221 return barbarian_type_invalid();
3222}
struct action * action_by_rule_name(const char *name)
Definition actions.c:1100
int action_number(const struct action *action)
Definition actions.c:1229
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_iterate_end
Definition actions.h:218
#define action_get_activity(_pact_)
Definition actions.h:464
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_NONE
Definition actions.h:59
struct @130::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:249
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
char * incite_cost
Definition comments.c:77
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define 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:215
#define EC_SPECIAL
Definition fc_types.h:809
revolen_type
Definition fc_types.h:978
@ REVOLEN_RANDOM
Definition fc_types.h:980
@ REVOLEN_RANDQUICK
Definition fc_types.h:982
@ REVOLEN_FIXED
Definition fc_types.h:979
@ REVOLEN_QUICKENING
Definition fc_types.h:981
#define DIR8_ORIGIN
Definition fc_types.h:316
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:743
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_SAVETURNS
Definition game.h:685
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:571
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:703
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c:133
int len
Definition packhand.c:129
int player_slot_count(void)
Definition player.c:415
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
#define ANON_USER_NAME
Definition player.h:48
#define player_slots_iterate(_pslot)
Definition player.h:538
#define players_iterate_alive_end
Definition player.h:562
#define player_slots_iterate_end
Definition player.h:542
#define players_iterate_alive(_pplayer)
Definition player.h:557
void update_capital(struct player *pplayer)
Definition plrhand.c:731
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
bool secfile_entry_delete(struct section_file *secfile, const char *path,...)
bool entry_set_name(struct entry *pentry, const char *name)
bool secfile_lookup_enum_data(const struct section_file *secfile, int *pvalue, bool bitwise, secfile_enum_name_data_fn_t name_fn, secfile_data_t data, const char *path,...)
const struct entry_list * section_entries(const struct section *psection)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
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_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define entry_list_iterate(entlist, pentry)
#define secfile_replace_float(secfile, value, path,...)
#define secfile_replace_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
struct extra_type * resource_by_identifier(const char identifier)
Definition savecompat.c:335
int current_compat_ver(void)
Definition savecompat.c:233
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:273
bool sg_success
Definition savecompat.c:35
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:572
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:37
static struct compatibility compat[]
Definition savecompat.c:117
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:353
static void upgrade_unit_order_targets(struct unit *act_unit)
static void compat_load_030300(struct loaddata *loading, enum sgf_version format_class)
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:243
static const int compat_num
Definition savecompat.c:144
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:715
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:97
int char2num(char ch)
Definition savecompat.c:279
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:154
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:696
static int increase_secfile_turn_int(struct loaddata *loading, const char *key, int old_def, bool keep_default)
enum ai_level ai_level_convert(int old_level)
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:255
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:320
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:589
static void compat_load_030200(struct loaddata *loading, enum sgf_version format_class)
static void compat_post_load_030300(struct loaddata *loading, enum sgf_version format_class)
enum tile_special_type special_by_rule_name(const char *name)
Definition savecompat.c:294
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:205
static void compat_load_030400(struct loaddata *loading, enum sgf_version format_class)
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:310
static void compat_load_030100(struct loaddata *loading, enum sgf_version format_class)
static void insert_server_side_agent(struct loaddata *loading, enum sgf_version format_class)
#define compat_current
Definition savecompat.c:145
#define sg_check_ret(...)
Definition savecompat.h:148
#define sg_warn(condition, message,...)
Definition savecompat.h:158
tile_special_type
Definition savecompat.h:29
@ S_LAST
Definition savecompat.h:38
#define hex_chars
Definition savecompat.h:203
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:182
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:175
#define MAX_TRADE_ROUTES_OLD
Definition savecompat.h:220
sgf_version
Definition savecompat.h:27
@ SAVEGAME_2
Definition savecompat.h:27
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:144
const char * setcompat_S3_2_name_from_S3_1(const char *old_name)
Definition setcompat.c:62
struct setting * setting_by_name(const char *name)
Definition settings.c:3349
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4311
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4267
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:4108
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:157
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:85
#define specialist_type_iterate(sp)
Definition specialist.h:79
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
int world_peace_start
Definition game.h:245
struct packet_game_info info
Definition game.h:89
struct civ_game::@32::@36 server
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@44::@46 server
int huts_absolute
Definition map_types.h:108
const load_version_func_t post_load
Definition savecompat.c:102
const load_version_func_t load
Definition savecompat.c:101
struct name_translation name
Definition specialist.h:31
Definition tile.h:50
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:139
int length
Definition unit.h:197
bool has_orders
Definition unit.h:195
enum unit_activity activity
Definition unit.h:158
enum gen_action action
Definition unit.h:159
struct unit::@83 orders
struct extra_type * activity_target
Definition unit.h:166
struct unit_order * list
Definition unit.h:200
enum server_side_agent ssa_controller
Definition unit.h:174
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c: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:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:127
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:249
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define terrain_type_iterate_end
Definition terrain.h:273
void free_unit_orders(struct unit *punit)
Definition unit.c:1826
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:402
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2942
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
#define unit_tile(_pu)
Definition unit.h:407
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1084
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1274
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1313