Freeciv-3.2
Loading...
Searching...
No Matches
savecompat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "capability.h"
20#include "log.h"
21
22/* common */
23#include "map.h"
24#include "specialist.h"
25
26/* server */
27#include "aiiface.h"
28#include "setcompat.h"
29#include "settings.h"
30#include "unittools.h"
31
32#include "savecompat.h"
33
35
36static char *special_names[] =
37 {
38 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
39 "Fallout", NULL
40 };
41
42/*
43 For each savefile format after 2.3.0, compatibility functions are defined
44 which translate secfile structures from previous version to that version;
45 all necessary compat functions are called in order to
46 translate between the file and current version. See sg_load_compat().
47
48 The integer version ID should be increased every time the format is changed.
49 If the change is not backwards compatible, please state the changes in the
50 following list and update the compat functions at the end of this file.
51
52 - what was added / removed
53 - when was it added / removed (date and version)
54 - when can additional capability checks be set to mandatory (version)
55 - which compatibility checks are needed and till when (version)
56
57 freeciv | what | date | id
58 --------+------------------------------------------------+------------+----
59 current | (mapped to current savegame format) | ----/--/-- | 0
60 | first version (svn17538) | 2010/07/05 | -
61 2.3.0 | 2.3.0 release | 2010/11/?? | 3
62 2.4.0 | 2.4.0 release | 201./../.. | 10
63 | * player ai type | |
64 | * delegation | |
65 | * citizens | |
66 | * save player color | |
67 | * "known" info format change | |
68 2.5.0 | 2.5.0 release | 201./../.. | 20
69 2.6.0 | 2.6.0 release | 201./../.. | 30
70 3.0.0 | 3.0.0 release | 201./../.. | 40
71 3.1.0 | 3.1.0 release | 201./../.. | 50
72 3.2.0 | 3.2.0 release (development) | 202./../.. | 60
73 | | |
74*/
75
82static void compat_post_load_030100(struct loaddata *loading,
84
85#ifdef FREECIV_DEV_SAVE_COMPAT
86static void compat_load_dev(struct loaddata *loading);
87static void compat_post_load_dev(struct loaddata *loading);
88#endif /* FREECIV_DEV_SAVE_COMPAT */
89
91
97
98/* The struct below contains the information about the savegame versions. It
99 * is identified by the version number (first element), which should be
100 * steadily increasing. It is saved as 'savefile.version'. The support
101 * string (first element of 'name') is not saved in the savegame; it is
102 * saved in settings files (so, once assigned, cannot be changed). The
103 * 'pretty' string (second element of 'name') can be changed if necessary
104 * For changes in the development version, edit the definitions above and
105 * add the needed code to load the old version below. Thus, old
106 * savegames can still be loaded while the main definition
107 * represents the current state of the art. */
108/* While developing freeciv 3.2.0, add the compatibility functions to
109 * - compat_load_030200 to load old savegame. */
110static struct compatibility compat[] = {
111 /* dummy; equal to the current version (last element) */
112 { 0, NULL, NULL },
113 /* version 1 and 2 is not used */
114 /* version 3: first savegame2 format, so no compat functions for translation
115 * from previous format */
116 { 3, NULL, NULL },
117 /* version 4 to 9 are reserved for possible changes in 2.3.x */
118 { 10, compat_load_020400, NULL },
119 /* version 11 to 19 are reserved for possible changes in 2.4.x */
120 { 20, compat_load_020500, NULL },
121 /* version 21 to 29 are reserved for possible changes in 2.5.x */
122 { 30, compat_load_020600, NULL },
123 /* version 31 to 39 are reserved for possible changes in 2.6.x */
124 { 40, compat_load_030000, NULL },
125 /* version 41 to 49 are reserved for possible changes in 3.0.x */
127 /* version 51 to 59 are reserved for possible changes in 3.1.x */
128 { 60, compat_load_030200, NULL },
129 /* Current savefile version is listed above this line; it corresponds to
130 the definitions in this file. */
131};
132
133static const int compat_num = ARRAY_SIZE(compat);
134#define compat_current (compat_num - 1)
135
136/************************************************************************/
144{
145 int i;
146
147 /* Check status and return if not OK (sg_success FALSE). */
148 sg_check_ret();
149
150 loading->version = secfile_lookup_int_default(loading->file, -1,
151 "savefile.version");
152#ifdef FREECIV_DEBUG
153 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
154 loading->version);
155 if (loading->version > compat[compat_current].version) {
156 /* Debug build can (TRY TO!) load newer versions but ... */
157 log_error("Savegame version newer than this build found (%d > %d). "
158 "Trying to load the game nevertheless ...", loading->version,
160 }
161#else /* FREECIV_DEBUG */
162 sg_failure_ret(0 < loading->version
163 && loading->version <= compat[compat_current].version,
164 "Unknown savefile format version (%d).", loading->version);
165#endif /* FREECIV_DEBUG */
166
167
168 for (i = 0; i < compat_num; i++) {
169 if (loading->version < compat[i].version && compat[i].load != NULL) {
170 log_normal(_("Run compatibility function for version: <%d "
171 "(save file: %d; server: %d)."), compat[i].version,
174 }
175 }
176
177#ifdef FREECIV_DEV_SAVE_COMPAT
178 if (loading->version == compat[compat_current].version) {
180 }
181#endif /* FREECIV_DEV_SAVE_COMPAT */
182}
183
184/************************************************************************/
196{
197 int i;
198
199 /* Check status and return if not OK (sg_success FALSE). */
200 sg_check_ret();
201
202 for (i = 0; i < compat_num; i++) {
203 if (loading->version < compat[i].version
204 && compat[i].post_load != NULL) {
205 log_normal(_("Run post load compatibility function for version: <%d "
206 "(save file: %d; server: %d)."), compat[i].version,
209 }
210 }
211
212#ifdef FREECIV_DEV_SAVE_COMPAT
213 if (loading->version == compat[compat_current].version) {
215 }
216#endif /* FREECIV_DEV_SAVE_COMPAT */
217}
218
219/************************************************************************/
223{
225}
226
227/************************************************************************/
232char bin2ascii_hex(int value, int halfbyte_wanted)
233{
234 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
235}
236
237/************************************************************************/
245{
246 const char *pch;
247
248 if (ch == ' ') {
249 /* Sane value. It is unknow if there are savegames out there which
250 * need this fix. Savegame.c doesn't write such savegames
251 * (anymore) since the inclusion into CVS (2000-08-25). */
252 return 0;
253 }
254
256
257 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
258 "Unknown hex value: '%c' %d", ch, ch);
259 return (pch - hex_chars) << (halfbyte * 4);
260}
261
262static const char num_chars[] =
263 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
264
265/************************************************************************/
268int char2num(char ch)
269{
270 const char *pch;
271
273
275 "Unknown ascii value for num: '%c' %d", ch, ch);
276
277 return pch - num_chars;
278}
279
280/************************************************************************/
284{
285 int i;
286
287 for (i = 0; special_names[i] != NULL; i++) {
288 if (!strcmp(name, special_names[i])) {
289 return i;
290 }
291 }
292
293 return S_LAST;
294}
295
296/************************************************************************/
300{
301 fc_assert(type >= 0 && type < S_LAST);
302
303 return special_names[type];
304}
305
306/************************************************************************/
310{
312
315 }
316
317 return NULL;
318}
319
320/************************************************************************/
323struct extra_type *resource_by_identifier(const char identifier)
324{
326 if (presource->data.resource->id_old_save == identifier) {
327 return presource;
328 }
330
331 return NULL;
332}
333
334/* =======================================================================
335 * Compatibility functions for loading a game.
336 * ======================================================================= */
337
338/************************************************************************/
343{
344 /* Check status and return if not OK (sg_success FALSE). */
345 sg_check_ret();
346
347 log_debug("Upgrading data from savegame to version 2.4.0");
348
349 /* Add the default player AI. */
350 player_slots_iterate(pslot) {
351 int ncities, i, plrno = player_slot_index(pslot);
352
353 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
354 continue;
355 }
356
358 "player%d.ai_type", player_slot_index(pslot));
359
360 /* Create dummy citizens informations. We do not know if citizens are
361 * activated due to the fact that this information
362 * (game.info.citizen_nationality) is not available, but adding the
363 * information does no harm. */
365 "player%d.ncities", plrno);
366 if (ncities > 0) {
367 for (i = 0; i < ncities; i++) {
369 "player%d.c%d.size", plrno, i);
370 if (size > 0) {
372 "player%d.c%d.citizen%d", plrno, i, plrno);
373 }
374 }
375 }
376
378
379 /* Player colors are assigned at the end of player loading, as this
380 * needs information not available here. */
381
382 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
383 * workaround in later 2.3.x); see gna bug #19029.
384 * (The structure of this code is odd as it avoids relying on knowledge of
385 * xsize/ysize, which haven't been extracted from the savefile yet.) */
386 {
387 if (has_capability("knownv2",
388 secfile_lookup_str(loading->file, "savefile.options"))) {
389 /* This savefile contains known information in a sane format.
390 * Just move any entries to where 2.4.x+ expect to find them. */
391 struct section *map = secfile_section_by_name(loading->file, "map");
392
393 if (map != NULL) {
395 const char *name = entry_name(pentry);
396
397 if (!fc_strncmp(name, "kvb", 3)) {
398 /* Rename the "kvb..." entry to "k..." */
399 char *name2 = fc_strdup(name), *newname = name2 + 2;
400
401 *newname = 'k';
402 /* Savefile probably contains existing "k" entries, which are bogus
403 * so we trash them. */
404 secfile_entry_delete(loading->file, "map.%s", newname);
406 FC_FREE(name2);
407 }
409 }
410 /* Could remove "knownv2" from savefile.options, but it's doing
411 * no harm there. */
412 } else {
413 /* This savefile only contains known information in the broken
414 * format. Try to recover it to a sane format. */
415 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
416 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
417 const int maxslots = 128, maxmapsize = 512;
418 const int lines = maxslots/32;
419 int xsize = 0, y, l, j, x;
420 unsigned int known_row_old[lines * maxmapsize],
422 /* Process a map row at a time */
423 for (y = 0; y < maxmapsize; y++) {
424 /* Look for broken info to convert */
425 bool found = FALSE;
427 for (l = 0; l < lines; l++) {
428 for (j = 0; j < 8; j++) {
429 const char *s =
431 "map.k%02d_%04d", l * 8 + j, y);
432 if (s) {
433 found = TRUE;
434 if (xsize == 0) {
435 xsize = strlen(s);
436 }
437 sg_failure_ret(xsize == strlen(s),
438 "Inconsistent xsize in map.k%02d_%04d",
439 l * 8 + j, y);
440 for (x = 0; x < xsize; x++) {
441 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
442 }
443 }
444 }
445 }
446 if (found) {
447 /* At least one entry found for this row. Let's hope they were
448 * all there. */
449 /* Attempt to munge into sane format */
450 int p;
451 memset(known_row, 0, sizeof(known_row));
452 /* Iterate over possible player slots */
453 for (p = 0; p < maxslots; p++) {
454 l = p / 32;
455 for (x = 0; x < xsize; x++) {
456 /* This test causes bit-shifts of >=32 (undefined behaviour), but
457 * on common platforms, information happens not to be lost, just
458 * oddly arranged. */
459 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
460 known_row[l * xsize + x] |= (1u << (p - l * 32));
461 }
462 }
463 }
464 /* Save sane format back to memory representation of secfile for
465 * real loading code to pick up */
466 for (l = 0; l < lines; l++) {
467 for (j = 0; j < 8; j++) {
468 /* Save info for all slots (not just used ones). It's only
469 * memory, after all. */
470 char row[xsize+1];
471 for (x = 0; x < xsize; x++) {
472 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
473 }
474 row[xsize] = '\0';
476 "map.k%02d_%04d", l * 8 + j, y);
477 }
478 }
479 }
480 }
481 }
482 }
483
484 /* Server setting migration. */
485 {
486 int set_count;
487
488 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
489 int i, new_opt = set_count;
490 bool gamestart_valid
492 "settings.gamestart_valid");
493
494 for (i = 0; i < set_count; i++) {
495 const char *name
496 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
497
498 if (!name) {
499 continue;
500 }
501
502 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
503 * This is now controlled by the "autosaves" setting. */
504 if (!fc_strcasecmp("saveturns", name)) {
505 /* XXX: hardcodes details from GAME_AUTOSAVES_DEFAULT
506 * and settings.c:autosaves_name() (but these defaults reflect
507 * 2.3's behaviour). */
508 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
509 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
510 int nturns;
511
513 "settings.set%d.value", i)) {
514 if (nturns == 0) {
515 /* Invent a new "autosaves" setting */
517 "settings.set%d.value", new_opt);
518 /* Pick something valid for saveturns */
520 "settings.set%d.value", i);
521 } else {
523 "settings.set%d.value", new_opt);
524 }
525 } else {
526 log_sg("Setting '%s': %s", name, secfile_error());
527 }
528 if (gamestart_valid) {
530 "settings.set%d.gamestart", i)) {
531 if (nturns == 0) {
532 /* Invent a new "autosaves" setting */
534 "settings.set%d.gamestart", new_opt);
535 /* Pick something valid for saveturns */
537 "settings.set%d.gamestart", i);
538 } else {
540 "settings.set%d.gamestart", new_opt);
541 }
542 } else {
543 log_sg("Setting '%s': %s", name, secfile_error());
544 }
545 }
546 } else if (!fc_strcasecmp("autosaves", name)) {
547 /* Sanity check. This won't trigger on an option we've just
548 * invented, as the loop won't include it. */
549 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
550 "savefile. It may have been overridden.");
551 }
552 }
553 }
554 }
555}
556
557/************************************************************************/
560static const char *killcitizen_enum_str(secfile_data_t data, int bit)
561{
562 switch (bit) {
563 case UMT_LAND:
564 return "LAND";
565 case UMT_SEA:
566 return "SEA";
567 case UMT_BOTH:
568 return "BOTH";
569 }
570
571 return NULL;
572}
573
574/************************************************************************/
579{
580 const char *modname[] = { "Road", "Railroad" };
581 const char *old_activities_names[] = {
582 "Idle",
583 "Pollution",
584 "Unused Road",
585 "Mine",
586 "Irrigate",
587 "Mine",
588 "Irrigate",
589 "Fortified",
590 "Fortress",
591 "Sentry",
592 "Unused Railroad",
593 "Pillage",
594 "Goto",
595 "Explore",
596 "Transform",
597 "Unused",
598 "Unused Airbase",
599 "Fortifying",
600 "Fallout",
601 "Unused Patrol",
602 "Base"
603 };
604
605 /* Check status and return if not OK (sg_success FALSE). */
606 sg_check_ret();
607
608 log_debug("Upgrading data from savegame to version 2.5.0");
609
610 secfile_insert_int(loading->file, 2, "savefile.roads_size");
611 secfile_insert_int(loading->file, 0, "savefile.trait_size");
612
614 "savefile.roads_vector");
615
616 secfile_insert_int(loading->file, 19, "savefile.activities_size");
618 "savefile.activities_vector");
619
620 /* Server setting migration. */
621 {
622 int set_count;
623
624 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
625 int i;
626 bool gamestart_valid
628 "settings.gamestart_valid");
629 for (i = 0; i < set_count; i++) {
630 const char *name
631 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
632 if (!name) {
633 continue;
634 }
635 /* In 2.4.x and prior, "killcitizen" listed move types that
636 * killed citizens after successful attack. Now killcitizen
637 * is just boolean and classes affected are defined in ruleset. */
638 if (!fc_strcasecmp("killcitizen", name)) {
639 int value;
640
641 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
643 "settings.set%d.value", i)) {
644 /* Lowest bit of old killcitizen value indicates if
645 * land units should kill citizens. We take that as
646 * new boolean killcitizen value. */
647 if (value & 0x1) {
649 "settings.set%d.value", i);
650 } else {
652 "settings.set%d.value", i);
653 }
654 } else {
655 log_sg("Setting '%s': %s", name, secfile_error());
656 }
657 if (gamestart_valid) {
658 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
660 "settings.set%d.gamestart", i)) {
661 /* Lowest bit of old killcitizen value indicates if
662 * land units should kill citizens. We take that as
663 * new boolean killcitizen value. */
664 if (value & 0x1) {
666 "settings.set%d.gamestart", i);
667 } else {
669 "settings.set%d.gamestart", i);
670 }
671 } else {
672 log_sg("Setting '%s': %s", name, secfile_error());
673 }
674 }
675 }
676 }
677 }
678 }
679}
680
681/************************************************************************/
685{
686 switch (type) {
687 case REVOLEN_FIXED:
688 return "FIXED";
689 case REVOLEN_RANDOM:
690 return "RANDOM";
692 return "QUICKENING";
694 return "RANDQUICK";
695 }
696
697 return "";
698}
699
700/************************************************************************/
705{
706 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
707 int tsize;
708 int ti;
709 int turn;
710
711 /* Check status and return if not OK (sg_success FALSE). */
712 sg_check_ret();
713
714 log_debug("Upgrading data from savegame to version 2.6.0");
715
716 /* Terrain mapping table - use current ruleset as we have no way to know
717 * any other old values. */
718 ti = 0;
720 char buf[2];
721
722 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
724 buf[1] = '\0';
725 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
727
728 /* Server setting migration. */
729 {
730 int set_count;
731
732 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
733 char value_buffer[1024] = "";
734 char gamestart_buffer[1024] = "";
735 int i;
736 int dcost = -1;
737 int dstartcost = -1;
740 bool gamestart_valid
742 "settings.gamestart_valid");
743 int new_set_count;
744
745 for (i = 0; i < set_count; i++) {
746 const char *name
747 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
748 if (!name) {
749 continue;
750 }
751
752 /* In 2.5.x and prior, "spacerace" boolean controlled if
753 * spacerace victory condition was active. */
754 if (!fc_strcasecmp("spacerace", name)) {
755 bool value;
756
757 if (secfile_lookup_bool(loading->file, &value,
758 "settings.set%d.value", i)) {
759 if (value) {
760 if (value_buffer[0] != '\0') {
762 }
763 sz_strlcat(value_buffer, "SPACERACE");
764 }
765 } else {
766 log_sg("Setting '%s': %s", name, secfile_error());
767 }
768 if (secfile_lookup_bool(loading->file, &value,
769 "settings.set%d.gamestart", i)) {
770 if (value) {
771 if (gamestart_buffer[0] != '\0') {
773 }
774 sz_strlcat(gamestart_buffer, "SPACERACE");
775 }
776 } else {
777 log_sg("Setting '%s': %s", name, secfile_error());
778 }
779
780 /* We cannot delete old values from the secfile, or rather cannot
781 * change index of the later settings. Renumbering them is not easy as
782 * we don't know type of each setting we would encounter.
783 * So we keep old setting values and only add new "victories" setting. */
784 } else if (!fc_strcasecmp("alliedvictory", name)) {
785 bool value;
786
787 if (secfile_lookup_bool(loading->file, &value,
788 "settings.set%d.value", i)) {
789 if (value) {
790 if (value_buffer[0] != '\0') {
792 }
793 sz_strlcat(value_buffer, "ALLIED");
794 }
795 } else {
796 log_sg("Setting '%s': %s", name, secfile_error());
797 }
798 if (secfile_lookup_bool(loading->file, &value,
799 "settings.set%d.gamestart", i)) {
800 if (value) {
801 if (gamestart_buffer[0] != '\0') {
803 }
804 sz_strlcat(gamestart_buffer, "ALLIED");
805 }
806 } else {
807 log_sg("Setting '%s': %s", name, secfile_error());
808 }
809 } else if (!fc_strcasecmp("revolen", name)) {
810 int value;
811
812 if (secfile_lookup_int(loading->file, &value,
813 "settings.set%d.value", i)) {
814 /* 0 meant RANDOM 1-5 */
815 if (value == 0) {
818 "settings.set%d.value", i);
819 } else {
821 }
822 } else {
823 log_sg("Setting '%s': %s", name, secfile_error());
824 }
825 if (secfile_lookup_int(loading->file, &value,
826 "settings.set%d.gamestart", i)) {
827 /* 0 meant RANDOM 1-5 */
828 if (value == 0) {
831 "settings.set%d.gamestart", i);
832 } else {
834 }
835 } else {
836 log_sg("Setting '%s': %s", name, secfile_error());
837 }
838 } else if (!fc_strcasecmp("happyborders", name)) {
839 bool value;
840
841 if (secfile_lookup_bool(loading->file, &value,
842 "settings.set%d.value", i)) {
843 secfile_entry_delete(loading->file, "settings.set%d.value", i);
844 if (value) {
845 secfile_insert_str(loading->file, "NATIONAL",
846 "settings.set%d.value", i);
847 } else {
848 secfile_insert_str(loading->file, "DISABLED",
849 "settings.set%d.value", i);
850 }
851 } else {
852 log_sg("Setting '%s': %s", name, secfile_error());
853 }
854 if (secfile_lookup_bool(loading->file, &value,
855 "settings.set%d.gamestart", i)) {
856 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
857 if (value) {
858 secfile_insert_str(loading->file, "NATIONAL",
859 "settings.set%d.gamestart", i);
860 } else {
861 secfile_insert_str(loading->file, "DISABLED",
862 "settings.set%d.gamestart", i);
863 }
864 } else {
865 log_sg("Setting '%s': %s", name, secfile_error());
866 }
867 } else if (!fc_strcasecmp("team_pooled_research", name)) {
869 &team_pooled_research,
870 "settings.set%d.value", i),
871 "%s", secfile_error());
872 } else if (!fc_strcasecmp("diplcost", name)) {
873 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
874 if (secfile_lookup_int(loading->file, &dcost,
875 "settings.set%d.value", i)) {
876 } else {
877 log_sg("Setting '%s': %s", name, secfile_error());
878 }
879
881 "settings.set%d.gamestart", i)) {
882 } else {
883 log_sg("Setting '%s': %s", name, secfile_error());
884 }
885 } else if (!fc_strcasecmp("huts", name)) {
886 /* Scale of 'huts' changed. */
887 int hcount;
888
890 "settings.set%d.value", i)) {
891 } else {
892 log_sg("Setting '%s': %s", name, secfile_error());
893 }
894
895 /* Store old-style absolute value. */
897 }
898 }
899
900 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
901
902 if (dcost >= 0) {
903 new_set_count += 2;
904 }
905
906 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
907
908 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
909 set_count);
910 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
911 set_count);
912 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
913 set_count + 1);
914 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
915 set_count + 1);
916
917 if (dcost >= 0) {
918 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
919 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
920 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
921 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
922 }
923
924 if (gamestart_valid) {
925 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
926 set_count);
927 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
928 set_count + 1);
929
930 if (dcost >= 0) {
931 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
932 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
933 }
934 }
935 }
936 }
937
938 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
939 "Trait size: %s", secfile_error());
940
941 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
942
943 player_slots_iterate(pslot) {
944 int plrno = player_slot_index(pslot);
945 bool got_first_city;
946 int old_barb_type;
947 enum barbarian_type new_barb_type;
948 int i;
949 const char *name;
950 int score;
951 int units_num;
952
953 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
954 continue;
955 }
956
957 /* Renamed 'capital' to 'got_first_city'. */
959 "player%d.capital", plrno)) {
961 "player%d.got_first_city", plrno);
962 }
963
964 /* Add 'anonymous' qualifiers for user names */
965 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
967 "player%d.unassigned_user", plrno);
968
969 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
971 "player%d.unassigned_ranked", plrno);
972
973 /* Convert numeric barbarian type to textual */
975 "player%d.ai.is_barbarian", plrno);
978 "player%d.ai.barb_type", plrno);
979
980 /* Pre-2.6 didn't record when a player was created or died, so we have
981 * to assume they lived from the start of the game until last turn */
982 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
983
984 /* As if there never has been a war. */
985 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
986
987 /* Assume people were playing until current reload */
988 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
989
990 for (i = 0; i < tsize; i++) {
991 int val;
992
993 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
994 plrno, i);
995 if (val != -1) {
996 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
997 }
998
1000 "player%d.trait.mod%d", plrno, i),
1001 "Trait mod: %s", secfile_error());
1002 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1003 }
1004
1005 score = secfile_lookup_int_default(loading->file, -1,
1006 "player%d.units_built", plrno);
1007 if (score >= 0) {
1008 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1009 }
1010
1011 score = secfile_lookup_int_default(loading->file, -1,
1012 "player%d.units_killed", plrno);
1013 if (score >= 0) {
1014 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1015 }
1016
1017 score = secfile_lookup_int_default(loading->file, -1,
1018 "player%d.units_lost", plrno);
1019 if (score >= 0) {
1020 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1021 }
1022
1023 /* Units orders. */
1025 "player%d.nunits",
1026 plrno);
1027
1028 for (i = 0; i < units_num; i++) {
1029 int len;
1030
1032 "player%d.u%d.orders_last_move_safe",
1033 plrno, i)) {
1034 continue;
1035 }
1036
1038 "player%d.u%d.orders_length",
1039 plrno, i);
1040 if (len > 0) {
1041 char orders_str[len + 1];
1042 char *p;
1043
1046 "player%d.u%d.orders_list",
1047 plrno, i));
1048 if ((p = strrchr(orders_str, 'm'))
1049 || (p = strrchr(orders_str, 'M'))) {
1050 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1052 "player%d.u%d.orders_list", plrno, i);
1053 }
1054 }
1055 }
1057
1058 /* Add specialist order - loading time order is ok here, as we will use
1059 * that when we in later part of compatibility conversion use the specialist
1060 * values */
1062 "savefile.specialists_size");
1063 {
1064 const char **modname;
1065 int i = 0;
1066
1068
1072
1074 "savefile.specialists_vector");
1075
1076 free(modname);
1077 }
1078
1079 /* Replace all city specialist count fields with correct names */
1080 player_slots_iterate(pslot) {
1081 int plrno = player_slot_index(pslot);
1082 int ncities;
1083 int i;
1084
1085 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1086 continue;
1087 }
1088
1089 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1090
1091 for (i = 0; i < ncities; i++) {
1092 int k = 0;
1093
1095 struct specialist *psp = specialist_by_number(sp);
1096 int count;
1097
1099 "player%d.c%d.n%s",
1101 "specialist error: %s", secfile_error());
1102 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1104 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1105 plrno, i, k++);
1107 }
1109
1110 /* Build [research]. */
1111 {
1112 const struct {
1113 const char *name;
1114 enum entry_type type;
1115 } entries[] = {
1116 { "goal_name", ENTRY_STR },
1117 { "techs", ENTRY_INT },
1118 { "futuretech", ENTRY_INT },
1119 { "bulbs_before", ENTRY_INT },
1120 { "saved_name", ENTRY_STR },
1121 { "bulbs", ENTRY_INT },
1122 { "now_name", ENTRY_STR },
1123 { "got_tech", ENTRY_BOOL },
1124 { "done", ENTRY_STR }
1125 };
1126
1128 int count = 0;
1129 int i;
1130
1131 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1132 researches[i] = -1;
1133 }
1134
1135 player_slots_iterate(pslot) {
1136 int plrno = player_slot_index(pslot);
1137 int ival;
1138 bool bval;
1139 const char *sval;
1140 int j;
1141
1142 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1143 continue;
1144 }
1145
1146 /* Get the research number. */
1147 if (team_pooled_research) {
1149 "player%d.team_no", plrno);
1150 } else {
1151 i = plrno;
1152 }
1153
1155 "Research out of bounds (%d)!", i);
1156
1157 /* Find the index in [research] section. */
1158 if (researches[i] == -1) {
1159 /* This is the first player for this research. */
1160 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1161 researches[i] = count;
1162 count++;
1163 }
1164 i = researches[i];
1165
1166 /* Move entries. */
1167 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1168 switch (entries[j].type) {
1169 case ENTRY_BOOL:
1170 if (secfile_lookup_bool(loading->file, &bval,
1171 "player%d.research.%s",
1172 plrno, entries[j].name)) {
1173 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1174 i, entries[j].name);
1175 }
1176 break;
1177 case ENTRY_INT:
1178 if (secfile_lookup_int(loading->file, &ival,
1179 "player%d.research.%s",
1180 plrno, entries[j].name)) {
1181 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1182 i, entries[j].name);
1183 }
1184 break;
1185 case ENTRY_STR:
1186 if ((sval = secfile_lookup_str(loading->file,
1187 "player%d.research.%s",
1188 plrno, entries[j].name))) {
1189 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1190 i, entries[j].name);
1191 }
1192 break;
1193 case ENTRY_FLOAT:
1195 "Research related entry marked as float.");
1196 break;
1199 break;
1200 case ENTRY_LONG_COMMENT:
1202 break;
1203 case ENTRY_ILLEGAL:
1205 break;
1206 }
1207 }
1209 secfile_insert_int(loading->file, count, "research.count");
1210 }
1211
1212 /* Add diplstate type order. */
1214 "savefile.diplstate_type_size");
1215 if (DS_LAST > 0) {
1216 const char **modname;
1217 int i;
1218 int j;
1219
1220 i = 0;
1221 modname = fc_calloc(DS_LAST, sizeof(*modname));
1222
1223 for (j = 0; j < DS_LAST; j++) {
1225 }
1226
1228 DS_LAST,
1229 "savefile.diplstate_type_vector");
1230 free(modname);
1231 }
1232
1233 /* Fix save games from Freeciv versions with a bug that made it view
1234 * "Never met" as closer than "Peace" or "Alliance". */
1235 player_slots_iterate(pslot) {
1236 int plrno = player_slot_index(pslot);
1237
1238 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1239 continue;
1240 }
1241
1243 int i = player_slot_index(pslot2);
1244 char buf[32];
1245 int current;
1246 int closest;
1247
1248 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1249 continue;
1250 }
1251
1252 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1253
1254 /* Read the current diplomatic state. */
1256 "%s.type",
1257 buf);
1258
1259 /* Read the closest diplomatic state. */
1261 "%s.max_state",
1262 buf);
1263
1264 if (closest == DS_NO_CONTACT
1265 && (current == DS_PEACE
1266 || current == DS_ALLIANCE)) {
1267 const char *name1 = secfile_lookup_str_default(loading->file, "",
1268 "player%d.name", plrno);
1269 const char *name2 = secfile_lookup_str_default(loading->file, "",
1270 "player%d.name", i);
1271 /* The current relationship is closer than what the save game
1272 * claims is the closes relationship ever. */
1273
1274 log_sg(_("The save game is wrong about what the closest"
1275 " relationship %s (player %d) and %s (player %d) have had is."
1276 " Fixing it..."),
1277 name1, plrno, name2, i);
1278
1279 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1280 }
1283}
1284
1285/************************************************************************/
1288static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1289 int old_def, bool keep_default)
1290{
1291 int value;
1292
1293 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1294
1295 if (value != old_def || !keep_default) {
1296 value++;
1297 secfile_replace_int(loading->file, value, "%s", key);
1298 }
1299
1300 return value;
1301}
1302
1303/************************************************************************/
1311{
1312 bool randsaved;
1313 int num_settings;
1314 bool started;
1315 int old_turn;
1316 int event_count;
1317 int i;
1318
1319 /* Check status and return if not OK (sg_success FALSE). */
1320 sg_check_ret();
1321
1322 log_debug("Upgrading data from savegame to version 3.0.0");
1323
1324 /* Rename "random.save" as "random.saved"
1325 * Note that it's not an error if a scenario does not have [random] at all. */
1326 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1327 secfile_insert_bool(loading->file, randsaved, "random.saved");
1328 }
1329
1330 /* Already started games should have their turn counts increased by 1 */
1331 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1332 started = TRUE;
1333
1334 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1336 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1337 } else {
1338 started = FALSE;
1339 }
1340
1341 player_slots_iterate(pslot) {
1342 int plrno = player_slot_index(pslot);
1343 const char *flag_names[1];
1344
1345 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1346 continue;
1347 }
1348
1349 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1350 plrno)) {
1352
1354 "player%d.flags", plrno);
1355 }
1356
1357 if (started) {
1358 int num = secfile_lookup_int_default(loading->file, 0,
1359 "player%d.nunits",
1360 plrno);
1361
1362 for (i = 0; i < num; i++) {
1363 char buf[64];
1364
1365 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1366
1368 }
1369
1370 num = secfile_lookup_int_default(loading->file, 0,
1371 "player%d.ncities", plrno);
1372
1373 for (i = 0; i < num; i++) {
1374 char buf[64];
1375
1376 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1377
1379 }
1380 }
1382
1383 /* Settings */
1385 "settings.set_count");
1386
1387 /* User meta server message is now a setting. */
1389 "game.meta_usermessage")) {
1390 const char *metamessage;
1391
1393 "game.meta_message");
1394
1395 /* Insert the meta message as a setting */
1396 secfile_insert_str(loading->file, "metamessage",
1397 "settings.set%d.name", num_settings);
1399 "settings.set%d.value", num_settings);
1400 secfile_insert_str(loading->file, "",
1401 "settings.set%d.gamestart", num_settings);
1402 num_settings++;
1403 }
1404
1405 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1406
1407 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1408
1409 for (i = 0; i < event_count; i++) {
1410 const char *etype;
1411
1412 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1413
1414 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1415 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1416 "event_cache.events%d.event", i);
1417 }
1418 }
1419}
1420
1421/************************************************************************/
1426{
1427 int ssa_size;
1428
1429 if (format_class == SAVEGAME_2) {
1430 /* Handled in savegame2 */
1431 return;
1432 }
1433
1435 "savefile.server_side_agent_size");
1436
1437 if (ssa_size != 0) {
1438 /* Already inserted. */
1439 return;
1440 }
1441
1442 /* Add server side agent order. */
1444 "savefile.server_side_agent_size");
1445 if (SSA_COUNT > 0) {
1446 const char **modname;
1447 int i;
1448 int j;
1449
1450 i = 0;
1451 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1452
1453 for (j = 0; j < SSA_COUNT; j++) {
1455 }
1456
1458 SSA_COUNT,
1459 "savefile.server_side_agent_list");
1460 free(modname);
1461 }
1462
1463 /* Insert server_side_agent unit field. */
1464 player_slots_iterate(pslot) {
1465 int unit;
1466 int units_num;
1467 int plrno = player_slot_index(pslot);
1468
1469 if (secfile_section_lookup(loading->file, "player%d", plrno)
1470 == NULL) {
1471 continue;
1472 }
1473
1474 /* Number of units the player has. */
1476 "player%d.nunits",
1477 plrno);
1478
1479 for (unit = 0; unit < units_num; unit++) {
1480 bool ai;
1481
1483 "player%d.u%d.server_side_agent",
1484 plrno, unit)
1485 != NULL) {
1486 /* Already updated? */
1487 continue;
1488 }
1489
1491 "player%d.u%d.ai",
1492 plrno, unit);
1493
1494 if (ai) {
1495 /* Autosettler and Autoexplore are separated by
1496 * compat_post_load_030100() when set to SSA_AUTOSETTLER */
1498 "player%d.u%d.server_side_agent",
1499 plrno, unit);
1500 } else {
1502 "player%d.u%d.server_side_agent",
1503 plrno, unit);
1504 }
1505 }
1507}
1508
1509/************************************************************************/
1517{
1518 /* Check status and return if not OK (sg_success FALSE). */
1519 sg_check_ret();
1520
1521 log_debug("Upgrading data from savegame to version 3.1.0");
1522
1523 /* Actions are now stored by number. */
1524 player_slots_iterate(pslot) {
1525 int unit;
1526 int units_num;
1527 int plrno = player_slot_index(pslot);
1528
1529 if (secfile_section_lookup(loading->file, "player%d", plrno)
1530 == NULL) {
1531 continue;
1532 }
1533
1534 /* Number of units the player has. */
1536 "player%d.nunits",
1537 plrno);
1538
1539 for (unit = 0; unit < units_num; unit++) {
1540 const char *action_unitstr;
1541 int order_len;
1542
1544 "player%d.u%d.orders_length",
1545 plrno, unit);
1546
1548 "player%d.u%d.action_list",
1549 plrno, unit))) {
1550 int order_num;
1551
1554 }
1555
1556 for (order_num = 0; order_num < order_len; order_num++) {
1558
1559 if (action_unitstr[order_num] == '?') {
1561 } else {
1563 }
1564
1565 if (order_num == 0) {
1566 /* The start of a vector has no number. */
1568 "player%d.u%d.action_vec",
1569 plrno, unit);
1570 } else {
1572 "player%d.u%d.action_vec,%d",
1573 plrno, unit, order_num);
1574 }
1575 }
1576 }
1577 }
1579
1580 {
1581 int action_count;
1582
1584 "savefile.action_size");
1585
1586 if (action_count > 0) {
1587 const char **modname;
1588 const char **savemod;
1589 int j;
1590 const char *dur_name = "Disband Unit Recover";
1591
1592 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1593 "savefile.action_vector");
1594
1596
1597 for (j = 0; j < action_count; j++) {
1598 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1599 savemod[j] = dur_name;
1600 } else {
1601 savemod[j] = modname[j];
1602 }
1603 }
1604
1606 "savefile.action_vector");
1607
1608 free(savemod);
1609 }
1610 }
1611
1612 /* Server setting migration. */
1613 {
1614 int set_count;
1615
1616 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1617 int i;
1618 bool gamestart_valid
1620 "settings.gamestart_valid");
1621
1622 /* Only add gamesetdef if gamestart is valid at all */
1623 if (gamestart_valid) {
1624 for (i = 0; i < set_count; i++) {
1625 const char *name
1626 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1627
1628 if (!name) {
1629 continue;
1630 }
1631
1633 "settings.set%d.gamesetdef", i);
1634 }
1635 }
1636 }
1637 }
1638
1639 /* Explicit server side agent was new in 3.1 */
1641}
1642
1643/************************************************************************/
1647{
1648 int i;
1649
1650 for (i = 0; i < act_unit->orders.length; i++) {
1651 struct unit_order *order = &act_unit->orders.list[i];
1652
1653 if (order->order != ORDER_ACTIVITY) {
1654 continue;
1655 }
1656
1657 switch (order->activity) {
1658 case ACTIVITY_CLEAN:
1659 case ACTIVITY_MINE:
1660 case ACTIVITY_IRRIGATE:
1661 case ACTIVITY_PLANT:
1662 case ACTIVITY_CULTIVATE:
1663 case ACTIVITY_TRANSFORM:
1664 case ACTIVITY_CONVERT:
1666 case ACTIVITY_BASE:
1667 case ACTIVITY_GEN_ROAD:
1668 case ACTIVITY_PILLAGE:
1669 action_iterate(act_id) {
1670 struct action *paction = action_by_number(act_id);
1671
1672 if (action_get_activity(paction) == order->activity) {
1673 order->order = ORDER_PERFORM_ACTION;
1674 order->action = action_number(paction);
1675 order->activity = ACTIVITY_LAST;
1676 break;
1677 }
1679 break;
1680 case ACTIVITY_SENTRY:
1681 /* Not an action */
1682 break;
1683 case ACTIVITY_EXPLORE:
1684 case ACTIVITY_IDLE:
1685 case ACTIVITY_GOTO:
1686 case ACTIVITY_FORTIFIED:
1687 case ACTIVITY_LAST:
1688 log_error("Activity %d is not supposed to appear in unit orders",
1689 order->activity);
1690 break;
1691 }
1692 }
1693}
1694
1695/************************************************************************/
1699{
1700 switch (dir) {
1701 case DIR8_NORTH:
1702 return DIR8_SOUTH;
1703 case DIR8_NORTHEAST:
1704 return DIR8_SOUTHWEST;
1705 case DIR8_EAST:
1706 return DIR8_WEST;
1707 case DIR8_SOUTHEAST:
1708 return DIR8_NORTHWEST;
1709 case DIR8_SOUTH:
1710 return DIR8_NORTH;
1711 case DIR8_SOUTHWEST:
1712 return DIR8_NORTHEAST;
1713 case DIR8_WEST:
1714 return DIR8_EAST;
1715 case DIR8_NORTHWEST:
1716 return DIR8_SOUTHEAST;
1717 }
1718
1719 return DIR8_ORIGIN;
1720}
1721
1722/************************************************************************/
1726{
1727 int i;
1728 struct tile *current_tile;
1729 struct tile *tgt_tile;
1730
1731 if (!unit_has_orders(act_unit)) {
1732 return;
1733 }
1734
1735 /* The order index is for the unit at its current tile. */
1736 current_tile = unit_tile(act_unit);
1737
1738 /* Rewind to the beginning of the orders */
1739 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1740 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1741
1742 if (!(prev_order->order == ORDER_PERFORM_ACTION
1746 current_tile = mapstep(&(wld.map), current_tile,
1747 dir_opposite(prev_order->dir));
1748 }
1749 }
1750
1751 /* Upgrade to explicit target tile */
1752 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1753 struct unit_order *order = &act_unit->orders.list[i];
1754
1755 if (order->order == ORDER_PERFORM_ACTION
1756 && order->target != NO_TARGET) {
1757 /* The target is already specified in the new format. */
1758
1759 /* The index_to_tile() call has no side-effects that we
1760 * would want also in NDEBUG builds. */
1761 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1762 return;
1763 }
1764
1765 if (!direction8_is_valid(order->dir)) {
1766 /* The target of the action is on the actor's tile. */
1767 tgt_tile = current_tile;
1768 } else {
1769 /* The target of the action is on a tile next to the actor. */
1770 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1771 }
1772
1773 if (order->order == ORDER_PERFORM_ACTION) {
1774 if (tgt_tile != NULL) {
1775 struct action *paction = action_by_number(order->action);
1776
1777 order->target = tgt_tile->index;
1778 /* Leave no traces. */
1779 order->dir = DIR8_ORIGIN;
1780
1782 /* The action moves the unit to the target tile (unless this is the
1783 * final order) */
1786 || i == act_unit->orders.length - 1);
1787 current_tile = tgt_tile;
1788 }
1789 } else {
1790 current_tile = NULL;
1791 }
1792 } else {
1793 current_tile = tgt_tile;
1794 }
1795 }
1796
1797 if (current_tile == NULL) {
1798 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1800 }
1801}
1802
1803/************************************************************************/
1807{
1808 players_iterate_alive(pplayer) {
1809 unit_list_iterate(pplayer->units, punit) {
1812 }
1815}
1816
1817/************************************************************************/
1822{
1823 /* Check status and return if not OK (sg_success FALSE). */
1824 sg_check_ret();
1825
1826 /* Action orders were new in 3.0 */
1827 if (format_class == SAVEGAME_3) {
1828 /* Only 3.0 savegames may have "Attack" action orders. */
1829 players_iterate_alive(pplayer) {
1830 unit_list_iterate(pplayer->units, punit) {
1831 int i;
1832
1833 if (!punit->has_orders) {
1834 continue;
1835 }
1836
1838 || punit->orders.list != NULL, continue);
1839
1840 for (i = 0; i < punit->orders.length; i++) {
1841 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1847 }
1848
1849 /* Production targeted actions were split from building targeted
1850 * actions in 3.1. The building sub target encoding changed. */
1852 && ((punit->orders.list[i].action
1854 || (punit->orders.list[i].action
1856 punit->orders.list[i].sub_target -= 1;
1857 }
1859 && (punit->orders.list[i].action
1861 && punit->orders.list[i].sub_target == -1) {
1864 }
1866 && (punit->orders.list[i].action
1868 && punit->orders.list[i].sub_target == -1) {
1871 }
1872 }
1875 }
1876
1877 /* Explicit server side agent was new in 3.1 */
1879
1880 /* Some activities should only be ordered in action orders. */
1881 players_iterate_alive(pplayer) {
1882 unit_list_iterate(pplayer->units, punit) {
1886
1887 /* Unit order action target isn't dir anymore */
1888 players_iterate_alive(pplayer) {
1889 unit_list_iterate(pplayer->units, punit) {
1893
1894 /* Backward compatibility: if we had any open-ended orders (pillage)
1895 * in the savegame, assign specific targets now */
1896 players_iterate_alive(pplayer) {
1897 unit_list_iterate(pplayer->units, punit) {
1899 &punit->activity,
1903}
1904
1905/************************************************************************/
1913{
1914 int i;
1915 int count;
1916 int set_count;
1917 bool gamestart_valid = FALSE;
1918
1919 /* Check status and return if not OK (sg_success FALSE). */
1920 sg_check_ret();
1921
1922 log_debug("Upgrading data from savegame to version 3.2.0");
1923
1924 {
1925 const char *str = secfile_lookup_str_default(loading->file, NULL,
1926 "savefile.orig_version");
1927
1928 if (str == NULL) {
1929 /* Make sure CURRENTLY running version does not
1930 * end as orig_version when we resave. */
1931 if (format_class == SAVEGAME_3) {
1932 secfile_insert_str(loading->file, "old savegame3, or older",
1933 "savefile.orig_version");
1934 } else {
1936
1937 secfile_insert_str(loading->file, "savegame2, or older",
1938 "savefile.orig_version");
1939 }
1940 }
1941 }
1942
1943 {
1944 int action_count;
1945
1947 "savefile.action_size");
1948
1949 if (action_count > 0) {
1950 const char **modname;
1951 const char **savemod;
1952 int j;
1953 const char *dur_name = "Transport Deboard";
1954 const char *clean_name = "Clean";
1955
1956 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1957 "savefile.action_vector");
1958
1960
1961 for (j = 0; j < action_count; j++) {
1962 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1963 savemod[j] = dur_name;
1964 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1965 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1966 savemod[j] = clean_name;
1967 } else {
1968 savemod[j] = modname[j];
1969 }
1970 }
1971
1973 "savefile.action_vector");
1974
1975 free(savemod);
1976 }
1977 }
1978
1979 {
1980 int activities_count;
1981
1983 "savefile.activities_size");
1984
1985 if (activities_count > 0) {
1986 const char **modname;
1987 const char **savemod;
1988 int j;
1989 const char *clean_name = "Clean";
1990
1991 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1992 "savefile.activities_vector");
1993
1995
1996 for (j = 0; j < activities_count; j++) {
1997 if (!fc_strcasecmp("Pollution", modname[j])
1998 || !fc_strcasecmp("Fallout", modname[j])) {
1999 savemod[j] = clean_name;
2000 } else {
2001 savemod[j] = modname[j];
2002 }
2003 }
2004
2006 "savefile.activities_vector");
2007
2008 free(savemod);
2009 }
2010 }
2011
2012 /* Server setting migration. */
2013 {
2014 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2015 int alltemperate_idx = -1, singlepole_idx = -1;
2016 bool count_changed = FALSE;
2017
2020 "settings.gamestart_valid");
2021
2022 for (i = 0; i < set_count; i++) {
2023 const char *old_name
2024 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2025 const char *name;
2026
2027 if (!old_name) {
2028 continue;
2029 }
2030
2032
2033 if (fc_strcasecmp(old_name, name)) {
2034 /* Setting's name changed */
2035 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2036 }
2037
2038 if (!gamestart_valid) {
2039 /* Older savegames saved these values even when they were not valid.
2040 * Silence warnings caused by them. */
2041 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2042 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2043 }
2044
2045 if (!fc_strcasecmp("compresstype", name)) {
2046 const char *val = secfile_lookup_str(loading->file,
2047 "settings.set%d.value", i);
2048 if (!fc_strcasecmp(val, "BZIP2")) {
2049#ifdef FREECIV_HAVE_LIBZSTD
2050 secfile_replace_str(loading->file, "ZSTD",
2051 "settings.set%d.value", i);
2052#elif FREECIV_HAVE_LIBLZMA
2053 secfile_replace_str(loading->file, "XZ",
2054 "settings.set%d.value", i);
2055#elif FREECIV_HAVE_LIBZ
2056 secfile_replace_str(loading->file, "LIBZ",
2057 "settings.set%d.value", i);
2058#else
2059 secfile_replace_str(loading->file, "PLAIN",
2060 "settings.set%d.value", i);
2061#endif
2062 }
2063
2064 if (gamestart_valid) {
2065 val = secfile_lookup_str(loading->file,
2066 "settings.set%d.gamestart", i);
2067 if (!fc_strcasecmp(val, "BZIP2")) {
2068#ifdef FREECIV_HAVE_LIBZSTD
2069 secfile_replace_str(loading->file, "ZSTD",
2070 "settings.set%d.gamestart", i);
2071#elif FREECIV_HAVE_LIBLZMA
2072 secfile_replace_str(loading->file, "XZ",
2073 "settings.set%d.gamestart", i);
2074#elif FREECIV_HAVE_LIBZ
2075 secfile_replace_str(loading->file, "LIBZ",
2076 "settings.set%d.gamestart", i);
2077#else
2078 secfile_replace_str(loading->file, "PLAIN",
2079 "settings.set%d.gamestart", i);
2080#endif
2081 }
2082 }
2083 } else if (!fc_strcasecmp("topology", name)) {
2084 struct setting *pset = setting_by_name(name);
2085 struct sf_cb_data info = { pset, TRUE };
2086 int val;
2087
2088 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2090 "settings.set%d.value", i)) {
2091 char wrap[100];
2092 char buf[100];
2093
2094 if (val & TF_OLD_WRAPX) {
2095 if (val & TF_OLD_WRAPY) {
2096 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2097 } else {
2098 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2099 }
2100 } else if (val & TF_OLD_WRAPY) {
2101 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2102 } else {
2103 fc_strlcpy(wrap, "", sizeof(wrap));
2104 }
2105
2106 if (val & TF_ISO) {
2107 if (val & TF_HEX) {
2108 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2109 } else {
2110 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2111 }
2112 } else if (val & TF_HEX) {
2113 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2114 } else {
2116 }
2117
2118 setting_value_name(pset, FALSE, buf, sizeof(buf));
2120 "settings.set%d.value", i);
2121
2123 "wrap", "settings.set%d.name", set_count);
2125 wrap, "settings.set%d.value", set_count);
2126
2127 if (gamestart_valid) {
2128 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2130 "settings.set%d.gamestart", i)) {
2131 if (val & TF_OLD_WRAPX) {
2132 if (val & TF_OLD_WRAPY) {
2133 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2134 } else {
2135 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2136 }
2137 } else if (val & TF_OLD_WRAPY) {
2138 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2139 } else {
2140 fc_strlcpy(wrap, "", sizeof(wrap));
2141 }
2142
2143 if (val & TF_ISO) {
2144 if (val & TF_HEX) {
2145 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2146 } else {
2147 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2148 }
2149 } else if (val & TF_HEX) {
2150 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2151 } else {
2153 }
2154
2155 setting_value_name(pset, FALSE, buf, sizeof(buf));
2157 "settings.set%d.gamestart", i);
2158
2160 wrap, "settings.set%d.gamestart", set_count);
2161 }
2162 }
2163
2164 set_count++;
2166 }
2167 } else if (!fc_strcasecmp("alltemperate", name)) {
2169 } else if (!fc_strcasecmp("singlepole", name)) {
2170 singlepole_idx = i;
2171 }
2172 }
2173
2174 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2175 int north_latitude, south_latitude;
2176 int north_idx, south_idx;
2178
2179 if (alltemperate_idx < 0
2181 "settings.set%d.value",
2183 /* Infer what would've been the ruleset default */
2185 }
2186
2187 if (singlepole_idx < 0
2189 "settings.set%d.value",
2190 singlepole_idx)) {
2191 /* Infer what would've been the ruleset default */
2193 }
2194
2195 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2196 * changes, that'll have to be handled in later migrations anyway */
2197 north_latitude = alltemperate ? 500 : 1000;
2198 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2199
2200 /* Replace alltemperate with northlatitude, and singlepole with
2201 * southlatitude. If only one of the two was given, add the other
2202 * at the end. */
2205
2206 secfile_replace_str(loading->file, "northlatitude",
2207 "settings.set%d.name", north_idx);
2208 secfile_replace_int(loading->file, north_latitude,
2209 "settings.set%d.value", north_idx);
2210
2211 secfile_replace_str(loading->file, "southlatitude",
2212 "settings.set%d.name", south_idx);
2213 secfile_replace_int(loading->file, south_latitude,
2214 "settings.set%d.value", south_idx);
2215
2216 if (gamestart_valid) {
2217 if (alltemperate_idx < 0
2219 "settings.set%d.gamestart",
2221 alltemperate =
2223 }
2224
2225 if (singlepole_idx < 0
2227 "settings.set%d.gamestart",
2228 singlepole_idx)) {
2230 }
2231
2232 north_latitude = alltemperate ? 500 : 1000;
2233 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2234
2235 secfile_replace_int(loading->file, north_latitude,
2236 "settings.set%d.gamestart", north_idx);
2237 secfile_replace_int(loading->file, south_latitude,
2238 "settings.set%d.gamestart", south_idx);
2239 }
2240
2241 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2242 /* only one was given and replaced ~> we added one new entry */
2243 set_count++;
2245 }
2246 }
2247
2248 if (count_changed) {
2250 "settings.set_count");
2251 }
2252 }
2253 }
2254
2255 {
2256 /* Turn old AI level field to a setting. */
2257 const char *level;
2258 enum ai_level lvl;
2259
2260 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2261 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2262 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2264 } else {
2266 }
2267
2268 if (!ai_level_is_valid(lvl)) {
2269 log_sg("Invalid AI level \"%s\". "
2270 "Changed to \"%s\".", level,
2273 }
2274
2275 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2276 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2277
2278 if (gamestart_valid) {
2279 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2280 set_count);
2281 }
2282
2283 set_count++;
2284 secfile_replace_int(loading->file, set_count, "settings.set_count");
2285 }
2286
2287 if (format_class != SAVEGAME_2) {
2288 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2289 /* Older savegames had a bug that got_tech_multi was not saved. */
2290 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2291 for (i = 0; i < count; i++) {
2292 bool got_tech = FALSE;
2293 int bulbs = 0;
2294 bool got_tech_multi
2296 "research.r%d.got_tech_multi", i);
2297
2299 "research.r%d.got_tech", i)
2300 && secfile_lookup_int(loading->file, &bulbs,
2301 "research.r%d.bulbs", i)) {
2303 got_tech || got_tech_multi ? bulbs : 0,
2304 "research.r%d.free_bulbs", i);
2305 }
2306 }
2307 }
2308
2309 /* Older savegames unnecessarily saved diplstate type order.
2310 * Silence "unused entry" warnings about those. */
2311 {
2313 "savefile.diplstate_type_size");
2314
2315 for (i = 0; i < dscount; i++) {
2317 "savefile.diplstate_type_vector,%d", i);
2318 }
2319 }
2320
2321 /* Add wl_max_length entries for players */
2322 {
2323 player_slots_iterate(pslot) {
2324 int plrno = player_slot_index(pslot);
2325 int ncities;
2326 int cnro;
2327 size_t wlist_max_length = 0;
2328 bool first_city;
2329
2330 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2331 continue;
2332 }
2333
2335 "player%d.got_first_city",
2336 plrno);
2337 if (first_city) {
2338 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2339 int flagcount = 0;
2340 const char **flags_sg;
2341 size_t nval;
2342
2344
2346 "player%d.flags", plrno);
2347
2348 for (i = 0; i < nval; i++) {
2351
2353 }
2354
2356 "player%d.flags", plrno);
2357
2359 }
2360
2362 "player%d.ncities", plrno);
2363
2364 for (cnro = 0; cnro < ncities; cnro++) {
2366 "player%d.c%d.wl_length",
2367 plrno, cnro);
2368
2370
2371 if (format_class == SAVEGAME_3) {
2373 "player%d.c%d.original",
2374 plrno, cnro) != plrno) {
2376 "player%d.c%d.acquire_t",
2377 plrno, cnro);
2378 } else {
2380 "player%d.c%d.acquire_t",
2381 plrno, cnro);
2382 }
2383
2385 "player%d.c%d.wlcb",
2386 plrno, cnro);
2387 }
2388 }
2389
2391 "player%d.wl_max_length", plrno);
2392
2393 if (format_class == SAVEGAME_3) {
2394 int nunits;
2395 int unro;
2396 size_t olist_max_length = 0;
2397
2399 "player%d.nunits", plrno);
2400
2401 for (unro = 0; unro < nunits; unro++) {
2403 "player%d.u%d.orders_length",
2404 plrno, unro);
2405
2407 }
2408
2410 "player%d.orders_max_length", plrno);
2411
2413 "player%d.routes_max_length", plrno);
2414 }
2415
2417 }
2418}
2419
2420/************************************************************************/
2424#ifdef FREECIV_DEV_SAVE_COMPAT
2425static void compat_load_dev(struct loaddata *loading)
2426{
2427 int game_version;
2428
2429 /* Check status and return if not OK (sg_success FALSE). */
2430 sg_check_ret();
2431
2432 log_debug("Upgrading data between development revisions");
2433
2434 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
2435 game_version = 2060000;
2436 }
2437
2438#ifdef FREECIV_DEV_SAVE_COMPAT_3_2
2439
2440 if (game_version < 3019100) {
2441 /* Before version number bump to 3.1.91 */
2442 int i;
2443 int count;
2444
2445 /* Older savegames had a bug that got_tech_multi was not saved.
2446 * Insert the entry to such savegames */
2447
2448 /* May be unsaved (e.g. scenario case). */
2449 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2450 for (i = 0; i < count; i++) {
2451 if (secfile_entry_lookup(loading->file,
2452 "research.r%d.got_tech_multi", i) == NULL) {
2453 /* Default to FALSE */
2455 "research.r%d.got_tech_multi", i);
2456 }
2457 }
2458 } /* Version < 3.1.91 */
2459
2460 if (game_version < 3019200) {
2461 /* Before version number bump to 3.1.92, August 2022 */
2462 int set_count;
2463 bool gamestart_valid = FALSE;
2464 bool al_set_already = FALSE;
2465 bool wrap_set_already = FALSE;
2466 const char *level;
2467 bool count_changed = FALSE;
2468 bool topo_defined = FALSE;
2469 char wrap[100];
2470 char wrap_gs[100];
2471
2472 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2473 int i;
2476 "settings.gamestart_valid");
2477
2478 for (i = 0; i < set_count; i++) {
2479 const char *old_name
2480 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2481 const char *name;
2482
2483 if (!old_name) {
2484 continue;
2485 }
2486
2488
2489 if (fc_strcasecmp(old_name, name)) {
2490 /* Setting's name changed */
2491 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2492 }
2493
2494 if (!fc_strcasecmp("compresstype", name)) {
2495 const char *val = secfile_lookup_str(loading->file,
2496 "settings.set%d.value", i);
2497
2498 if (!fc_strcasecmp(val, "BZIP2")) {
2499#ifdef FREECIV_HAVE_LIBZSTD
2500 secfile_replace_str(loading->file, "ZSTD",
2501 "settings.set%d.value", i);
2502#elif FREECIV_HAVE_LIBLZMA
2503 secfile_replace_str(loading->file, "XZ",
2504 "settings.set%d.value", i);
2505#elif FREECIV_HAVE_LIBZ
2506 secfile_replace_str(loading->file, "LIBZ",
2507 "settings.set%d.value", i);
2508#else
2509 secfile_replace_str(loading->file, "PLAIN",
2510 "settings.set%d.value", i);
2511#endif
2512 }
2513
2514 if (gamestart_valid) {
2515 val = secfile_lookup_str(loading->file,
2516 "settings.set%d.gamestart", i);
2517 if (!fc_strcasecmp(val, "BZIP2")) {
2518#ifdef FREECIV_HAVE_LIBZSTD
2519 secfile_replace_str(loading->file, "ZSTD",
2520 "settings.set%d.gamestart", i);
2521#elif FREECIV_HAVE_LIBLZMA
2522 secfile_replace_str(loading->file, "XZ",
2523 "settings.set%d.gamestart", i);
2524#elif FREECIV_HAVE_LIBZ
2525 secfile_replace_str(loading->file, "LIBZ",
2526 "settings.set%d.gamestart", i);
2527#else
2528 secfile_replace_str(loading->file, "PLAIN",
2529 "settings.set%d.gamestart", i);
2530#endif
2531 }
2532 }
2533 } else if (!fc_strcasecmp("ailevel", name)) {
2535 } else if (!fc_strcasecmp("topology", name)) {
2536 struct setting *pset = setting_by_name(name);
2537 struct sf_cb_data info = { pset, TRUE };
2538 int val;
2539
2540 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2542 "settings.set%d.value", i)) {
2543 bool topo_changed = TRUE;
2544
2545 if (val & TF_OLD_WRAPX) {
2546 if (val & TF_OLD_WRAPY) {
2547 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2548 } else {
2549 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2550 }
2551 } else if (val & TF_OLD_WRAPY) {
2552 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2553 } else {
2554 fc_strlcpy(wrap, "", sizeof(wrap));
2556 }
2557
2558 if (topo_changed) {
2559 char buf[100];
2560
2561 if (val & TF_ISO) {
2562 if (val & TF_HEX) {
2563 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2564 } else {
2565 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2566 }
2567 } else if (val & TF_HEX) {
2568 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2569 } else {
2571 }
2572
2573 setting_value_name(pset, FALSE, buf, sizeof(buf));
2575 "settings.set%d.value", i);
2576 }
2577
2578 if (gamestart_valid) {
2579 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2581 "settings.set%d.gamestart", i)) {
2583
2584 if (val & TF_OLD_WRAPX) {
2585 if (val & TF_OLD_WRAPY) {
2586 fc_strlcpy(wrap_gs, "WrapX|WrapY", sizeof(wrap));
2587 } else {
2588 fc_strlcpy(wrap_gs, "WrapX", sizeof(wrap));
2589 }
2590 } else if (val & TF_OLD_WRAPY) {
2591 fc_strlcpy(wrap_gs, "WrapY", sizeof(wrap));
2592 } else {
2593 fc_strlcpy(wrap_gs, "", sizeof(wrap));
2595 }
2596
2597 if (topo_changed) {
2598 char buf[100];
2599
2600 if (val & TF_ISO) {
2601 if (val & TF_HEX) {
2602 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2603 } else {
2604 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2605 }
2606 } else if (val & TF_HEX) {
2607 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2608 } else {
2610 }
2611
2612 setting_value_name(pset, FALSE, buf, sizeof(buf));
2614 "settings.set%d.gamestart", i);
2615 }
2616 }
2617 }
2618
2620 }
2621 } else if (!fc_strcasecmp("wrap", name)) {
2623 }
2624 }
2625 }
2626
2627 if (!al_set_already) {
2628 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2629 if (level == NULL) {
2630 /* Assume that this was a new format savegame after all,
2631 * setting just has not been explicitly saved for containing default value. */
2633 }
2634 }
2635
2636 if (!al_set_already) {
2637 /* Turn old AI level field to a setting. */
2638 enum ai_level lvl;
2639
2640 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2641 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2643 } else {
2645 }
2646
2647 if (!ai_level_is_valid(lvl)) {
2648 log_sg("Invalid AI level \"%s\". "
2649 "Changed to \"%s\".", level,
2652 }
2653
2654 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2655 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2656
2657 if (gamestart_valid) {
2658 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2659 set_count);
2660 }
2661
2662 set_count++;
2664 }
2665
2667 secfile_insert_str(loading->file, "wrap", "settings.set%d.name", set_count);
2668 secfile_insert_str(loading->file, wrap, "settings.set%d.value", set_count);
2669
2670 if (gamestart_valid) {
2671 secfile_insert_str(loading->file, wrap_gs, "settings.set%d.value", set_count);
2672 }
2673
2674 set_count++;
2676 }
2677
2678 if (count_changed) {
2679 secfile_replace_int(loading->file, set_count, "settings.set_count");
2680 }
2681
2682 {
2683 int action_count;
2684
2686 "savefile.action_size");
2687
2688 if (action_count > 0) {
2689 const char **modname;
2690 const char **savemod;
2691 int j;
2692 const char *dur_name = "Disband Unit Recover";
2693
2694 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2695 "savefile.action_vector");
2696
2698
2699 for (j = 0; j < action_count; j++) {
2700 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
2701 savemod[j] = dur_name;
2702 } else {
2703 savemod[j] = modname[j];
2704 }
2705 }
2706
2708 "savefile.action_vector");
2709
2710 free(savemod);
2711 }
2712 }
2713
2714 player_slots_iterate(pslot) {
2715 int plrno = player_slot_index(pslot);
2716 int wonder_city = secfile_lookup_int_default(loading->file, -1,
2717 "player%d.adv.wonder_city",
2718 plrno);
2719 if (wonder_city < 0) {
2720 /* No wonder_city saved with the new name. Check for the old name */
2721 wonder_city = secfile_lookup_int_default(loading->file, -1,
2722 "player%d.wonder_city",
2723 plrno);
2724 if (wonder_city >= 0) {
2725 secfile_replace_int(loading->file, wonder_city,
2726 "player%d.adv.wonder_city", plrno);
2727 }
2728 }
2730 } /* Version < 3.1.92 */
2731
2732 if (game_version < 3019300) {
2733 /* Before version number bump to 3.1.93 */
2734
2735 /* Older savegames unnecessarily saved diplstate type order.
2736 * Silence "unused entry" warnings about those. */
2737 {
2739 "savefile.diplstate_type_size");
2740 int i;
2741
2742 for (i = 0; i < dscount; i++) {
2744 "savefile.diplstate_type_vector,%d", i);
2745 }
2746 }
2747
2748 (void) secfile_entry_lookup(loading->file, "game.hardcoded_counters");
2749
2750 /* Add wl_max_length and orders_max_length entries for players */
2751 {
2752 player_slots_iterate(pslot) {
2753 int plrno = player_slot_index(pslot);
2754 int ncities, nunits;
2755 int cnro, unro;
2756 size_t wlist_max_length = 0;
2757 size_t olist_max_length = 0;
2758
2759 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2760 continue;
2761 }
2762
2764 "player%d.ncities", plrno);
2765
2766 for (cnro = 0; cnro < ncities; cnro++) {
2768 "player%d.c%d.wl_length",
2769 plrno, cnro);
2770
2772
2773 if (secfile_entry_lookup(loading->file,
2774 "player%d.c%d.acquire_t",
2775 plrno, cnro) == NULL) {
2777 "player%d.c%d.original",
2778 plrno, cnro) != plrno) {
2780 "player%d.c%d.acquire_t",
2781 plrno, cnro);
2782 } else {
2784 "player%d.c%d.acquire_t",
2785 plrno, cnro);
2786 }
2787 }
2788 if (secfile_entry_lookup(loading->file,
2789 "player%d.c%d.wlcb",
2790 plrno, cnro) == NULL) {
2792 "player%d.c%d.wlcb",
2793 plrno, cnro);
2794 }
2795 }
2796
2798 "player%d.wl_max_length", plrno);
2799
2801 "player%d.nunits", plrno);
2802
2803 for (unro = 0; unro < nunits; unro++) {
2804 int ol_length
2806 "player%d.u%d.orders_length",
2807 plrno, unro);
2808
2810 }
2811
2813 "player%d.orders_max_length", plrno);
2814
2816 "player%d.routes_max_length", plrno);
2818 }
2819
2820 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2821 {
2822 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2823
2824 for (int i = 0; i < count; i++) {
2825 bool got_tech = FALSE;
2826 int bulbs = 0;
2827 bool got_tech_multi
2829 "research.r%d.got_tech_multi", i);
2830
2832 "research.r%d.got_tech", i)
2833 && secfile_lookup_int(loading->file, &bulbs,
2834 "research.r%d.bulbs", i)) {
2836 got_tech || got_tech_multi ? bulbs : 0,
2837 "research.r%d.free_bulbs", i);
2838 }
2839 }
2840 }
2841
2842 /* Convert 'alltemperate' and 'singlepole' into 'northlatitude' and
2843 * 'southlatitude' server settings */
2844 {
2845 int i;
2847 "settings.set_count");
2848 int alltemperate_idx = -1, singlepole_idx = -1;
2849
2850 for (i = 0; i < set_count; i++) {
2851 const char *name
2852 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2853
2854 if (!name) {
2855 continue;
2856 }
2857
2858 if (!fc_strcasecmp("northlatitude", name)
2859 || !fc_strcasecmp("southlatitude", name)) {
2860 /* this savegame is recent enough to already have latitude
2861 * settings ~> no change necessary */
2863 break;
2864 }
2865
2866 if (!fc_strcasecmp("alltemperate", name)) {
2868 } else if (!fc_strcasecmp("singlepole", name)) {
2869 singlepole_idx = i;
2870 }
2871 }
2872
2873 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2874 int north_latitude, south_latitude;
2875 int north_idx, south_idx;
2877
2878 if (alltemperate_idx < 0
2880 "settings.set%d.value",
2882 /* infer what would've been the ruleset default */
2884 }
2885
2886 if (singlepole_idx < 0
2888 "settings.set%d.value",
2889 singlepole_idx)) {
2890 /* infer what would've been the ruleset default */
2892 }
2893
2894 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2895 * changes, that'll have to be handled in later migrations anyway */
2896 north_latitude = alltemperate ? 500 : 1000;
2897 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2898
2899 /* Replace alltemperate with northlatitude, and singlepole with
2900 * southlatitude. If only one of the two was given, add the other
2901 * at the end. */
2904
2905 secfile_replace_str(loading->file, "northlatitude",
2906 "settings.set%d.name", north_idx);
2907 secfile_replace_int(loading->file, north_latitude,
2908 "settings.set%d.value", north_idx);
2909
2910 secfile_replace_str(loading->file, "southlatitude",
2911 "settings.set%d.name", south_idx);
2912 secfile_replace_int(loading->file, south_latitude,
2913 "settings.set%d.value", south_idx);
2914
2916 "settings.gamestart_valid")) {
2917 if (alltemperate_idx < 0
2919 "settings.set%d.gamestart",
2921 alltemperate =
2923 }
2924
2925 if (singlepole_idx < 0
2927 "settings.set%d.gamestart",
2928 singlepole_idx)) {
2930 }
2931
2932 north_latitude = alltemperate ? 500 : 1000;
2933 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2934
2935 secfile_replace_int(loading->file, north_latitude,
2936 "settings.set%d.gamestart", north_idx);
2937 secfile_replace_int(loading->file, south_latitude,
2938 "settings.set%d.gamestart", south_idx);
2939 }
2940
2941 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2942 /* only one was given and replaced ~> we added one new entry */
2943 set_count++;
2945 "settings.set_count");
2946 }
2947 }
2948 }
2949
2950 {
2951 int action_count;
2952
2954 "savefile.action_size");
2955
2956 if (action_count > 0) {
2957 const char **modname;
2958 const char **savemod;
2959 int j;
2960 const char *dur_name = "Transport Deboard";
2961
2962 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2963 "savefile.action_vector");
2964
2966
2967 for (j = 0; j < action_count; j++) {
2968 if (!fc_strcasecmp("Transport Alight", modname[j])) {
2969 savemod[j] = dur_name;
2970 } else {
2971 savemod[j] = modname[j];
2972 }
2973 }
2974
2976 "savefile.action_vector");
2977
2978 free(savemod);
2979 }
2980 }
2981
2982 {
2983 const char *str = secfile_lookup_str_default(loading->file, NULL,
2984 "savefile.orig_version");
2985
2986 if (str == NULL) {
2987 /* Make sure CURRENTLY running version does not
2988 * end as orig_version when we resave. */
2989 secfile_insert_str(loading->file, "old savegame3, or older",
2990 "savefile.orig_version");
2991 }
2992 }
2993
2994 } /* Version < 3.1.93 */
2995
2996 if (game_version < 3019400) {
2997 /* Before version number bump to 3.1.94, January 2024 */
2998
2999 {
3000 int action_count;
3001
3003 "savefile.action_size");
3004
3005 if (action_count > 0) {
3006 const char **modname;
3007 const char **savemod;
3008 int j;
3009 const char *clean_name = "Clean";
3010
3011 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3012 "savefile.action_vector");
3013
3015
3016 for (j = 0; j < action_count; j++) {
3017 if (!fc_strcasecmp("Clean Pollution", modname[j])
3018 || !fc_strcasecmp("Clean Fallout", modname[j])) {
3019 savemod[j] = clean_name;
3020 } else {
3021 savemod[j] = modname[j];
3022 }
3023 }
3024
3026 "savefile.action_vector");
3027
3028 free(savemod);
3029 }
3030 }
3031
3032 {
3033 int activities_count;
3034
3036 "savefile.activities_size");
3037
3038 if (activities_count > 0) {
3039 const char **modname;
3040 const char **savemod;
3041 int j;
3042 const char *clean_name = "Clean";
3043
3044 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
3045 "savefile.activities_vector");
3046
3048
3049 for (j = 0; j < activities_count; j++) {
3050 if (!fc_strcasecmp("Pollution", modname[j])
3051 || !fc_strcasecmp("Fallout", modname[j])) {
3052 savemod[j] = clean_name;
3053 } else {
3054 savemod[j] = modname[j];
3055 }
3056 }
3057
3059 "savefile.activities_vector");
3060
3061 free(savemod);
3062 }
3063 }
3064
3065 /* Server setting migration. */
3066 {
3067 int set_count;
3068
3069 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
3070 bool gamestart_valid = FALSE;
3071
3074 "settings.gamestart_valid");
3075
3076 if (!gamestart_valid) {
3077 int i;
3078
3079 /* Older savegames saved gamestart values even when they were not valid.
3080 * Silence warnings caused by them. */
3081 for (i = 0; i < set_count; i++) {
3082 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
3083 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
3084 }
3085 }
3086 }
3087 }
3088
3089 {
3090 player_slots_iterate(pslot) {
3091 int plrno = player_slot_index(pslot);
3092 bool first_city;
3093
3094 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
3095 continue;
3096 }
3097
3099 "player%d.got_first_city",
3100 plrno);
3101
3102 if (first_city) {
3103 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
3104 int flagcount = 0;
3105 const char **flags_sg;
3106 size_t nval;
3107 int i;
3108
3110
3112 "player%d.flags", plrno);
3113
3114 for (i = 0; i < nval; i++) {
3117
3119 }
3120
3122 "player%d.flags", plrno);
3123
3125 }
3127 }
3128
3129 } /* Version < 3.1.94 */
3130
3131 if (game_version < 3019500) {
3132 /* Before version number bump to 3.1.95 */
3133
3134 } /* Version < 3.1.95 */
3135
3136#endif /* FREECIV_DEV_SAVE_COMPAT_3_2 */
3137}
3138
3139/************************************************************************/
3143static void compat_post_load_dev(struct loaddata *loading)
3144{
3145 int game_version;
3146
3147 /* Check status and return if not OK (sg_success FALSE). */
3148 sg_check_ret();
3149
3150 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
3151 game_version = 2060000;
3152 }
3153
3154#ifdef FREECIV_DEV_SAVE_COMPAT_3_2
3155
3156 if (game_version < 3019100) {
3157 /* Before version number bump to 3.1.91 */
3158
3159 } /* Version < 3.1.91 */
3160
3161#endif /* FREECIV_DEV_SAVE_COMPAT_3_2 */
3162}
3163#endif /* FREECIV_DEV_SAVE_COMPAT */
3164
3165/************************************************************************/
3168enum ai_level ai_level_convert(int old_level)
3169{
3170 switch (old_level) {
3171 case 1:
3172 return AI_LEVEL_AWAY;
3173 case 2:
3174 return AI_LEVEL_NOVICE;
3175 case 3:
3176 return AI_LEVEL_EASY;
3177 case 5:
3178 return AI_LEVEL_NORMAL;
3179 case 7:
3180 return AI_LEVEL_HARD;
3181 case 8:
3182 return AI_LEVEL_CHEATING;
3183 case 10:
3184#ifdef FREECIV_DEBUG
3185 return AI_LEVEL_EXPERIMENTAL;
3186#else /* FREECIV_DEBUG */
3187 return AI_LEVEL_HARD;
3188#endif /* FREECIV_DEBUG */
3189 }
3190
3191 return ai_level_invalid();
3192}
3193
3194/************************************************************************/
3197enum barbarian_type barb_type_convert(int old_type)
3198{
3199 switch (old_type) {
3200 case 0:
3201 return NOT_A_BARBARIAN;
3202 case 1:
3203 return LAND_BARBARIAN;
3204 case 2:
3205 return SEA_BARBARIAN;
3206 }
3207
3208 return barbarian_type_invalid();
3209}
int action_number(const struct action *action)
Definition actions.c:1960
static struct action * action_by_number(action_id act_id)
Definition actions.h:633
#define action_iterate_end
Definition actions.h:463
#define action_get_activity(_pact_)
Definition actions.h:697
#define action_iterate(_act_)
Definition actions.h:459
struct @126::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:266
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:77
char * incite_cost
Definition comments.c:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define NO_TARGET
Definition fc_types.h:357
#define EC_SPECIAL
Definition fc_types.h:1115
revolen_type
Definition fc_types.h:1283
@ REVOLEN_RANDOM
Definition fc_types.h:1285
@ REVOLEN_RANDQUICK
Definition fc_types.h:1287
@ REVOLEN_FIXED
Definition fc_types.h:1284
@ REVOLEN_QUICKENING
Definition fc_types.h:1286
#define DIR8_ORIGIN
Definition fc_types.h:460
#define _(String)
Definition fcintl.h:67
struct world wld
Definition game.c:63
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:734
#define GAME_DEFAULT_SCORETURN
Definition game.h:578
#define GAME_DEFAULT_SAVETURNS
Definition game.h:676
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:562
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:694
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:371
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c:131
int len
Definition packhand.c:127
int player_slot_count(void)
Definition player.c:418
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
#define ANON_USER_NAME
Definition player.h:48
#define player_slots_iterate(_pslot)
Definition player.h:523
#define players_iterate_alive_end
Definition player.h:547
#define player_slots_iterate_end
Definition player.h:527
#define players_iterate_alive(_pplayer)
Definition player.h:542
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
bool secfile_entry_delete(struct section_file *secfile, const char *path,...)
bool entry_set_name(struct entry *pentry, const char *name)
bool secfile_lookup_enum_data(const struct section_file *secfile, int *pvalue, bool bitwise, secfile_enum_name_data_fn_t name_fn, secfile_data_t data, const char *path,...)
const struct entry_list * section_entries(const struct section *psection)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct section * secfile_section_by_name(const struct section_file *secfile, const char *name)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_replace_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
entry_type
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_replace_int(secfile, value, path,...)
#define entry_list_iterate_end
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define entry_list_iterate(entlist, pentry)
#define secfile_replace_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
struct extra_type * resource_by_identifier(const char identifier)
Definition savecompat.c:323
int current_compat_ver(void)
Definition savecompat.c:222
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:262
bool sg_success
Definition savecompat.c:34
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:560
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:36
static struct compatibility compat[]
Definition savecompat.c:110
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:341
static void upgrade_unit_order_targets(struct unit *act_unit)
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:232
static const int compat_num
Definition savecompat.c:133
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:703
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:90
int char2num(char ch)
Definition savecompat.c:268
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:143
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:684
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:244
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:309
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:577
static void compat_load_030200(struct loaddata *loading, enum sgf_version format_class)
enum tile_special_type special_by_rule_name(const char *name)
Definition savecompat.c:283
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:194
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:299
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:134
#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:3299
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4257
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4213
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:4055
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
Specialist_type_id specialist_count(void)
Definition specialist.c:71
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
int north_latitude
Definition map_types.h:79
int south_latitude
Definition map_types.h:80
struct civ_map::@42::@44 server
int huts_absolute
Definition map_types.h:95
const load_version_func_t post_load
Definition savecompat.c:95
const load_version_func_t load
Definition savecompat.c:94
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:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:138
int length
Definition unit.h:195
bool has_orders
Definition unit.h:193
struct unit::@80 orders
enum unit_activity activity
Definition unit.h:157
struct extra_type * activity_target
Definition unit.h:164
struct unit_order * list
Definition unit.h:198
enum server_side_agent ssa_controller
Definition unit.h:172
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
#define sz_strlcpy(dest, src)
Definition support.h:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:190
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:154
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
#define terrain_type_iterate(_p)
Definition terrain.h:373
#define terrain_type_iterate_end
Definition terrain.h:379
void free_unit_orders(struct unit *punit)
Definition unit.c:1765
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:361
bool unit_has_orders(const struct unit *punit)
Definition unit.c:205
#define unit_tile(_pu)
Definition unit.h:390
@ 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, struct extra_type **target)
Definition unittools.c:1082
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1249
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1288