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", NULL
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, NULL, NULL },
120 /* version 1 and 2 is not used */
121 /* version 3: first savegame2 format, so no compat functions for translation
122 * from previous format */
123 { 3, NULL, NULL },
124 /* version 4 to 9 are reserved for possible changes in 2.3.x */
125 { 10, compat_load_020400, NULL },
126 /* version 11 to 19 are reserved for possible changes in 2.4.x */
127 { 20, compat_load_020500, NULL },
128 /* version 21 to 29 are reserved for possible changes in 2.5.x */
129 { 30, compat_load_020600, NULL },
130 /* version 31 to 39 are reserved for possible changes in 2.6.x */
131 { 40, compat_load_030000, NULL },
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, NULL },
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, NULL },
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 != NULL) {
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 != NULL) {
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(NULL != pch && '\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
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] != NULL; 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 NULL;
329}
330
331/************************************************************************/
334struct extra_type *resource_by_identifier(const char identifier)
335{
337 if (presource->data.resource->id_old_save == identifier) {
338 return presource;
339 }
341
342 return NULL;
343}
344
345/* =======================================================================
346 * Compatibility functions for loading a game.
347 * ======================================================================= */
348
349/************************************************************************/
354{
355 /* Check status and return if not OK (sg_success FALSE). */
356 sg_check_ret();
357
358 log_debug("Upgrading data from savegame to version 2.4.0");
359
360 /* Add the default player AI. */
361 player_slots_iterate(pslot) {
362 int ncities, i, plrno = player_slot_index(pslot);
363
364 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
365 continue;
366 }
367
369 "player%d.ai_type", player_slot_index(pslot));
370
371 /* Create dummy citizens information. We do not know if citizens are
372 * activated due to the fact that this information
373 * (game.info.citizen_nationality) is not available, but adding the
374 * information does no harm. */
376 "player%d.ncities", plrno);
377 if (ncities > 0) {
378 for (i = 0; i < ncities; i++) {
380 "player%d.c%d.size", plrno, i);
381 if (size > 0) {
383 "player%d.c%d.citizen%d", plrno, i, plrno);
384 }
385 }
386 }
387
389
390 /* Player colors are assigned at the end of player loading, as this
391 * needs information not available here. */
392
393 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
394 * workaround in later 2.3.x); see gna bug #19029.
395 * (The structure of this code is odd as it avoids relying on knowledge of
396 * xsize/ysize, which haven't been extracted from the savefile yet.) */
397 {
398 if (has_capability("knownv2",
399 secfile_lookup_str(loading->file, "savefile.options"))) {
400 /* This savefile contains known information in a sane format.
401 * Just move any entries to where 2.4.x+ expect to find them. */
402 struct section *map = secfile_section_by_name(loading->file, "map");
403
404 if (map != NULL) {
406 const char *name = entry_name(pentry);
407
408 if (!fc_strncmp(name, "kvb", 3)) {
409 /* Rename the "kvb..." entry to "k..." */
410 char *name2 = fc_strdup(name), *newname = name2 + 2;
411
412 *newname = 'k';
413 /* Savefile probably contains existing "k" entries, which are bogus
414 * so we trash them. */
415 secfile_entry_delete(loading->file, "map.%s", newname);
417 FC_FREE(name2);
418 }
420 }
421 /* Could remove "knownv2" from savefile.options, but it's doing
422 * no harm there. */
423 } else {
424 /* This savefile only contains known information in the broken
425 * format. Try to recover it to a sane format. */
426 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
427 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
428 const int maxslots = 128, maxmapsize = 512;
429 const int lines = maxslots/32;
430 int xsize = 0, y, l, j, x;
431 unsigned int known_row_old[lines * maxmapsize],
433 /* Process a map row at a time */
434 for (y = 0; y < maxmapsize; y++) {
435 /* Look for broken info to convert */
436 bool found = FALSE;
438 for (l = 0; l < lines; l++) {
439 for (j = 0; j < 8; j++) {
440 const char *s =
442 "map.k%02d_%04d", l * 8 + j, y);
443 if (s) {
444 found = TRUE;
445 if (xsize == 0) {
446 xsize = strlen(s);
447 }
448 sg_failure_ret(xsize == strlen(s),
449 "Inconsistent xsize in map.k%02d_%04d",
450 l * 8 + j, y);
451 for (x = 0; x < xsize; x++) {
452 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
453 }
454 }
455 }
456 }
457 if (found) {
458 /* At least one entry found for this row. Let's hope they were
459 * all there. */
460 /* Attempt to munge into sane format */
461 int p;
462 memset(known_row, 0, sizeof(known_row));
463 /* Iterate over possible player slots */
464 for (p = 0; p < maxslots; p++) {
465 l = p / 32;
466 for (x = 0; x < xsize; x++) {
467 /* This test causes bit-shifts of >=32 (undefined behavior), but
468 * on common platforms, information happens not to be lost, just
469 * oddly arranged. */
470 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
471 known_row[l * xsize + x] |= (1u << (p - l * 32));
472 }
473 }
474 }
475 /* Save sane format back to memory representation of secfile for
476 * real loading code to pick up */
477 for (l = 0; l < lines; l++) {
478 for (j = 0; j < 8; j++) {
479 /* Save info for all slots (not just used ones). It's only
480 * memory, after all. */
481 char row[xsize+1];
482 for (x = 0; x < xsize; x++) {
483 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
484 }
485 row[xsize] = '\0';
487 "map.k%02d_%04d", l * 8 + j, y);
488 }
489 }
490 }
491 }
492 }
493 }
494
495 /* Server setting migration. */
496 {
497 int set_count;
498
499 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
500 int i, new_opt = set_count;
501 bool gamestart_valid
503 "settings.gamestart_valid");
504
505 for (i = 0; i < set_count; i++) {
506 const char *name
507 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
508
509 if (!name) {
510 continue;
511 }
512
513 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
514 * This is now controlled by the "autosaves" setting. */
515 if (!fc_strcasecmp("saveturns", name)) {
516 /* XXX: Hardcodes details from GAME_AUTOSAVES_DEFAULT
517 * and settings.c:autosaves_name() (but these defaults reflect
518 * 2.3's behavior). */
519 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
520 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
521 int nturns;
522
524 "settings.set%d.value", i)) {
525 if (nturns == 0) {
526 /* Invent a new "autosaves" setting */
528 "settings.set%d.value", new_opt);
529 /* Pick something valid for saveturns */
531 "settings.set%d.value", i);
532 } else {
534 "settings.set%d.value", new_opt);
535 }
536 } else {
537 log_sg("Setting '%s': %s", name, secfile_error());
538 }
539 if (gamestart_valid) {
541 "settings.set%d.gamestart", i)) {
542 if (nturns == 0) {
543 /* Invent a new "autosaves" setting */
545 "settings.set%d.gamestart", new_opt);
546 /* Pick something valid for saveturns */
548 "settings.set%d.gamestart", i);
549 } else {
551 "settings.set%d.gamestart", new_opt);
552 }
553 } else {
554 log_sg("Setting '%s': %s", name, secfile_error());
555 }
556 }
557 } else if (!fc_strcasecmp("autosaves", name)) {
558 /* Sanity check. This won't trigger on an option we've just
559 * invented, as the loop won't include it. */
560 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
561 "savefile. It may have been overridden.");
562 }
563 }
564 }
565 }
566}
567
568/************************************************************************/
571static const char *killcitizen_enum_str(secfile_data_t data, int bit)
572{
573 switch (bit) {
574 case UMT_LAND:
575 return "LAND";
576 case UMT_SEA:
577 return "SEA";
578 case UMT_BOTH:
579 return "BOTH";
580 }
581
582 return NULL;
583}
584
585/************************************************************************/
590{
591 const char *modname[] = { "Road", "Railroad" };
592 const char *old_activities_names[] = {
593 "Idle",
594 "Pollution",
595 "Unused Road",
596 "Mine",
597 "Irrigate",
598 "Mine",
599 "Irrigate",
600 "Fortified",
601 "Fortress",
602 "Sentry",
603 "Unused Railroad",
604 "Pillage",
605 "Goto",
606 "Explore",
607 "Transform",
608 "Unused",
609 "Unused Airbase",
610 "Fortifying",
611 "Fallout",
612 "Unused Patrol",
613 "Base"
614 };
615
616 /* Check status and return if not OK (sg_success FALSE). */
617 sg_check_ret();
618
619 log_debug("Upgrading data from savegame to version 2.5.0");
620
621 secfile_insert_int(loading->file, 2, "savefile.roads_size");
622 secfile_insert_int(loading->file, 0, "savefile.trait_size");
623
625 "savefile.roads_vector");
626
627 secfile_insert_int(loading->file, 19, "savefile.activities_size");
629 "savefile.activities_vector");
630
631 /* Server setting migration. */
632 {
633 int set_count;
634
635 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
636 int i;
637 bool gamestart_valid
639 "settings.gamestart_valid");
640 for (i = 0; i < set_count; i++) {
641 const char *name
642 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
643 if (!name) {
644 continue;
645 }
646 /* In 2.4.x and prior, "killcitizen" listed move types that
647 * killed citizens after successful attack. Now killcitizen
648 * is just boolean and classes affected are defined in ruleset. */
649 if (!fc_strcasecmp("killcitizen", name)) {
650 int value;
651
652 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
654 "settings.set%d.value", i)) {
655 /* Lowest bit of old killcitizen value indicates if
656 * land units should kill citizens. We take that as
657 * new boolean killcitizen value. */
658 if (value & 0x1) {
660 "settings.set%d.value", i);
661 } else {
663 "settings.set%d.value", i);
664 }
665 } else {
666 log_sg("Setting '%s': %s", name, secfile_error());
667 }
668 if (gamestart_valid) {
669 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
671 "settings.set%d.gamestart", i)) {
672 /* Lowest bit of old killcitizen value indicates if
673 * land units should kill citizens. We take that as
674 * new boolean killcitizen value. */
675 if (value & 0x1) {
677 "settings.set%d.gamestart", i);
678 } else {
680 "settings.set%d.gamestart", i);
681 }
682 } else {
683 log_sg("Setting '%s': %s", name, secfile_error());
684 }
685 }
686 }
687 }
688 }
689 }
690}
691
692/************************************************************************/
696{
697 switch (type) {
698 case REVOLEN_FIXED:
699 return "FIXED";
700 case REVOLEN_RANDOM:
701 return "RANDOM";
703 return "QUICKENING";
705 return "RANDQUICK";
706 }
707
708 return "";
709}
710
711/************************************************************************/
716{
717 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
718 int tsize;
719 int ti;
720 int turn;
721
722 /* Check status and return if not OK (sg_success FALSE). */
723 sg_check_ret();
724
725 log_debug("Upgrading data from savegame to version 2.6.0");
726
727 /* Terrain mapping table - use current ruleset as we have no way to know
728 * any other old values. */
729 ti = 0;
731 char buf[2];
732
733 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
735 buf[1] = '\0';
736 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
738
739 /* Server setting migration. */
740 {
741 int set_count;
742
743 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
744 char value_buffer[1024] = "";
745 char gamestart_buffer[1024] = "";
746 int i;
747 int dcost = -1;
748 int dstartcost = -1;
751 bool gamestart_valid
753 "settings.gamestart_valid");
754 int new_set_count;
755
756 for (i = 0; i < set_count; i++) {
757 const char *name
758 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
759 if (!name) {
760 continue;
761 }
762
763 /* In 2.5.x and prior, "spacerace" boolean controlled if
764 * spacerace victory condition was active. */
765 if (!fc_strcasecmp("spacerace", name)) {
766 bool value;
767
768 if (secfile_lookup_bool(loading->file, &value,
769 "settings.set%d.value", i)) {
770 if (value) {
771 if (value_buffer[0] != '\0') {
773 }
774 sz_strlcat(value_buffer, "SPACERACE");
775 }
776 } else {
777 log_sg("Setting '%s': %s", name, secfile_error());
778 }
779 if (secfile_lookup_bool(loading->file, &value,
780 "settings.set%d.gamestart", i)) {
781 if (value) {
782 if (gamestart_buffer[0] != '\0') {
784 }
785 sz_strlcat(gamestart_buffer, "SPACERACE");
786 }
787 } else {
788 log_sg("Setting '%s': %s", name, secfile_error());
789 }
790
791 /* We cannot delete old values from the secfile, or rather cannot
792 * change index of the later settings. Renumbering them is not easy as
793 * we don't know type of each setting we would encounter.
794 * So we keep old setting values and only add new "victories" setting. */
795 } else if (!fc_strcasecmp("alliedvictory", name)) {
796 bool value;
797
798 if (secfile_lookup_bool(loading->file, &value,
799 "settings.set%d.value", i)) {
800 if (value) {
801 if (value_buffer[0] != '\0') {
803 }
804 sz_strlcat(value_buffer, "ALLIED");
805 }
806 } else {
807 log_sg("Setting '%s': %s", name, secfile_error());
808 }
809 if (secfile_lookup_bool(loading->file, &value,
810 "settings.set%d.gamestart", i)) {
811 if (value) {
812 if (gamestart_buffer[0] != '\0') {
814 }
815 sz_strlcat(gamestart_buffer, "ALLIED");
816 }
817 } else {
818 log_sg("Setting '%s': %s", name, secfile_error());
819 }
820 } else if (!fc_strcasecmp("revolen", name)) {
821 int value;
822
823 if (secfile_lookup_int(loading->file, &value,
824 "settings.set%d.value", i)) {
825 /* 0 meant RANDOM 1-5 */
826 if (value == 0) {
829 "settings.set%d.value", i);
830 } else {
832 }
833 } else {
834 log_sg("Setting '%s': %s", name, secfile_error());
835 }
836 if (secfile_lookup_int(loading->file, &value,
837 "settings.set%d.gamestart", i)) {
838 /* 0 meant RANDOM 1-5 */
839 if (value == 0) {
842 "settings.set%d.gamestart", i);
843 } else {
845 }
846 } else {
847 log_sg("Setting '%s': %s", name, secfile_error());
848 }
849 } else if (!fc_strcasecmp("happyborders", name)) {
850 bool value;
851
852 if (secfile_lookup_bool(loading->file, &value,
853 "settings.set%d.value", i)) {
854 secfile_entry_delete(loading->file, "settings.set%d.value", i);
855 if (value) {
856 secfile_insert_str(loading->file, "NATIONAL",
857 "settings.set%d.value", i);
858 } else {
859 secfile_insert_str(loading->file, "DISABLED",
860 "settings.set%d.value", i);
861 }
862 } else {
863 log_sg("Setting '%s': %s", name, secfile_error());
864 }
865 if (secfile_lookup_bool(loading->file, &value,
866 "settings.set%d.gamestart", i)) {
867 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
868 if (value) {
869 secfile_insert_str(loading->file, "NATIONAL",
870 "settings.set%d.gamestart", i);
871 } else {
872 secfile_insert_str(loading->file, "DISABLED",
873 "settings.set%d.gamestart", i);
874 }
875 } else {
876 log_sg("Setting '%s': %s", name, secfile_error());
877 }
878 } else if (!fc_strcasecmp("team_pooled_research", name)) {
880 &team_pooled_research,
881 "settings.set%d.value", i),
882 "%s", secfile_error());
883 } else if (!fc_strcasecmp("diplcost", name)) {
884 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
885 if (secfile_lookup_int(loading->file, &dcost,
886 "settings.set%d.value", i)) {
887 } else {
888 log_sg("Setting '%s': %s", name, secfile_error());
889 }
890
892 "settings.set%d.gamestart", i)) {
893 } else {
894 log_sg("Setting '%s': %s", name, secfile_error());
895 }
896 } else if (!fc_strcasecmp("huts", name)) {
897 /* Scale of 'huts' changed. */
898 int hcount;
899
901 "settings.set%d.value", i)) {
902 } else {
903 log_sg("Setting '%s': %s", name, secfile_error());
904 }
905
906 /* Store old-style absolute value. */
908 }
909 }
910
911 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
912
913 if (dcost >= 0) {
914 new_set_count += 2;
915 }
916
917 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
918
919 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
920 set_count);
921 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
922 set_count);
923 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
924 set_count + 1);
925 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
926 set_count + 1);
927
928 if (dcost >= 0) {
929 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
930 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
931 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
932 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
933 }
934
935 if (gamestart_valid) {
936 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
937 set_count);
938 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
939 set_count + 1);
940
941 if (dcost >= 0) {
942 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
943 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
944 }
945 }
946 }
947 }
948
949 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
950 "Trait size: %s", secfile_error());
951
952 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
953
954 player_slots_iterate(pslot) {
955 int plrno = player_slot_index(pslot);
956 bool got_first_city;
957 int old_barb_type;
958 enum barbarian_type new_barb_type;
959 int i;
960 const char *name;
961 int score;
962 int units_num;
963
964 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
965 continue;
966 }
967
968 /* Renamed 'capital' to 'got_first_city'. */
970 "player%d.capital", plrno)) {
972 "player%d.got_first_city", plrno);
973 }
974
975 /* Add 'anonymous' qualifiers for user names */
976 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
978 "player%d.unassigned_user", plrno);
979
980 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
982 "player%d.unassigned_ranked", plrno);
983
984 /* Convert numeric barbarian type to textual */
986 "player%d.ai.is_barbarian", plrno);
989 "player%d.ai.barb_type", plrno);
990
991 /* Pre-2.6 didn't record when a player was created or died, so we have
992 * to assume they lived from the start of the game until last turn */
993 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
994
995 /* As if there never has been a war. */
996 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
997
998 /* Assume people were playing until current reload */
999 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
1000
1001 for (i = 0; i < tsize; i++) {
1002 int val;
1003
1004 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
1005 plrno, i);
1006 if (val != -1) {
1007 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
1008 }
1009
1011 "player%d.trait.mod%d", plrno, i),
1012 "Trait mod: %s", secfile_error());
1013 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1014 }
1015
1016 score = secfile_lookup_int_default(loading->file, -1,
1017 "player%d.units_built", plrno);
1018 if (score >= 0) {
1019 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1020 }
1021
1022 score = secfile_lookup_int_default(loading->file, -1,
1023 "player%d.units_killed", plrno);
1024 if (score >= 0) {
1025 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1026 }
1027
1028 score = secfile_lookup_int_default(loading->file, -1,
1029 "player%d.units_lost", plrno);
1030 if (score >= 0) {
1031 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1032 }
1033
1034 /* Units orders. */
1036 "player%d.nunits",
1037 plrno);
1038
1039 for (i = 0; i < units_num; i++) {
1040 int len;
1041
1043 "player%d.u%d.orders_last_move_safe",
1044 plrno, i)) {
1045 continue;
1046 }
1047
1049 "player%d.u%d.orders_length",
1050 plrno, i);
1051 if (len > 0) {
1052 char orders_str[len + 1];
1053 char *p;
1054
1057 "player%d.u%d.orders_list",
1058 plrno, i));
1059 if ((p = strrchr(orders_str, 'm'))
1060 || (p = strrchr(orders_str, 'M'))) {
1061 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1063 "player%d.u%d.orders_list", plrno, i);
1064 }
1065 }
1066 }
1068
1069 /* Add specialist order - loading time order is ok here, as we will use
1070 * that when we in later part of compatibility conversion use the specialist
1071 * values */
1073 "savefile.specialists_size");
1074 {
1075 const char **modname;
1076 int i = 0;
1077
1079
1083
1085 "savefile.specialists_vector");
1086
1087 free(modname);
1088 }
1089
1090 /* Replace all city specialist count fields with correct names */
1091 player_slots_iterate(pslot) {
1092 int plrno = player_slot_index(pslot);
1093 int ncities;
1094 int i;
1095
1096 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1097 continue;
1098 }
1099
1100 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1101
1102 for (i = 0; i < ncities; i++) {
1103 int k = 0;
1104
1106 struct specialist *psp = specialist_by_number(sp);
1107 int count;
1108
1110 "player%d.c%d.n%s",
1112 "specialist error: %s", secfile_error());
1113 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1115 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1116 plrno, i, k++);
1118 }
1120
1121 /* Build [research]. */
1122 {
1123 const struct {
1124 const char *name;
1125 enum entry_type type;
1126 } entries[] = {
1127 { "goal_name", ENTRY_STR },
1128 { "techs", ENTRY_INT },
1129 { "futuretech", ENTRY_INT },
1130 { "bulbs_before", ENTRY_INT },
1131 { "saved_name", ENTRY_STR },
1132 { "bulbs", ENTRY_INT },
1133 { "now_name", ENTRY_STR },
1134 { "got_tech", ENTRY_BOOL },
1135 { "done", ENTRY_STR }
1136 };
1137
1139 int count = 0;
1140 int i;
1141
1142 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1143 researches[i] = -1;
1144 }
1145
1146 player_slots_iterate(pslot) {
1147 int plrno = player_slot_index(pslot);
1148 int ival;
1149 bool bval;
1150 const char *sval;
1151 int j;
1152
1153 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1154 continue;
1155 }
1156
1157 /* Get the research number. */
1158 if (team_pooled_research) {
1160 "player%d.team_no", plrno);
1161 } else {
1162 i = plrno;
1163 }
1164
1166 "Research out of bounds (%d)!", i);
1167
1168 /* Find the index in [research] section. */
1169 if (researches[i] == -1) {
1170 /* This is the first player for this research. */
1171 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1172 researches[i] = count;
1173 count++;
1174 }
1175 i = researches[i];
1176
1177 /* Move entries. */
1178 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1179 switch (entries[j].type) {
1180 case ENTRY_BOOL:
1181 if (secfile_lookup_bool(loading->file, &bval,
1182 "player%d.research.%s",
1183 plrno, entries[j].name)) {
1184 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1185 i, entries[j].name);
1186 }
1187 break;
1188 case ENTRY_INT:
1189 if (secfile_lookup_int(loading->file, &ival,
1190 "player%d.research.%s",
1191 plrno, entries[j].name)) {
1192 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1193 i, entries[j].name);
1194 }
1195 break;
1196 case ENTRY_STR:
1197 if ((sval = secfile_lookup_str(loading->file,
1198 "player%d.research.%s",
1199 plrno, entries[j].name))) {
1200 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1201 i, entries[j].name);
1202 }
1203 break;
1204 case ENTRY_FLOAT:
1206 "Research related entry marked as float.");
1207 break;
1210 break;
1211 case ENTRY_LONG_COMMENT:
1213 break;
1214 case ENTRY_ILLEGAL:
1216 break;
1217 }
1218 }
1220 secfile_insert_int(loading->file, count, "research.count");
1221 }
1222
1223 /* Add diplstate type order. */
1225 "savefile.diplstate_type_size");
1226 if (DS_LAST > 0) {
1227 const char **modname;
1228 int i;
1229 int j;
1230
1231 i = 0;
1232 modname = fc_calloc(DS_LAST, sizeof(*modname));
1233
1234 for (j = 0; j < DS_LAST; j++) {
1236 }
1237
1239 DS_LAST,
1240 "savefile.diplstate_type_vector");
1241 free(modname);
1242 }
1243
1244 /* Fix save games from Freeciv versions with a bug that made it view
1245 * "Never met" as closer than "Peace" or "Alliance". */
1246 player_slots_iterate(pslot) {
1247 int plrno = player_slot_index(pslot);
1248
1249 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1250 continue;
1251 }
1252
1254 int i = player_slot_index(pslot2);
1255 char buf[32];
1256 int current;
1257 int closest;
1258
1259 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1260 continue;
1261 }
1262
1263 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1264
1265 /* Read the current diplomatic state. */
1267 "%s.type",
1268 buf);
1269
1270 /* Read the closest diplomatic state. */
1272 "%s.max_state",
1273 buf);
1274
1275 if (closest == DS_NO_CONTACT
1276 && (current == DS_PEACE
1277 || current == DS_ALLIANCE)) {
1278 const char *name1 = secfile_lookup_str_default(loading->file, "",
1279 "player%d.name", plrno);
1280 const char *name2 = secfile_lookup_str_default(loading->file, "",
1281 "player%d.name", i);
1282 /* The current relationship is closer than what the save game
1283 * claims is the closes relationship ever. */
1284
1285 log_sg(_("The save game is wrong about what the closest"
1286 " relationship %s (player %d) and %s (player %d) have had is."
1287 " Fixing it..."),
1288 name1, plrno, name2, i);
1289
1290 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1291 }
1294}
1295
1296/************************************************************************/
1299static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1300 int old_def, bool keep_default)
1301{
1302 int value;
1303
1304 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1305
1306 if (value != old_def || !keep_default) {
1307 value++;
1308 secfile_replace_int(loading->file, value, "%s", key);
1309 }
1310
1311 return value;
1312}
1313
1314/************************************************************************/
1322{
1323 bool randsaved;
1324 int num_settings;
1325 bool started;
1326 int old_turn;
1327 int event_count;
1328 int i;
1329
1330 /* Check status and return if not OK (sg_success FALSE). */
1331 sg_check_ret();
1332
1333 log_debug("Upgrading data from savegame to version 3.0.0");
1334
1335 /* Rename "random.save" as "random.saved"
1336 * Note that it's not an error if a scenario does not have [random] at all. */
1337 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1338 secfile_insert_bool(loading->file, randsaved, "random.saved");
1339 }
1340
1341 /* Already started games should have their turn counts increased by 1 */
1342 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1343 started = TRUE;
1344
1345 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1347 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1348 } else {
1349 started = FALSE;
1350 }
1351
1352 player_slots_iterate(pslot) {
1353 int plrno = player_slot_index(pslot);
1354 const char *flag_names[1];
1355
1356 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1357 continue;
1358 }
1359
1360 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1361 plrno)) {
1363
1365 "player%d.flags", plrno);
1366 }
1367
1368 if (started) {
1369 int num = secfile_lookup_int_default(loading->file, 0,
1370 "player%d.nunits",
1371 plrno);
1372
1373 for (i = 0; i < num; i++) {
1374 char buf[64];
1375
1376 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1377
1379 }
1380
1381 num = secfile_lookup_int_default(loading->file, 0,
1382 "player%d.ncities", plrno);
1383
1384 for (i = 0; i < num; i++) {
1385 char buf[64];
1386
1387 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1388
1390 }
1391 }
1393
1394 /* Settings */
1396 "settings.set_count");
1397
1398 /* User meta server message is now a setting. */
1400 "game.meta_usermessage")) {
1401 const char *metamessage;
1402
1404 "game.meta_message");
1405
1406 /* Insert the meta message as a setting */
1407 secfile_insert_str(loading->file, "metamessage",
1408 "settings.set%d.name", num_settings);
1410 "settings.set%d.value", num_settings);
1411 secfile_insert_str(loading->file, "",
1412 "settings.set%d.gamestart", num_settings);
1413 num_settings++;
1414 }
1415
1416 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1417
1418 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1419
1420 for (i = 0; i < event_count; i++) {
1421 const char *etype;
1422
1423 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1424
1425 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1426 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1427 "event_cache.events%d.event", i);
1428 }
1429 }
1430}
1431
1432/************************************************************************/
1437{
1438 int ssa_size;
1439
1440 if (format_class == SAVEGAME_2) {
1441 /* Handled in savegame2 */
1442 return;
1443 }
1444
1446 "savefile.server_side_agent_size");
1447
1448 if (ssa_size != 0) {
1449 /* Already inserted. */
1450 return;
1451 }
1452
1453 /* Add server side agent order. */
1455 "savefile.server_side_agent_size");
1456 if (SSA_COUNT > 0) {
1457 const char **modname;
1458 int i;
1459 int j;
1460
1461 i = 0;
1462 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1463
1464 for (j = 0; j < SSA_COUNT; j++) {
1466 }
1467
1469 SSA_COUNT,
1470 "savefile.server_side_agent_list");
1471 free(modname);
1472 }
1473
1474 /* Insert server_side_agent unit field. */
1475 player_slots_iterate(pslot) {
1476 int unit;
1477 int units_num;
1478 int plrno = player_slot_index(pslot);
1479
1480 if (secfile_section_lookup(loading->file, "player%d", plrno)
1481 == NULL) {
1482 continue;
1483 }
1484
1485 /* Number of units the player has. */
1487 "player%d.nunits",
1488 plrno);
1489
1490 for (unit = 0; unit < units_num; unit++) {
1491 bool ai;
1492
1494 "player%d.u%d.server_side_agent",
1495 plrno, unit)
1496 != NULL) {
1497 /* Already updated? */
1498 continue;
1499 }
1500
1502 "player%d.u%d.ai",
1503 plrno, unit);
1504
1505 if (ai) {
1506 /* Autoworker and Autoexplore are separated by
1507 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1509 "player%d.u%d.server_side_agent",
1510 plrno, unit);
1511 } else {
1513 "player%d.u%d.server_side_agent",
1514 plrno, unit);
1515 }
1516 }
1518}
1519
1520/************************************************************************/
1528{
1529 /* Check status and return if not OK (sg_success FALSE). */
1530 sg_check_ret();
1531
1532 log_debug("Upgrading data from savegame to version 3.1.0");
1533
1534 /* Actions are now stored by number. */
1535 player_slots_iterate(pslot) {
1536 int unit;
1537 int units_num;
1538 int plrno = player_slot_index(pslot);
1539
1540 if (secfile_section_lookup(loading->file, "player%d", plrno)
1541 == NULL) {
1542 continue;
1543 }
1544
1545 /* Number of units the player has. */
1547 "player%d.nunits",
1548 plrno);
1549
1550 for (unit = 0; unit < units_num; unit++) {
1551 const char *action_unitstr;
1552 int order_len;
1553
1555 "player%d.u%d.orders_length",
1556 plrno, unit);
1557
1559 "player%d.u%d.action_list",
1560 plrno, unit))) {
1561 int order_num;
1562
1565 }
1566
1567 for (order_num = 0; order_num < order_len; order_num++) {
1569
1570 if (action_unitstr[order_num] == '?') {
1572 } else {
1574 }
1575
1576 if (order_num == 0) {
1577 /* The start of a vector has no number. */
1579 "player%d.u%d.action_vec",
1580 plrno, unit);
1581 } else {
1583 "player%d.u%d.action_vec,%d",
1584 plrno, unit, order_num);
1585 }
1586 }
1587 }
1588 }
1590
1591 {
1592 int action_count;
1593
1595 "savefile.action_size");
1596
1597 if (action_count > 0) {
1598 const char **modname;
1599 const char **savemod;
1600 int j;
1601 const char *dur_name = "Disband Unit Recover";
1602
1603 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1604 "savefile.action_vector");
1605
1607
1608 for (j = 0; j < action_count; j++) {
1609 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1610 savemod[j] = dur_name;
1611 } else {
1612 savemod[j] = modname[j];
1613 }
1614 }
1615
1617 "savefile.action_vector");
1618
1619 free(savemod);
1620 }
1621 }
1622
1623 /* Server setting migration. */
1624 {
1625 int set_count;
1626
1627 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1628 int i;
1629 bool gamestart_valid
1631 "settings.gamestart_valid");
1632
1633 /* Only add gamesetdef if gamestart is valid at all */
1634 if (gamestart_valid) {
1635 for (i = 0; i < set_count; i++) {
1636 const char *name
1637 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1638
1639 if (!name) {
1640 continue;
1641 }
1642
1644 "settings.set%d.gamesetdef", i);
1645 }
1646 }
1647 }
1648 }
1649
1650 /* Explicit server side agent was new in 3.1 */
1652}
1653
1654/************************************************************************/
1658{
1659 int i;
1660
1661 for (i = 0; i < act_unit->orders.length; i++) {
1662 struct unit_order *order = &act_unit->orders.list[i];
1663
1664 if (order->order != ORDER_ACTIVITY) {
1665 continue;
1666 }
1667
1668 switch (order->activity) {
1669 case ACTIVITY_CLEAN:
1670 case ACTIVITY_MINE:
1671 case ACTIVITY_IRRIGATE:
1672 case ACTIVITY_PLANT:
1673 case ACTIVITY_CULTIVATE:
1674 case ACTIVITY_TRANSFORM:
1675 case ACTIVITY_CONVERT:
1677 case ACTIVITY_BASE:
1678 case ACTIVITY_GEN_ROAD:
1679 case ACTIVITY_PILLAGE:
1680 action_iterate(act_id) {
1681 struct action *paction = action_by_number(act_id);
1682
1683 if (action_get_activity(paction) == order->activity) {
1684 order->order = ORDER_PERFORM_ACTION;
1685 order->action = action_number(paction);
1686 order->activity = ACTIVITY_LAST;
1687 break;
1688 }
1690 break;
1691 case ACTIVITY_SENTRY:
1692 /* Not an action */
1693 break;
1694 case ACTIVITY_EXPLORE:
1695 case ACTIVITY_IDLE:
1696 case ACTIVITY_GOTO:
1697 case ACTIVITY_FORTIFIED:
1698 case ACTIVITY_LAST:
1699 log_error("Activity %d is not supposed to appear in unit orders",
1700 order->activity);
1701 break;
1702 }
1703 }
1704}
1705
1706/************************************************************************/
1710{
1711 switch (dir) {
1712 case DIR8_NORTH:
1713 return DIR8_SOUTH;
1714 case DIR8_NORTHEAST:
1715 return DIR8_SOUTHWEST;
1716 case DIR8_EAST:
1717 return DIR8_WEST;
1718 case DIR8_SOUTHEAST:
1719 return DIR8_NORTHWEST;
1720 case DIR8_SOUTH:
1721 return DIR8_NORTH;
1722 case DIR8_SOUTHWEST:
1723 return DIR8_NORTHEAST;
1724 case DIR8_WEST:
1725 return DIR8_EAST;
1726 case DIR8_NORTHWEST:
1727 return DIR8_SOUTHEAST;
1728 }
1729
1730 return DIR8_ORIGIN;
1731}
1732
1733/************************************************************************/
1737{
1738 int i;
1739 struct tile *current_tile;
1740 struct tile *tgt_tile;
1741
1742 if (!unit_has_orders(act_unit)) {
1743 return;
1744 }
1745
1746 /* The order index is for the unit at its current tile. */
1747 current_tile = unit_tile(act_unit);
1748
1749 /* Rewind to the beginning of the orders */
1750 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1751 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1752
1753 if (!(prev_order->order == ORDER_PERFORM_ACTION
1757 current_tile = mapstep(&(wld.map), current_tile,
1758 dir_opposite(prev_order->dir));
1759 }
1760 }
1761
1762 /* Upgrade to explicit target tile */
1763 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1764 struct unit_order *order = &act_unit->orders.list[i];
1765
1766 if (order->order == ORDER_PERFORM_ACTION
1767 && order->target != NO_TARGET) {
1768 /* The target is already specified in the new format. */
1769
1770 /* The index_to_tile() call has no side-effects that we
1771 * would want also in NDEBUG builds. */
1772 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1773 return;
1774 }
1775
1776 if (!direction8_is_valid(order->dir)) {
1777 /* The target of the action is on the actor's tile. */
1778 tgt_tile = current_tile;
1779 } else {
1780 /* The target of the action is on a tile next to the actor. */
1781 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1782 }
1783
1784 if (order->order == ORDER_PERFORM_ACTION) {
1785 if (tgt_tile != NULL) {
1786 struct action *paction = action_by_number(order->action);
1787
1788 order->target = tgt_tile->index;
1789 /* Leave no traces. */
1790 order->dir = DIR8_ORIGIN;
1791
1793 /* The action moves the unit to the target tile (unless this is the
1794 * final order) */
1797 || i == act_unit->orders.length - 1);
1798 current_tile = tgt_tile;
1799 }
1800 } else {
1801 current_tile = NULL;
1802 }
1803 } else {
1804 current_tile = tgt_tile;
1805 }
1806 }
1807
1808 if (current_tile == NULL) {
1809 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1811 }
1812}
1813
1814/************************************************************************/
1818{
1819 players_iterate_alive(pplayer) {
1820 unit_list_iterate(pplayer->units, punit) {
1823 }
1826}
1827
1828/************************************************************************/
1833{
1834 /* Check status and return if not OK (sg_success FALSE). */
1835 sg_check_ret();
1836
1837 /* Action orders were new in 3.0 */
1838 if (format_class == SAVEGAME_3) {
1839 /* Only 3.0 savegames may have "Attack" action orders. */
1840 players_iterate_alive(pplayer) {
1841 unit_list_iterate(pplayer->units, punit) {
1842 int i;
1843
1844 if (!punit->has_orders) {
1845 continue;
1846 }
1847
1849 || punit->orders.list != NULL, continue);
1850
1851 for (i = 0; i < punit->orders.length; i++) {
1852 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1858 }
1859
1860 /* Production targeted actions were split from building targeted
1861 * actions in 3.1. The building sub target encoding changed. */
1863 && ((punit->orders.list[i].action
1865 || (punit->orders.list[i].action
1867 punit->orders.list[i].sub_target -= 1;
1868 }
1870 && (punit->orders.list[i].action
1872 && punit->orders.list[i].sub_target == -1) {
1875 }
1877 && (punit->orders.list[i].action
1879 && punit->orders.list[i].sub_target == -1) {
1882 }
1883 }
1886 }
1887
1888 /* Explicit server side agent was new in 3.1 */
1890
1891 /* Some activities should only be ordered in action orders. */
1892 players_iterate_alive(pplayer) {
1893 unit_list_iterate(pplayer->units, punit) {
1897
1898 /* Unit order action target isn't dir anymore */
1899 players_iterate_alive(pplayer) {
1900 unit_list_iterate(pplayer->units, punit) {
1904
1905 /* Backward compatibility: if we had any open-ended orders (pillage)
1906 * in the savegame, assign specific targets now */
1907 players_iterate_alive(pplayer) {
1908 unit_list_iterate(pplayer->units, punit) {
1910 &punit->activity,
1911 punit->action,
1915}
1916
1917/************************************************************************/
1925{
1926 int i;
1927 int count;
1928 int set_count;
1929 bool gamestart_valid = FALSE;
1930
1931 /* Check status and return if not OK (sg_success FALSE). */
1932 sg_check_ret();
1933
1934 log_debug("Upgrading data from savegame to version 3.2.0");
1935
1936 {
1937 const char *str = secfile_lookup_str_default(loading->file, NULL,
1938 "savefile.orig_version");
1939
1940 if (str == NULL) {
1941 /* Make sure CURRENTLY running version does not
1942 * end as orig_version when we resave. */
1943 if (format_class == SAVEGAME_3) {
1944 secfile_insert_str(loading->file, "old savegame3, or older",
1945 "savefile.orig_version");
1946 } else {
1948
1949 secfile_insert_str(loading->file, "savegame2, or older",
1950 "savefile.orig_version");
1951 }
1952 }
1953 }
1954
1955 {
1956 int action_count;
1957
1959 "savefile.action_size");
1960
1961 if (action_count > 0) {
1962 const char **modname;
1963 const char **savemod;
1964 int j;
1965 const char *dur_name = "Transport Deboard";
1966 const char *clean_name = "Clean";
1967
1968 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1969 "savefile.action_vector");
1970
1972
1973 for (j = 0; j < action_count; j++) {
1974 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1975 savemod[j] = dur_name;
1976 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1977 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1978 savemod[j] = clean_name;
1979 } else {
1980 savemod[j] = modname[j];
1981 }
1982 }
1983
1985 "savefile.action_vector");
1986
1987 free(savemod);
1988 }
1989 }
1990
1991 {
1992 int activities_count;
1993
1995 "savefile.activities_size");
1996
1997 if (activities_count > 0) {
1998 const char **modname;
1999 const char **savemod;
2000 int j;
2001 const char *clean_name = "Clean";
2002
2003 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2004 "savefile.activities_vector");
2005
2007
2008 for (j = 0; j < activities_count; j++) {
2009 if (!fc_strcasecmp("Pollution", modname[j])
2010 || !fc_strcasecmp("Fallout", modname[j])) {
2011 savemod[j] = clean_name;
2012 } else {
2013 savemod[j] = modname[j];
2014 }
2015 }
2016
2018 "savefile.activities_vector");
2019
2020 free(savemod);
2021 }
2022 }
2023
2024 /* Server setting migration. */
2025 {
2026 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2027 int alltemperate_idx = -1, singlepole_idx = -1;
2028 bool count_changed = FALSE;
2029
2032 "settings.gamestart_valid");
2033
2034 for (i = 0; i < set_count; i++) {
2035 const char *old_name
2036 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2037 const char *name;
2038
2039 if (!old_name) {
2040 continue;
2041 }
2042
2044
2045 if (fc_strcasecmp(old_name, name)) {
2046 /* Setting's name changed */
2047 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2048 }
2049
2050 if (!gamestart_valid) {
2051 /* Older savegames saved these values even when they were not valid.
2052 * Silence warnings caused by them. */
2053 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2054 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2055 }
2056
2057 if (!fc_strcasecmp("compresstype", name)) {
2058 const char *val = secfile_lookup_str(loading->file,
2059 "settings.set%d.value", i);
2060 if (!fc_strcasecmp(val, "BZIP2")) {
2061#ifdef FREECIV_HAVE_LIBZSTD
2062 secfile_replace_str(loading->file, "ZSTD",
2063 "settings.set%d.value", i);
2064#elif FREECIV_HAVE_LIBLZMA
2065 secfile_replace_str(loading->file, "XZ",
2066 "settings.set%d.value", i);
2067#elif FREECIV_HAVE_LIBZ
2068 secfile_replace_str(loading->file, "LIBZ",
2069 "settings.set%d.value", i);
2070#else
2071 secfile_replace_str(loading->file, "PLAIN",
2072 "settings.set%d.value", i);
2073#endif
2074 }
2075
2076 if (gamestart_valid) {
2077 val = secfile_lookup_str(loading->file,
2078 "settings.set%d.gamestart", i);
2079 if (!fc_strcasecmp(val, "BZIP2")) {
2080#ifdef FREECIV_HAVE_LIBZSTD
2081 secfile_replace_str(loading->file, "ZSTD",
2082 "settings.set%d.gamestart", i);
2083#elif FREECIV_HAVE_LIBLZMA
2084 secfile_replace_str(loading->file, "XZ",
2085 "settings.set%d.gamestart", i);
2086#elif FREECIV_HAVE_LIBZ
2087 secfile_replace_str(loading->file, "LIBZ",
2088 "settings.set%d.gamestart", i);
2089#else
2090 secfile_replace_str(loading->file, "PLAIN",
2091 "settings.set%d.gamestart", i);
2092#endif
2093 }
2094 }
2095 } else if (!fc_strcasecmp("topology", name)) {
2096 struct setting *pset = setting_by_name(name);
2097 struct sf_cb_data info = { pset, TRUE };
2098 int val;
2099
2100 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2102 "settings.set%d.value", i)) {
2103 char wrap[100];
2104 char buf[100];
2105
2106 if (val & TF_OLD_WRAPX) {
2107 if (val & TF_OLD_WRAPY) {
2108 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2109 } else {
2110 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2111 }
2112 } else if (val & TF_OLD_WRAPY) {
2113 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2114 } else {
2115 fc_strlcpy(wrap, "", sizeof(wrap));
2116 }
2117
2118 if (val & TF_ISO) {
2119 if (val & TF_HEX) {
2120 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2121 } else {
2122 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2123 }
2124 } else if (val & TF_HEX) {
2125 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2126 } else {
2128 }
2129
2130 setting_value_name(pset, FALSE, buf, sizeof(buf));
2132 "settings.set%d.value", i);
2133
2135 "wrap", "settings.set%d.name", set_count);
2137 wrap, "settings.set%d.value", set_count);
2138
2139 if (gamestart_valid) {
2140 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2142 "settings.set%d.gamestart", i)) {
2143 if (val & TF_OLD_WRAPX) {
2144 if (val & TF_OLD_WRAPY) {
2145 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2146 } else {
2147 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2148 }
2149 } else if (val & TF_OLD_WRAPY) {
2150 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2151 } else {
2152 fc_strlcpy(wrap, "", sizeof(wrap));
2153 }
2154
2155 if (val & TF_ISO) {
2156 if (val & TF_HEX) {
2157 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2158 } else {
2159 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2160 }
2161 } else if (val & TF_HEX) {
2162 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2163 } else {
2165 }
2166
2167 setting_value_name(pset, FALSE, buf, sizeof(buf));
2169 "settings.set%d.gamestart", i);
2170
2172 wrap, "settings.set%d.gamestart", set_count);
2173 }
2174 }
2175
2176 set_count++;
2178 }
2179 } else if (!fc_strcasecmp("alltemperate", name)) {
2181 } else if (!fc_strcasecmp("singlepole", name)) {
2182 singlepole_idx = i;
2183 }
2184 }
2185
2186 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2187 int north_latitude, south_latitude;
2188 int north_idx, south_idx;
2190
2191 if (alltemperate_idx < 0
2193 "settings.set%d.value",
2195 /* Infer what would've been the ruleset default */
2197 }
2198
2199 if (singlepole_idx < 0
2201 "settings.set%d.value",
2202 singlepole_idx)) {
2203 /* Infer what would've been the ruleset default */
2205 }
2206
2207 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2208 * changes, that'll have to be handled in later migrations anyway */
2209 north_latitude = alltemperate ? 500 : 1000;
2210 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2211
2212 /* Replace alltemperate with northlatitude, and singlepole with
2213 * southlatitude. If only one of the two was given, add the other
2214 * at the end. */
2217
2218 secfile_replace_str(loading->file, "northlatitude",
2219 "settings.set%d.name", north_idx);
2220 secfile_replace_int(loading->file, north_latitude,
2221 "settings.set%d.value", north_idx);
2222
2223 secfile_replace_str(loading->file, "southlatitude",
2224 "settings.set%d.name", south_idx);
2225 secfile_replace_int(loading->file, south_latitude,
2226 "settings.set%d.value", south_idx);
2227
2228 if (gamestart_valid) {
2229 if (alltemperate_idx < 0
2231 "settings.set%d.gamestart",
2233 alltemperate =
2235 }
2236
2237 if (singlepole_idx < 0
2239 "settings.set%d.gamestart",
2240 singlepole_idx)) {
2242 }
2243
2244 north_latitude = alltemperate ? 500 : 1000;
2245 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2246
2247 secfile_replace_int(loading->file, north_latitude,
2248 "settings.set%d.gamestart", north_idx);
2249 secfile_replace_int(loading->file, south_latitude,
2250 "settings.set%d.gamestart", south_idx);
2251 }
2252
2253 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2254 /* only one was given and replaced ~> we added one new entry */
2255 set_count++;
2257 }
2258 }
2259
2260 if (count_changed) {
2262 "settings.set_count");
2263 }
2264 }
2265 }
2266
2267 {
2268 /* Turn old AI level field to a setting. */
2269 const char *level;
2270 enum ai_level lvl;
2271
2272 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2273 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2274 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2276 } else {
2278 }
2279
2280 if (!ai_level_is_valid(lvl)) {
2281 log_sg("Invalid AI level \"%s\". "
2282 "Changed to \"%s\".", level,
2285 }
2286
2287 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2288 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2289
2290 if (gamestart_valid) {
2291 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2292 set_count);
2293 }
2294
2295 set_count++;
2296 secfile_replace_int(loading->file, set_count, "settings.set_count");
2297 }
2298
2299 if (format_class != SAVEGAME_2) {
2300 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2301 /* Older savegames had a bug that got_tech_multi was not saved. */
2302 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2303 for (i = 0; i < count; i++) {
2304 bool got_tech = FALSE;
2305 int bulbs = 0;
2306 bool got_tech_multi
2308 "research.r%d.got_tech_multi", i);
2309
2311 "research.r%d.got_tech", i)
2312 && secfile_lookup_int(loading->file, &bulbs,
2313 "research.r%d.bulbs", i)) {
2315 got_tech || got_tech_multi ? bulbs : 0,
2316 "research.r%d.free_bulbs", i);
2317 }
2318 }
2319 }
2320
2321 /* Older savegames unnecessarily saved diplstate type order.
2322 * Silence "unused entry" warnings about those. */
2323 {
2325 "savefile.diplstate_type_size");
2326
2327 for (i = 0; i < dscount; i++) {
2329 "savefile.diplstate_type_vector,%d", i);
2330 }
2331 }
2332
2333 /* Add wl_max_length entries for players */
2334 {
2335 player_slots_iterate(pslot) {
2336 int plrno = player_slot_index(pslot);
2337 int ncities;
2338 int cnro;
2339 size_t wlist_max_length = 0;
2340 bool first_city;
2341
2342 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2343 continue;
2344 }
2345
2347 "player%d.got_first_city",
2348 plrno);
2349 if (first_city) {
2350 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2351 int flagcount = 0;
2352 const char **flags_sg;
2353 size_t nval;
2354
2356
2358 "player%d.flags", plrno);
2359
2360 for (i = 0; i < nval; i++) {
2363
2365 }
2366
2368 "player%d.flags", plrno);
2369
2371 }
2372
2374 "player%d.ncities", plrno);
2375
2376 for (cnro = 0; cnro < ncities; cnro++) {
2378 "player%d.c%d.wl_length",
2379 plrno, cnro);
2380
2382
2383 if (format_class == SAVEGAME_3) {
2385 "player%d.c%d.original",
2386 plrno, cnro) != plrno) {
2388 "player%d.c%d.acquire_t",
2389 plrno, cnro);
2390 } else {
2392 "player%d.c%d.acquire_t",
2393 plrno, cnro);
2394 }
2395
2397 "player%d.c%d.wlcb",
2398 plrno, cnro);
2399 }
2400 }
2401
2403 "player%d.wl_max_length", plrno);
2404
2405 if (format_class == SAVEGAME_3) {
2406 int nunits;
2407 int unro;
2408 size_t olist_max_length = 0;
2409
2411 "player%d.nunits", plrno);
2412
2413 for (unro = 0; unro < nunits; unro++) {
2415 "player%d.u%d.orders_length",
2416 plrno, unro);
2417
2419 }
2420
2422 "player%d.orders_max_length", plrno);
2423
2425 "player%d.routes_max_length", plrno);
2426 }
2427
2429 }
2430}
2431
2432/************************************************************************/
2440{
2441 /* Check status and return if not OK (sg_success != TRUE). */
2442 sg_check_ret();
2443
2444 log_debug("Upgrading data from savegame to version 3.3.0");
2445
2446 /* World Peace has never started in the old savegame. */
2447 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2448
2449 if (format_class != SAVEGAME_2) {
2450 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2451
2452 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2453 }
2454
2455 /* Last turn change time as a float, not integer multiplied by 100 */
2456 {
2457 float tct = secfile_lookup_int_default(loading->file, 0,
2458 "game.last_turn_change_time") / 100.0;
2459
2460 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2461 }
2462
2463 {
2464 int ssa_count;
2465
2467 "savefile.server_side_agent_size");
2468 if (ssa_count > 0) {
2469 const char **modname;
2470 const char **savemod;
2471 int j;
2472 const char *aw_name = "AutoWorker";
2473
2474 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2475 "savefile.server_side_agent_list");
2476
2477 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2478
2479 for (j = 0; j < ssa_count; j++) {
2480 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2481 savemod[j] = aw_name;
2482 } else {
2483 savemod[j] = modname[j];
2484 }
2485 }
2486
2488 "savefile.server_side_agent_list");
2489
2490 free(savemod);
2491 }
2492 }
2493
2494 {
2495 int action_count;
2496
2498 "savefile.action_size");
2499
2500 if (action_count > 0) {
2501 const char **modname;
2502 const char **savemod;
2503 int j;
2504 const char *cc1_name = "Conquer City Shrink";
2505 const char *cc2_name = "Conquer City Shrink 2";
2506 const char *cc3_name = "Conquer City Shrink 3";
2507 const char *cc4_name = "Conquer City Shrink 4";
2508
2509 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2510 "savefile.action_vector");
2511
2513
2514 for (j = 0; j < action_count; j++) {
2515 if (!fc_strcasecmp("Conquer City", modname[j])) {
2516 savemod[j] = cc1_name;
2517 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
2518 savemod[j] = cc2_name;
2519 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
2520 savemod[j] = cc3_name;
2521 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
2522 savemod[j] = cc4_name;
2523 } else {
2524 savemod[j] = modname[j];
2525 }
2526 }
2527
2529 "savefile.action_vector");
2530
2531 free(savemod);
2532 }
2533 }
2534
2535 /* Add actions for unit activities */
2536 if (format_class == SAVEGAME_3) {
2537 loading->activities.size
2539 "savefile.activities_size");
2540 if (loading->activities.size) {
2541 loading->activities.order
2542 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2543 "savefile.activities_vector");
2544 sg_failure_ret(loading->activities.size != 0,
2545 "Failed to load activity order: %s",
2546 secfile_error());
2547 }
2548
2549 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2550 "savefile.action_size");
2551
2552 sg_failure_ret(loading->action.size > 0,
2553 "Failed to load action order: %s",
2554 secfile_error());
2555
2556 if (loading->action.size) {
2557 const char **modname;
2558 int j;
2559
2560 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2561 "savefile.action_vector");
2562
2563 loading->action.order = fc_calloc(loading->action.size,
2564 sizeof(*loading->action.order));
2565
2566 for (j = 0; j < loading->action.size; j++) {
2568
2569 if (real_action != nullptr) {
2570 loading->action.order[j] = real_action->id;
2571 } else {
2572 log_sg("Unknown action \'%s\'", modname[j]);
2573 loading->action.order[j] = ACTION_NONE;
2574 }
2575 }
2576
2577 free(modname);
2578 }
2579
2580 player_slots_iterate(pslot) {
2581 int plrno = player_slot_index(pslot);
2582 int nunits;
2583 int unro;
2584
2585 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2586 continue;
2587 }
2588
2590 "player%d.nunits", plrno);
2591
2592 for (unro = 0; unro < nunits; unro++) {
2593 int ei;
2594 int i;
2595 enum unit_activity activity;
2596 enum gen_action act;
2597
2599 "player%d.u%d.activity", plrno, unro);
2600
2601 if (ei >= 0 && ei < loading->activities.size) {
2602 bool found = FALSE;
2603
2604 activity = unit_activity_by_name(loading->activities.order[ei],
2606
2607 act = activity_default_action(activity);
2608
2609 for (i = 0; i < loading->action.size; i++) {
2610 if (act == loading->action.order[i]) {
2611 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2612 plrno, unro);
2613 found = TRUE;
2614 break;
2615 }
2616 }
2617
2618 if (!found) {
2619 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
2620 plrno, unro);
2621 }
2622 }
2623 }
2625 }
2626
2627 /* Researches */
2628 {
2629 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2630 int i;
2631
2632 for (i = 0; i < count; i++) {
2633 /* It's ok for old savegames to have these entries. */
2634 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
2635 }
2636 }
2637
2638 player_slots_iterate(pslot) {
2639 int plrno = player_slot_index(pslot);
2640 int ncities;
2641 int cnro;
2642
2643 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2644 continue;
2645 }
2646
2648 "player%d.dc_total", plrno);
2649
2650 for (cnro = 0; cnro < ncities; cnro++) {
2651 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
2652 plrno, cnro);
2653 }
2655}
2656
2657/************************************************************************/
2662{
2663 /* Check status and return if not OK (sg_success FALSE). */
2664 sg_check_ret();
2665
2666 /* Capital information was not saved in older savegames,
2667 * so we have no capital setup at all at the moment.
2668 * Best we can do is to do recalculation now. It might be
2669 * a bit off compared to the situation before the game was saved,
2670 * but definitely better than not setting capitals at all. */
2671 players_iterate_alive(pplayer) {
2672 update_capital(pplayer);
2674}
2675
2676/************************************************************************/
2684{
2685 /* Check status and return if not OK (sg_success != TRUE). */
2686 sg_check_ret();
2687
2688 log_debug("Upgrading data from savegame to version 3.4.0");
2689}
2690
2691/************************************************************************/
2695#ifdef FREECIV_DEV_SAVE_COMPAT
2696static void compat_load_dev(struct loaddata *loading)
2697{
2698 int game_version;
2699
2700 /* Check status and return if not OK (sg_success FALSE). */
2701 sg_check_ret();
2702
2703 log_verbose("Upgrading data between development revisions");
2704
2705 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2706 "No save version found");
2707
2708#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
2709
2710 if (game_version < 3029100) {
2711 /* Before version number bump to 3.2.91, September 2023 */
2712
2713 {
2714 const char *str = secfile_lookup_str_default(loading->file, NULL,
2715 "savefile.orig_version");
2716
2717 if (str == NULL) {
2718 /* Make sure CURRENTLY running version does not
2719 * end as orig_version when we resave. */
2720 secfile_insert_str(loading->file, "old savegame3, or older",
2721 "savefile.orig_version");
2722 }
2723 }
2724
2725 /* Add acquire_t entries for cities */
2726 {
2727 player_slots_iterate(pslot) {
2728 int plrno = player_slot_index(pslot);
2729 int ncities;
2730 int cnro;
2731 bool first_city;
2732
2733 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2734 continue;
2735 }
2736
2738 "player%d.got_first_city",
2739 plrno);
2740 if (first_city) {
2741 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2742 int flagcount = 0;
2743 const char **flags_sg;
2744 size_t nval;
2745 int i;
2746
2748
2750 "player%d.flags", plrno);
2751
2752 for (i = 0; i < nval; i++) {
2755
2757 }
2758
2760 "player%d.flags", plrno);
2761
2763 }
2764
2766 "player%d.ncities", plrno);
2767
2768 for (cnro = 0; cnro < ncities; cnro++) {
2769 if (secfile_entry_lookup(loading->file,
2770 "player%d.c%d.acquire_t",
2771 plrno, cnro) == NULL) {
2773 "player%d.c%d.original",
2774 plrno, cnro) != plrno) {
2776 "player%d.c%d.acquire_t",
2777 plrno, cnro);
2778 } else {
2780 "player%d.c%d.acquire_t",
2781 plrno, cnro);
2782 }
2783 }
2784 if (secfile_entry_lookup(loading->file,
2785 "player%d.c%d.wlcb",
2786 plrno, cnro) == NULL) {
2788 "player%d.c%d.wlcb",
2789 plrno, cnro);
2790 }
2791 }
2793 }
2794
2795 /* Add orders_max_length entries for players */
2796 {
2797 player_slots_iterate(pslot) {
2798 int plrno = player_slot_index(pslot);
2799
2800 if (secfile_section_lookup(loading->file, "player%d", plrno) != NULL
2802 "player%d.orders_max_length", plrno)
2803 == NULL) {
2804 size_t nunits;
2805 int unro;
2806 size_t olist_max_length = 0;
2807
2809 "player%d.nunits", plrno);
2810
2811 for (unro = 0; unro < nunits; unro++) {
2812 int ol_length
2814 "player%d.u%d.orders_length",
2815 plrno, unro);
2816
2818 }
2819
2821 "player%d.orders_max_length", plrno);
2822 }
2824 }
2825
2826 {
2827 int action_count;
2828
2830 "savefile.action_size");
2831
2832 if (action_count > 0) {
2833 const char **modname;
2834 const char **savemod;
2835 int j;
2836 const char *clean_name = "Clean";
2837
2838 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2839 "savefile.action_vector");
2840
2842
2843 for (j = 0; j < action_count; j++) {
2844 if (!fc_strcasecmp("Clean Pollution", modname[j])
2845 || !fc_strcasecmp("Clean Fallout", modname[j])) {
2846 savemod[j] = clean_name;
2847 } else {
2848 savemod[j] = modname[j];
2849 }
2850 }
2851
2853 "savefile.action_vector");
2854
2855 free(savemod);
2856 }
2857 }
2858
2859 {
2860 int activities_count;
2861
2863 "savefile.activities_size");
2864
2865 if (activities_count > 0) {
2866 const char **modname;
2867 const char **savemod;
2868 int j;
2869 const char *clean_name = "Clean";
2870
2871 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2872 "savefile.activities_vector");
2873
2875
2876 for (j = 0; j < activities_count; j++) {
2877 if (!fc_strcasecmp("Pollution", modname[j])
2878 || !fc_strcasecmp("Fallout", modname[j])) {
2879 savemod[j] = clean_name;
2880 } else {
2881 savemod[j] = modname[j];
2882 }
2883 }
2884
2886 "savefile.activities_vector");
2887
2888 free(savemod);
2889 }
2890 }
2891
2892 /* Server setting migration. */
2893 {
2894 int set_count;
2895
2896 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2897 bool gamestart_valid = FALSE;
2898
2901 "settings.gamestart_valid");
2902
2903 if (!gamestart_valid) {
2904 int i;
2905
2906 /* Older savegames saved gamestart values even when they were not valid.
2907 * Silence warnings caused by them. */
2908 for (i = 0; i < set_count; i++) {
2909 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2910 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2911 }
2912 }
2913 }
2914 }
2915
2916 {
2917 int ssa_count;
2918
2920 "savefile.server_side_agent_size");
2921 if (ssa_count > 0) {
2922 const char **modname;
2923 const char **savemod;
2924 int j;
2925 const char *aw_name = "AutoWorker";
2926
2927 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2928 "savefile.server_side_agent_list");
2929
2930 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2931
2932 for (j = 0; j < ssa_count; j++) {
2933 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2934 savemod[j] = aw_name;
2935 } else {
2936 savemod[j] = modname[j];
2937 }
2938 }
2939
2941 "savefile.server_side_agent_list");
2942
2943 free(savemod);
2944 }
2945 }
2946
2947 } /* Version < 3.2.91 */
2948
2949 if (game_version < 3029200) {
2950 /* Before version number bump to 3.2.92, June 2024 */
2951
2952 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2953
2954 /* World Peace has never started in the old savegame. */
2955 game.info.turn
2956 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2959 "game.world_peace_start");
2961 "game.world_peace_start");
2962
2963 /* Last turn change time as a float, not integer multiplied by 100 */
2964 {
2965 float tct = secfile_lookup_int_default(loading->file, 0,
2966 "game.last_turn_change_time") / 100.0;
2967
2968 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2969 }
2970
2971 /* Add actions for unit activities */
2972 loading->activities.size
2974 "savefile.activities_size");
2975 if (loading->activities.size) {
2976 loading->activities.order
2977 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2978 "savefile.activities_vector");
2979 sg_failure_ret(loading->activities.size != 0,
2980 "Failed to load activity order: %s",
2981 secfile_error());
2982 }
2983
2984 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2985 "savefile.action_size");
2986
2987 sg_failure_ret(loading->action.size > 0,
2988 "Failed to load action order: %s",
2989 secfile_error());
2990
2991 if (loading->action.size) {
2992 const char **modname;
2993 int j;
2994
2995 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2996 "savefile.action_vector");
2997
2998 loading->action.order = fc_calloc(loading->action.size,
2999 sizeof(*loading->action.order));
3000
3001 for (j = 0; j < loading->action.size; j++) {
3003
3004 if (real_action) {
3005 loading->action.order[j] = real_action->id;
3006 } else {
3007 log_sg("Unknown action \'%s\'", modname[j]);
3008 loading->action.order[j] = ACTION_NONE;
3009 }
3010 }
3011
3012 free(modname);
3013 }
3014
3015 player_slots_iterate(pslot) {
3016 int plrno = player_slot_index(pslot);
3017 int nunits;
3018 int unro;
3019
3020 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3021 continue;
3022 }
3023
3025 "player%d.nunits", plrno);
3026
3027 for (unro = 0; unro < nunits; unro++) {
3028 int ei;
3029 int i;
3030 enum unit_activity activity;
3031 enum gen_action act;
3032
3034 "player%d.u%d.activity", plrno, unro);
3035
3036 if (ei >= 0 && ei < loading->activities.size) {
3037 bool found = FALSE;
3038
3039 activity = unit_activity_by_name(loading->activities.order[ei],
3041 act = activity_default_action(activity);
3042
3043 for (i = 0; i < loading->action.size; i++) {
3044 if (act == loading->action.order[i]) {
3045 secfile_insert_int(loading->file, i, "player%d.u%d.action",
3046 plrno, unro);
3047 found = TRUE;
3048 break;
3049 }
3050 }
3051
3052 if (!found) {
3053 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
3054 plrno, unro);
3055 }
3056 }
3057 }
3059
3060 /* Researches */
3061 {
3062 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
3063 int i;
3064
3065 for (i = 0; i < count; i++) {
3066 /* It's ok for old savegames to have these entries. */
3067 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
3068 }
3069 }
3070
3071 } /* Version < 3.2.92 */
3072
3073 if (game_version < 3029300) {
3074 /* Before version number bump to 3.2.93 */
3075
3076 {
3077 int action_count;
3078
3080 "savefile.action_size");
3081
3082 if (action_count > 0) {
3083 const char **modname;
3084 const char **savemod;
3085 int j;
3086 const char *cc1_name = "Conquer City Shrink";
3087 const char *cc2_name = "Conquer City Shrink 2";
3088 const char *cc3_name = "Conquer City Shrink 3";
3089 const char *cc4_name = "Conquer City Shrink 4";
3090
3091 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3092 "savefile.action_vector");
3093
3095
3096 for (j = 0; j < action_count; j++) {
3097 if (!fc_strcasecmp("Conquer City", modname[j])) {
3098 savemod[j] = cc1_name;
3099 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
3100 savemod[j] = cc2_name;
3101 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
3102 savemod[j] = cc3_name;
3103 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
3104 savemod[j] = cc4_name;
3105 } else {
3106 savemod[j] = modname[j];
3107 }
3108 }
3109
3111 "savefile.action_vector");
3112
3113 free(savemod);
3114 }
3115 }
3116
3117 player_slots_iterate(pslot) {
3118 int plrno = player_slot_index(pslot);
3119 int ncities;
3120 int cnro;
3121
3122 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3123 continue;
3124 }
3125
3127 "player%d.dc_total", plrno);
3128
3129 for (cnro = 0; cnro < ncities; cnro++) {
3130 if (!secfile_entry_lookup(loading->file, "player%d.dc%d.original",
3131 plrno, cnro)) {
3132 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
3133 plrno, cnro);
3134 }
3135 }
3137 } /* Version < 3.2.93 */
3138
3139#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3140
3141#ifdef FREECIV_DEV_SAVE_COMPAT_3_4
3142
3143 if (game_version < 3039100) {
3144 /* Before version number bump to 3.3.91 */
3145
3146 } /* Version < 3.3.91 */
3147
3148#endif /* FREECIV_DEV_SAVE_COMPAT_3_4 */
3149}
3150
3151/************************************************************************/
3155static void compat_post_load_dev(struct loaddata *loading)
3156{
3157 int game_version;
3158
3159 /* Check status and return if not OK (sg_success FALSE). */
3160 sg_check_ret();
3161
3162 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
3163 game_version = 2060000;
3164 }
3165
3166#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
3167
3168 if (game_version < 3029100) {
3169 /* Before version number bump to 3.2.91 */
3170
3171 } /* Version < 3.2.91 */
3172
3173#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3174}
3175#endif /* FREECIV_DEV_SAVE_COMPAT */
3176
3177/************************************************************************/
3180enum ai_level ai_level_convert(int old_level)
3181{
3182 switch (old_level) {
3183 case 1:
3184 return AI_LEVEL_AWAY;
3185 case 2:
3186 return AI_LEVEL_NOVICE;
3187 case 3:
3188 return AI_LEVEL_EASY;
3189 case 5:
3190 return AI_LEVEL_NORMAL;
3191 case 7:
3192 return AI_LEVEL_HARD;
3193 case 8:
3194 return AI_LEVEL_CHEATING;
3195 case 10:
3196#ifdef FREECIV_DEBUG
3197 return AI_LEVEL_EXPERIMENTAL;
3198#else /* FREECIV_DEBUG */
3199 return AI_LEVEL_HARD;
3200#endif /* FREECIV_DEBUG */
3201 }
3202
3203 return ai_level_invalid();
3204}
3205
3206/************************************************************************/
3209enum barbarian_type barb_type_convert(int old_type)
3210{
3211 switch (old_type) {
3212 case 0:
3213 return NOT_A_BARBARIAN;
3214 case 1:
3215 return LAND_BARBARIAN;
3216 case 2:
3217 return SEA_BARBARIAN;
3218 }
3219
3220 return barbarian_type_invalid();
3221}
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:76
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:214
#define EC_SPECIAL
Definition fc_types.h:807
revolen_type
Definition fc_types.h:976
@ REVOLEN_RANDOM
Definition fc_types.h:978
@ REVOLEN_RANDQUICK
Definition fc_types.h:980
@ REVOLEN_FIXED
Definition fc_types.h:977
@ REVOLEN_QUICKENING
Definition fc_types.h:979
#define DIR8_ORIGIN
Definition fc_types.h:315
#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:132
int len
Definition packhand.c:128
int player_slot_count(void)
Definition player.c:420
int player_slot_index(const struct player_slot *pslot)
Definition player.c:428
#define ANON_USER_NAME
Definition player.h:48
#define player_slots_iterate(_pslot)
Definition player.h:528
#define players_iterate_alive_end
Definition player.h:552
#define player_slots_iterate_end
Definition player.h:532
#define players_iterate_alive(_pplayer)
Definition player.h:547
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:334
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:571
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:352
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:714
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:695
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:588
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: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: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: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
enum unit_activity activity
Definition unit.h:159
enum gen_action action
Definition unit.h:160
struct unit::@83 orders
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: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:128
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:250
#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:1833
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:2964
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: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, enum gen_action action, struct extra_type **target)
Definition unittools.c:1083
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