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
86
92
93/* The struct below contains the information about the savegame versions. It
94 * is identified by the version number (first element), which should be
95 * steadily increasing. It is saved as 'savefile.version'. The support
96 * string (first element of 'name') is not saved in the savegame; it is
97 * saved in settings files (so, once assigned, cannot be changed). The
98 * 'pretty' string (second element of 'name') can be changed if necessary
99 * For changes in the development version, edit the definitions above and
100 * add the needed code to load the old version below. Thus, old
101 * savegames can still be loaded while the main definition
102 * represents the current state of the art. */
103/* While developing freeciv 3.2.0, add the compatibility functions to
104 * - compat_load_030200 to load old savegame. */
105static struct compatibility compat[] = {
106 /* dummy; equal to the current version (last element) */
107 { 0, NULL, NULL },
108 /* version 1 and 2 is not used */
109 /* version 3: first savegame2 format, so no compat functions for translation
110 * from previous format */
111 { 3, NULL, NULL },
112 /* version 4 to 9 are reserved for possible changes in 2.3.x */
113 { 10, compat_load_020400, NULL },
114 /* version 11 to 19 are reserved for possible changes in 2.4.x */
115 { 20, compat_load_020500, NULL },
116 /* version 21 to 29 are reserved for possible changes in 2.5.x */
117 { 30, compat_load_020600, NULL },
118 /* version 31 to 39 are reserved for possible changes in 2.6.x */
119 { 40, compat_load_030000, NULL },
120 /* version 41 to 49 are reserved for possible changes in 3.0.x */
122 /* version 51 to 59 are reserved for possible changes in 3.1.x */
123 { 60, compat_load_030200, NULL },
124 /* Current savefile version is listed above this line; it corresponds to
125 the definitions in this file. */
126};
127
128static const int compat_num = ARRAY_SIZE(compat);
129#define compat_current (compat_num - 1)
130
131/************************************************************************/
139{
140 int i;
141
142 /* Check status and return if not OK (sg_success FALSE). */
143 sg_check_ret();
144
145 loading->version = secfile_lookup_int_default(loading->file, -1,
146 "savefile.version");
147#ifdef FREECIV_DEBUG
148 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
149 loading->version);
150 if (loading->version > compat[compat_current].version) {
151 /* Debug build can (TRY TO!) load newer versions but ... */
152 log_error("Savegame version newer than this build found (%d > %d). "
153 "Trying to load the game nevertheless ...", loading->version,
155 }
156#else /* FREECIV_DEBUG */
157 sg_failure_ret(0 < loading->version
158 && loading->version <= compat[compat_current].version,
159 "Unknown savefile format version (%d).", loading->version);
160#endif /* FREECIV_DEBUG */
161
162
163 for (i = 0; i < compat_num; i++) {
164 if (loading->version < compat[i].version && compat[i].load != NULL) {
165 log_normal(_("Run compatibility function for version: <%d "
166 "(save file: %d; server: %d)."), compat[i].version,
169 }
170 }
171}
172
173/************************************************************************/
185{
186 int i;
187
188 /* Check status and return if not OK (sg_success FALSE). */
189 sg_check_ret();
190
191 for (i = 0; i < compat_num; i++) {
192 if (loading->version < compat[i].version
193 && compat[i].post_load != NULL) {
194 log_normal(_("Run post load compatibility function for version: <%d "
195 "(save file: %d; server: %d)."), compat[i].version,
198 }
199 }
200}
201
202/************************************************************************/
206{
208}
209
210/************************************************************************/
215char bin2ascii_hex(int value, int halfbyte_wanted)
216{
217 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
218}
219
220/************************************************************************/
228{
229 const char *pch;
230
231 if (ch == ' ') {
232 /* Sane value. It is unknown if there are savegames out there which
233 * need this fix. Savegame.c doesn't write such savegames
234 * (anymore) since the inclusion into CVS (2000-08-25). */
235 return 0;
236 }
237
239
240 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
241 "Unknown hex value: '%c' %d", ch, ch);
242 return (pch - hex_chars) << (halfbyte * 4);
243}
244
245static const char num_chars[] =
246 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
247
248/************************************************************************/
251int char2num(char ch)
252{
253 const char *pch;
254
256
258 "Unknown ascii value for num: '%c' %d", ch, ch);
259
260 return pch - num_chars;
261}
262
263/************************************************************************/
267{
268 int i;
269
270 for (i = 0; special_names[i] != NULL; i++) {
271 if (!strcmp(name, special_names[i])) {
272 return i;
273 }
274 }
275
276 return S_LAST;
277}
278
279/************************************************************************/
283{
284 fc_assert(type >= 0 && type < S_LAST);
285
286 return special_names[type];
287}
288
289/************************************************************************/
293{
295
298 }
299
300 return NULL;
301}
302
303/************************************************************************/
306struct extra_type *resource_by_identifier(const char identifier)
307{
309 if (presource->data.resource->id_old_save == identifier) {
310 return presource;
311 }
313
314 return NULL;
315}
316
317/* =======================================================================
318 * Compatibility functions for loading a game.
319 * ======================================================================= */
320
321/************************************************************************/
326{
327 /* Check status and return if not OK (sg_success FALSE). */
328 sg_check_ret();
329
330 log_debug("Upgrading data from savegame to version 2.4.0");
331
332 /* Add the default player AI. */
333 player_slots_iterate(pslot) {
334 int ncities, i, plrno = player_slot_index(pslot);
335
336 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
337 continue;
338 }
339
341 "player%d.ai_type", player_slot_index(pslot));
342
343 /* Create dummy citizens information. We do not know if citizens are
344 * activated due to the fact that this information
345 * (game.info.citizen_nationality) is not available, but adding the
346 * information does no harm. */
348 "player%d.ncities", plrno);
349 if (ncities > 0) {
350 for (i = 0; i < ncities; i++) {
352 "player%d.c%d.size", plrno, i);
353 if (size > 0) {
355 "player%d.c%d.citizen%d", plrno, i, plrno);
356 }
357 }
358 }
359
361
362 /* Player colors are assigned at the end of player loading, as this
363 * needs information not available here. */
364
365 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
366 * workaround in later 2.3.x); see gna bug #19029.
367 * (The structure of this code is odd as it avoids relying on knowledge of
368 * xsize/ysize, which haven't been extracted from the savefile yet.) */
369 {
370 if (has_capability("knownv2",
371 secfile_lookup_str(loading->file, "savefile.options"))) {
372 /* This savefile contains known information in a sane format.
373 * Just move any entries to where 2.4.x+ expect to find them. */
374 struct section *map = secfile_section_by_name(loading->file, "map");
375
376 if (map != NULL) {
378 const char *name = entry_name(pentry);
379
380 if (!fc_strncmp(name, "kvb", 3)) {
381 /* Rename the "kvb..." entry to "k..." */
382 char *name2 = fc_strdup(name), *newname = name2 + 2;
383
384 *newname = 'k';
385 /* Savefile probably contains existing "k" entries, which are bogus
386 * so we trash them. */
387 secfile_entry_delete(loading->file, "map.%s", newname);
389 FC_FREE(name2);
390 }
392 }
393 /* Could remove "knownv2" from savefile.options, but it's doing
394 * no harm there. */
395 } else {
396 /* This savefile only contains known information in the broken
397 * format. Try to recover it to a sane format. */
398 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
399 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
400 const int maxslots = 128, maxmapsize = 512;
401 const int lines = maxslots/32;
402 int xsize = 0, y, l, j, x;
403 unsigned int known_row_old[lines * maxmapsize],
405 /* Process a map row at a time */
406 for (y = 0; y < maxmapsize; y++) {
407 /* Look for broken info to convert */
408 bool found = FALSE;
410 for (l = 0; l < lines; l++) {
411 for (j = 0; j < 8; j++) {
412 const char *s =
414 "map.k%02d_%04d", l * 8 + j, y);
415 if (s) {
416 found = TRUE;
417 if (xsize == 0) {
418 xsize = strlen(s);
419 }
420 sg_failure_ret(xsize == strlen(s),
421 "Inconsistent xsize in map.k%02d_%04d",
422 l * 8 + j, y);
423 for (x = 0; x < xsize; x++) {
424 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
425 }
426 }
427 }
428 }
429 if (found) {
430 /* At least one entry found for this row. Let's hope they were
431 * all there. */
432 /* Attempt to munge into sane format */
433 int p;
434 memset(known_row, 0, sizeof(known_row));
435 /* Iterate over possible player slots */
436 for (p = 0; p < maxslots; p++) {
437 l = p / 32;
438 for (x = 0; x < xsize; x++) {
439 /* This test causes bit-shifts of >=32 (undefined behaviour), but
440 * on common platforms, information happens not to be lost, just
441 * oddly arranged. */
442 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
443 known_row[l * xsize + x] |= (1u << (p - l * 32));
444 }
445 }
446 }
447 /* Save sane format back to memory representation of secfile for
448 * real loading code to pick up */
449 for (l = 0; l < lines; l++) {
450 for (j = 0; j < 8; j++) {
451 /* Save info for all slots (not just used ones). It's only
452 * memory, after all. */
453 char row[xsize+1];
454 for (x = 0; x < xsize; x++) {
455 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
456 }
457 row[xsize] = '\0';
459 "map.k%02d_%04d", l * 8 + j, y);
460 }
461 }
462 }
463 }
464 }
465 }
466
467 /* Server setting migration. */
468 {
469 int set_count;
470
471 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
472 int i, new_opt = set_count;
473 bool gamestart_valid
475 "settings.gamestart_valid");
476
477 for (i = 0; i < set_count; i++) {
478 const char *name
479 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
480
481 if (!name) {
482 continue;
483 }
484
485 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
486 * This is now controlled by the "autosaves" setting. */
487 if (!fc_strcasecmp("saveturns", name)) {
488 /* XXX: hardcodes details from GAME_AUTOSAVES_DEFAULT
489 * and settings.c:autosaves_name() (but these defaults reflect
490 * 2.3's behaviour). */
491 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
492 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
493 int nturns;
494
496 "settings.set%d.value", i)) {
497 if (nturns == 0) {
498 /* Invent a new "autosaves" setting */
500 "settings.set%d.value", new_opt);
501 /* Pick something valid for saveturns */
503 "settings.set%d.value", i);
504 } else {
506 "settings.set%d.value", new_opt);
507 }
508 } else {
509 log_sg("Setting '%s': %s", name, secfile_error());
510 }
511 if (gamestart_valid) {
513 "settings.set%d.gamestart", i)) {
514 if (nturns == 0) {
515 /* Invent a new "autosaves" setting */
517 "settings.set%d.gamestart", new_opt);
518 /* Pick something valid for saveturns */
520 "settings.set%d.gamestart", i);
521 } else {
523 "settings.set%d.gamestart", new_opt);
524 }
525 } else {
526 log_sg("Setting '%s': %s", name, secfile_error());
527 }
528 }
529 } else if (!fc_strcasecmp("autosaves", name)) {
530 /* Sanity check. This won't trigger on an option we've just
531 * invented, as the loop won't include it. */
532 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
533 "savefile. It may have been overridden.");
534 }
535 }
536 }
537 }
538}
539
540/************************************************************************/
543static const char *killcitizen_enum_str(secfile_data_t data, int bit)
544{
545 switch (bit) {
546 case UMT_LAND:
547 return "LAND";
548 case UMT_SEA:
549 return "SEA";
550 case UMT_BOTH:
551 return "BOTH";
552 }
553
554 return NULL;
555}
556
557/************************************************************************/
562{
563 const char *modname[] = { "Road", "Railroad" };
564 const char *old_activities_names[] = {
565 "Idle",
566 "Pollution",
567 "Unused Road",
568 "Mine",
569 "Irrigate",
570 "Mine",
571 "Irrigate",
572 "Fortified",
573 "Fortress",
574 "Sentry",
575 "Unused Railroad",
576 "Pillage",
577 "Goto",
578 "Explore",
579 "Transform",
580 "Unused",
581 "Unused Airbase",
582 "Fortifying",
583 "Fallout",
584 "Unused Patrol",
585 "Base"
586 };
587
588 /* Check status and return if not OK (sg_success FALSE). */
589 sg_check_ret();
590
591 log_debug("Upgrading data from savegame to version 2.5.0");
592
593 secfile_insert_int(loading->file, 2, "savefile.roads_size");
594 secfile_insert_int(loading->file, 0, "savefile.trait_size");
595
597 "savefile.roads_vector");
598
599 secfile_insert_int(loading->file, 19, "savefile.activities_size");
601 "savefile.activities_vector");
602
603 /* Server setting migration. */
604 {
605 int set_count;
606
607 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
608 int i;
609 bool gamestart_valid
611 "settings.gamestart_valid");
612 for (i = 0; i < set_count; i++) {
613 const char *name
614 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
615 if (!name) {
616 continue;
617 }
618 /* In 2.4.x and prior, "killcitizen" listed move types that
619 * killed citizens after successful attack. Now killcitizen
620 * is just boolean and classes affected are defined in ruleset. */
621 if (!fc_strcasecmp("killcitizen", name)) {
622 int value;
623
624 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
626 "settings.set%d.value", i)) {
627 /* Lowest bit of old killcitizen value indicates if
628 * land units should kill citizens. We take that as
629 * new boolean killcitizen value. */
630 if (value & 0x1) {
632 "settings.set%d.value", i);
633 } else {
635 "settings.set%d.value", i);
636 }
637 } else {
638 log_sg("Setting '%s': %s", name, secfile_error());
639 }
640 if (gamestart_valid) {
641 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
643 "settings.set%d.gamestart", 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.gamestart", i);
650 } else {
652 "settings.set%d.gamestart", i);
653 }
654 } else {
655 log_sg("Setting '%s': %s", name, secfile_error());
656 }
657 }
658 }
659 }
660 }
661 }
662}
663
664/************************************************************************/
668{
669 switch (type) {
670 case REVOLEN_FIXED:
671 return "FIXED";
672 case REVOLEN_RANDOM:
673 return "RANDOM";
675 return "QUICKENING";
677 return "RANDQUICK";
678 }
679
680 return "";
681}
682
683/************************************************************************/
688{
689 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
690 int tsize;
691 int ti;
692 int turn;
693
694 /* Check status and return if not OK (sg_success FALSE). */
695 sg_check_ret();
696
697 log_debug("Upgrading data from savegame to version 2.6.0");
698
699 /* Terrain mapping table - use current ruleset as we have no way to know
700 * any other old values. */
701 ti = 0;
703 char buf[2];
704
705 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
707 buf[1] = '\0';
708 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
710
711 /* Server setting migration. */
712 {
713 int set_count;
714
715 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
716 char value_buffer[1024] = "";
717 char gamestart_buffer[1024] = "";
718 int i;
719 int dcost = -1;
720 int dstartcost = -1;
723 bool gamestart_valid
725 "settings.gamestart_valid");
726 int new_set_count;
727
728 for (i = 0; i < set_count; i++) {
729 const char *name
730 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
731 if (!name) {
732 continue;
733 }
734
735 /* In 2.5.x and prior, "spacerace" boolean controlled if
736 * spacerace victory condition was active. */
737 if (!fc_strcasecmp("spacerace", name)) {
738 bool value;
739
740 if (secfile_lookup_bool(loading->file, &value,
741 "settings.set%d.value", i)) {
742 if (value) {
743 if (value_buffer[0] != '\0') {
745 }
746 sz_strlcat(value_buffer, "SPACERACE");
747 }
748 } else {
749 log_sg("Setting '%s': %s", name, secfile_error());
750 }
751 if (secfile_lookup_bool(loading->file, &value,
752 "settings.set%d.gamestart", i)) {
753 if (value) {
754 if (gamestart_buffer[0] != '\0') {
756 }
757 sz_strlcat(gamestart_buffer, "SPACERACE");
758 }
759 } else {
760 log_sg("Setting '%s': %s", name, secfile_error());
761 }
762
763 /* We cannot delete old values from the secfile, or rather cannot
764 * change index of the later settings. Renumbering them is not easy as
765 * we don't know type of each setting we would encounter.
766 * So we keep old setting values and only add new "victories" setting. */
767 } else if (!fc_strcasecmp("alliedvictory", name)) {
768 bool value;
769
770 if (secfile_lookup_bool(loading->file, &value,
771 "settings.set%d.value", i)) {
772 if (value) {
773 if (value_buffer[0] != '\0') {
775 }
776 sz_strlcat(value_buffer, "ALLIED");
777 }
778 } else {
779 log_sg("Setting '%s': %s", name, secfile_error());
780 }
781 if (secfile_lookup_bool(loading->file, &value,
782 "settings.set%d.gamestart", i)) {
783 if (value) {
784 if (gamestart_buffer[0] != '\0') {
786 }
787 sz_strlcat(gamestart_buffer, "ALLIED");
788 }
789 } else {
790 log_sg("Setting '%s': %s", name, secfile_error());
791 }
792 } else if (!fc_strcasecmp("revolen", name)) {
793 int value;
794
795 if (secfile_lookup_int(loading->file, &value,
796 "settings.set%d.value", i)) {
797 /* 0 meant RANDOM 1-5 */
798 if (value == 0) {
801 "settings.set%d.value", i);
802 } else {
804 }
805 } else {
806 log_sg("Setting '%s': %s", name, secfile_error());
807 }
808 if (secfile_lookup_int(loading->file, &value,
809 "settings.set%d.gamestart", i)) {
810 /* 0 meant RANDOM 1-5 */
811 if (value == 0) {
814 "settings.set%d.gamestart", i);
815 } else {
817 }
818 } else {
819 log_sg("Setting '%s': %s", name, secfile_error());
820 }
821 } else if (!fc_strcasecmp("happyborders", name)) {
822 bool value;
823
824 if (secfile_lookup_bool(loading->file, &value,
825 "settings.set%d.value", i)) {
826 secfile_entry_delete(loading->file, "settings.set%d.value", i);
827 if (value) {
828 secfile_insert_str(loading->file, "NATIONAL",
829 "settings.set%d.value", i);
830 } else {
831 secfile_insert_str(loading->file, "DISABLED",
832 "settings.set%d.value", i);
833 }
834 } else {
835 log_sg("Setting '%s': %s", name, secfile_error());
836 }
837 if (secfile_lookup_bool(loading->file, &value,
838 "settings.set%d.gamestart", i)) {
839 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
840 if (value) {
841 secfile_insert_str(loading->file, "NATIONAL",
842 "settings.set%d.gamestart", i);
843 } else {
844 secfile_insert_str(loading->file, "DISABLED",
845 "settings.set%d.gamestart", i);
846 }
847 } else {
848 log_sg("Setting '%s': %s", name, secfile_error());
849 }
850 } else if (!fc_strcasecmp("team_pooled_research", name)) {
852 &team_pooled_research,
853 "settings.set%d.value", i),
854 "%s", secfile_error());
855 } else if (!fc_strcasecmp("diplcost", name)) {
856 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
857 if (secfile_lookup_int(loading->file, &dcost,
858 "settings.set%d.value", i)) {
859 } else {
860 log_sg("Setting '%s': %s", name, secfile_error());
861 }
862
864 "settings.set%d.gamestart", i)) {
865 } else {
866 log_sg("Setting '%s': %s", name, secfile_error());
867 }
868 } else if (!fc_strcasecmp("huts", name)) {
869 /* Scale of 'huts' changed. */
870 int hcount;
871
873 "settings.set%d.value", i)) {
874 } else {
875 log_sg("Setting '%s': %s", name, secfile_error());
876 }
877
878 /* Store old-style absolute value. */
880 }
881 }
882
883 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
884
885 if (dcost >= 0) {
886 new_set_count += 2;
887 }
888
889 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
890
891 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
892 set_count);
893 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
894 set_count);
895 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
896 set_count + 1);
897 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
898 set_count + 1);
899
900 if (dcost >= 0) {
901 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
902 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
903 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
904 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
905 }
906
907 if (gamestart_valid) {
908 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
909 set_count);
910 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
911 set_count + 1);
912
913 if (dcost >= 0) {
914 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
915 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
916 }
917 }
918 }
919 }
920
921 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
922 "Trait size: %s", secfile_error());
923
924 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
925
926 player_slots_iterate(pslot) {
927 int plrno = player_slot_index(pslot);
928 bool got_first_city;
929 int old_barb_type;
930 enum barbarian_type new_barb_type;
931 int i;
932 const char *name;
933 int score;
934 int units_num;
935
936 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
937 continue;
938 }
939
940 /* Renamed 'capital' to 'got_first_city'. */
942 "player%d.capital", plrno)) {
944 "player%d.got_first_city", plrno);
945 }
946
947 /* Add 'anonymous' qualifiers for user names */
948 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
950 "player%d.unassigned_user", plrno);
951
952 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
954 "player%d.unassigned_ranked", plrno);
955
956 /* Convert numeric barbarian type to textual */
958 "player%d.ai.is_barbarian", plrno);
961 "player%d.ai.barb_type", plrno);
962
963 /* Pre-2.6 didn't record when a player was created or died, so we have
964 * to assume they lived from the start of the game until last turn */
965 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
966
967 /* As if there never has been a war. */
968 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
969
970 /* Assume people were playing until current reload */
971 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
972
973 for (i = 0; i < tsize; i++) {
974 int val;
975
976 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
977 plrno, i);
978 if (val != -1) {
979 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
980 }
981
983 "player%d.trait.mod%d", plrno, i),
984 "Trait mod: %s", secfile_error());
985 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
986 }
987
988 score = secfile_lookup_int_default(loading->file, -1,
989 "player%d.units_built", plrno);
990 if (score >= 0) {
991 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
992 }
993
994 score = secfile_lookup_int_default(loading->file, -1,
995 "player%d.units_killed", plrno);
996 if (score >= 0) {
997 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
998 }
999
1000 score = secfile_lookup_int_default(loading->file, -1,
1001 "player%d.units_lost", plrno);
1002 if (score >= 0) {
1003 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1004 }
1005
1006 /* Units orders. */
1008 "player%d.nunits",
1009 plrno);
1010
1011 for (i = 0; i < units_num; i++) {
1012 int len;
1013
1015 "player%d.u%d.orders_last_move_safe",
1016 plrno, i)) {
1017 continue;
1018 }
1019
1021 "player%d.u%d.orders_length",
1022 plrno, i);
1023 if (len > 0) {
1024 char orders_str[len + 1];
1025 char *p;
1026
1029 "player%d.u%d.orders_list",
1030 plrno, i));
1031 if ((p = strrchr(orders_str, 'm'))
1032 || (p = strrchr(orders_str, 'M'))) {
1033 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1035 "player%d.u%d.orders_list", plrno, i);
1036 }
1037 }
1038 }
1040
1041 /* Add specialist order - loading time order is ok here, as we will use
1042 * that when we in later part of compatibility conversion use the specialist
1043 * values */
1045 "savefile.specialists_size");
1046 {
1047 const char **modname;
1048 int i = 0;
1049
1051
1055
1057 "savefile.specialists_vector");
1058
1059 free(modname);
1060 }
1061
1062 /* Replace all city specialist count fields with correct names */
1063 player_slots_iterate(pslot) {
1064 int plrno = player_slot_index(pslot);
1065 int ncities;
1066 int i;
1067
1068 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1069 continue;
1070 }
1071
1072 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1073
1074 for (i = 0; i < ncities; i++) {
1075 int k = 0;
1076
1078 struct specialist *psp = specialist_by_number(sp);
1079 int count;
1080
1082 "player%d.c%d.n%s",
1084 "specialist error: %s", secfile_error());
1085 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1087 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1088 plrno, i, k++);
1090 }
1092
1093 /* Build [research]. */
1094 {
1095 const struct {
1096 const char *name;
1097 enum entry_type type;
1098 } entries[] = {
1099 { "goal_name", ENTRY_STR },
1100 { "techs", ENTRY_INT },
1101 { "futuretech", ENTRY_INT },
1102 { "bulbs_before", ENTRY_INT },
1103 { "saved_name", ENTRY_STR },
1104 { "bulbs", ENTRY_INT },
1105 { "now_name", ENTRY_STR },
1106 { "got_tech", ENTRY_BOOL },
1107 { "done", ENTRY_STR }
1108 };
1109
1111 int count = 0;
1112 int i;
1113
1114 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1115 researches[i] = -1;
1116 }
1117
1118 player_slots_iterate(pslot) {
1119 int plrno = player_slot_index(pslot);
1120 int ival;
1121 bool bval;
1122 const char *sval;
1123 int j;
1124
1125 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1126 continue;
1127 }
1128
1129 /* Get the research number. */
1130 if (team_pooled_research) {
1132 "player%d.team_no", plrno);
1133 } else {
1134 i = plrno;
1135 }
1136
1138 "Research out of bounds (%d)!", i);
1139
1140 /* Find the index in [research] section. */
1141 if (researches[i] == -1) {
1142 /* This is the first player for this research. */
1143 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1144 researches[i] = count;
1145 count++;
1146 }
1147 i = researches[i];
1148
1149 /* Move entries. */
1150 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1151 switch (entries[j].type) {
1152 case ENTRY_BOOL:
1153 if (secfile_lookup_bool(loading->file, &bval,
1154 "player%d.research.%s",
1155 plrno, entries[j].name)) {
1156 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1157 i, entries[j].name);
1158 }
1159 break;
1160 case ENTRY_INT:
1161 if (secfile_lookup_int(loading->file, &ival,
1162 "player%d.research.%s",
1163 plrno, entries[j].name)) {
1164 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1165 i, entries[j].name);
1166 }
1167 break;
1168 case ENTRY_STR:
1169 if ((sval = secfile_lookup_str(loading->file,
1170 "player%d.research.%s",
1171 plrno, entries[j].name))) {
1172 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1173 i, entries[j].name);
1174 }
1175 break;
1176 case ENTRY_FLOAT:
1178 "Research related entry marked as float.");
1179 break;
1182 break;
1183 case ENTRY_LONG_COMMENT:
1185 break;
1186 case ENTRY_ILLEGAL:
1188 break;
1189 }
1190 }
1192 secfile_insert_int(loading->file, count, "research.count");
1193 }
1194
1195 /* Add diplstate type order. */
1197 "savefile.diplstate_type_size");
1198 if (DS_LAST > 0) {
1199 const char **modname;
1200 int i;
1201 int j;
1202
1203 i = 0;
1204 modname = fc_calloc(DS_LAST, sizeof(*modname));
1205
1206 for (j = 0; j < DS_LAST; j++) {
1208 }
1209
1211 DS_LAST,
1212 "savefile.diplstate_type_vector");
1213 free(modname);
1214 }
1215
1216 /* Fix save games from Freeciv versions with a bug that made it view
1217 * "Never met" as closer than "Peace" or "Alliance". */
1218 player_slots_iterate(pslot) {
1219 int plrno = player_slot_index(pslot);
1220
1221 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1222 continue;
1223 }
1224
1226 int i = player_slot_index(pslot2);
1227 char buf[32];
1228 int current;
1229 int closest;
1230
1231 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1232 continue;
1233 }
1234
1235 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1236
1237 /* Read the current diplomatic state. */
1239 "%s.type",
1240 buf);
1241
1242 /* Read the closest diplomatic state. */
1244 "%s.max_state",
1245 buf);
1246
1247 if (closest == DS_NO_CONTACT
1248 && (current == DS_PEACE
1249 || current == DS_ALLIANCE)) {
1250 const char *name1 = secfile_lookup_str_default(loading->file, "",
1251 "player%d.name", plrno);
1252 const char *name2 = secfile_lookup_str_default(loading->file, "",
1253 "player%d.name", i);
1254 /* The current relationship is closer than what the save game
1255 * claims is the closes relationship ever. */
1256
1257 log_sg(_("The save game is wrong about what the closest"
1258 " relationship %s (player %d) and %s (player %d) have had is."
1259 " Fixing it..."),
1260 name1, plrno, name2, i);
1261
1262 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1263 }
1266}
1267
1268/************************************************************************/
1271static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1272 int old_def, bool keep_default)
1273{
1274 int value;
1275
1276 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1277
1278 if (value != old_def || !keep_default) {
1279 value++;
1280 secfile_replace_int(loading->file, value, "%s", key);
1281 }
1282
1283 return value;
1284}
1285
1286/************************************************************************/
1294{
1295 bool randsaved;
1296 int num_settings;
1297 bool started;
1298 int old_turn;
1299 int event_count;
1300 int i;
1301
1302 /* Check status and return if not OK (sg_success FALSE). */
1303 sg_check_ret();
1304
1305 log_debug("Upgrading data from savegame to version 3.0.0");
1306
1307 /* Rename "random.save" as "random.saved"
1308 * Note that it's not an error if a scenario does not have [random] at all. */
1309 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1310 secfile_insert_bool(loading->file, randsaved, "random.saved");
1311 }
1312
1313 /* Already started games should have their turn counts increased by 1 */
1314 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1315 started = TRUE;
1316
1317 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1319 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1320 } else {
1321 started = FALSE;
1322 }
1323
1324 player_slots_iterate(pslot) {
1325 int plrno = player_slot_index(pslot);
1326 const char *flag_names[1];
1327
1328 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1329 continue;
1330 }
1331
1332 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1333 plrno)) {
1335
1337 "player%d.flags", plrno);
1338 }
1339
1340 if (started) {
1341 int num = secfile_lookup_int_default(loading->file, 0,
1342 "player%d.nunits",
1343 plrno);
1344
1345 for (i = 0; i < num; i++) {
1346 char buf[64];
1347
1348 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1349
1351 }
1352
1353 num = secfile_lookup_int_default(loading->file, 0,
1354 "player%d.ncities", plrno);
1355
1356 for (i = 0; i < num; i++) {
1357 char buf[64];
1358
1359 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1360
1362 }
1363 }
1365
1366 /* Settings */
1368 "settings.set_count");
1369
1370 /* User meta server message is now a setting. */
1372 "game.meta_usermessage")) {
1373 const char *metamessage;
1374
1376 "game.meta_message");
1377
1378 /* Insert the meta message as a setting */
1379 secfile_insert_str(loading->file, "metamessage",
1380 "settings.set%d.name", num_settings);
1382 "settings.set%d.value", num_settings);
1383 secfile_insert_str(loading->file, "",
1384 "settings.set%d.gamestart", num_settings);
1385 num_settings++;
1386 }
1387
1388 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1389
1390 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1391
1392 for (i = 0; i < event_count; i++) {
1393 const char *etype;
1394
1395 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1396
1397 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1398 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1399 "event_cache.events%d.event", i);
1400 }
1401 }
1402}
1403
1404/************************************************************************/
1409{
1410 int ssa_size;
1411
1412 if (format_class == SAVEGAME_2) {
1413 /* Handled in savegame2 */
1414 return;
1415 }
1416
1418 "savefile.server_side_agent_size");
1419
1420 if (ssa_size != 0) {
1421 /* Already inserted. */
1422 return;
1423 }
1424
1425 /* Add server side agent order. */
1427 "savefile.server_side_agent_size");
1428 if (SSA_COUNT > 0) {
1429 const char **modname;
1430 int i;
1431 int j;
1432
1433 i = 0;
1434 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1435
1436 for (j = 0; j < SSA_COUNT; j++) {
1438 }
1439
1441 SSA_COUNT,
1442 "savefile.server_side_agent_list");
1443 free(modname);
1444 }
1445
1446 /* Insert server_side_agent unit field. */
1447 player_slots_iterate(pslot) {
1448 int unit;
1449 int units_num;
1450 int plrno = player_slot_index(pslot);
1451
1452 if (secfile_section_lookup(loading->file, "player%d", plrno)
1453 == NULL) {
1454 continue;
1455 }
1456
1457 /* Number of units the player has. */
1459 "player%d.nunits",
1460 plrno);
1461
1462 for (unit = 0; unit < units_num; unit++) {
1463 bool ai;
1464
1466 "player%d.u%d.server_side_agent",
1467 plrno, unit)
1468 != NULL) {
1469 /* Already updated? */
1470 continue;
1471 }
1472
1474 "player%d.u%d.ai",
1475 plrno, unit);
1476
1477 if (ai) {
1478 /* Autosettler and Autoexplore are separated by
1479 * compat_post_load_030100() when set to SSA_AUTOSETTLER */
1481 "player%d.u%d.server_side_agent",
1482 plrno, unit);
1483 } else {
1485 "player%d.u%d.server_side_agent",
1486 plrno, unit);
1487 }
1488 }
1490}
1491
1492/************************************************************************/
1500{
1501 /* Check status and return if not OK (sg_success FALSE). */
1502 sg_check_ret();
1503
1504 log_debug("Upgrading data from savegame to version 3.1.0");
1505
1506 /* Actions are now stored by number. */
1507 player_slots_iterate(pslot) {
1508 int unit;
1509 int units_num;
1510 int plrno = player_slot_index(pslot);
1511
1512 if (secfile_section_lookup(loading->file, "player%d", plrno)
1513 == NULL) {
1514 continue;
1515 }
1516
1517 /* Number of units the player has. */
1519 "player%d.nunits",
1520 plrno);
1521
1522 for (unit = 0; unit < units_num; unit++) {
1523 const char *action_unitstr;
1524 int order_len;
1525
1527 "player%d.u%d.orders_length",
1528 plrno, unit);
1529
1531 "player%d.u%d.action_list",
1532 plrno, unit))) {
1533 int order_num;
1534
1537 }
1538
1539 for (order_num = 0; order_num < order_len; order_num++) {
1541
1542 if (action_unitstr[order_num] == '?') {
1544 } else {
1546 }
1547
1548 if (order_num == 0) {
1549 /* The start of a vector has no number. */
1551 "player%d.u%d.action_vec",
1552 plrno, unit);
1553 } else {
1555 "player%d.u%d.action_vec,%d",
1556 plrno, unit, order_num);
1557 }
1558 }
1559 }
1560 }
1562
1563 {
1564 int action_count;
1565
1567 "savefile.action_size");
1568
1569 if (action_count > 0) {
1570 const char **modname;
1571 const char **savemod;
1572 int j;
1573 const char *dur_name = "Disband Unit Recover";
1574
1575 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1576 "savefile.action_vector");
1577
1579
1580 for (j = 0; j < action_count; j++) {
1581 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1582 savemod[j] = dur_name;
1583 } else {
1584 savemod[j] = modname[j];
1585 }
1586 }
1587
1589 "savefile.action_vector");
1590
1591 free(savemod);
1592 }
1593 }
1594
1595 /* Server setting migration. */
1596 {
1597 int set_count;
1598
1599 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1600 int i;
1601 bool gamestart_valid
1603 "settings.gamestart_valid");
1604
1605 /* Only add gamesetdef if gamestart is valid at all */
1606 if (gamestart_valid) {
1607 for (i = 0; i < set_count; i++) {
1608 const char *name
1609 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1610
1611 if (!name) {
1612 continue;
1613 }
1614
1616 "settings.set%d.gamesetdef", i);
1617 }
1618 }
1619 }
1620 }
1621
1622 /* Explicit server side agent was new in 3.1 */
1624}
1625
1626/************************************************************************/
1630{
1631 int i;
1632
1633 for (i = 0; i < act_unit->orders.length; i++) {
1634 struct unit_order *order = &act_unit->orders.list[i];
1635
1636 if (order->order != ORDER_ACTIVITY) {
1637 continue;
1638 }
1639
1640 switch (order->activity) {
1641 case ACTIVITY_CLEAN:
1642 case ACTIVITY_MINE:
1643 case ACTIVITY_IRRIGATE:
1644 case ACTIVITY_PLANT:
1645 case ACTIVITY_CULTIVATE:
1646 case ACTIVITY_TRANSFORM:
1647 case ACTIVITY_CONVERT:
1649 case ACTIVITY_BASE:
1650 case ACTIVITY_GEN_ROAD:
1651 case ACTIVITY_PILLAGE:
1652 action_iterate(act_id) {
1653 struct action *paction = action_by_number(act_id);
1654
1655 if (action_get_activity(paction) == order->activity) {
1656 order->order = ORDER_PERFORM_ACTION;
1657 order->action = action_number(paction);
1658 order->activity = ACTIVITY_LAST;
1659 break;
1660 }
1662 break;
1663 case ACTIVITY_SENTRY:
1664 /* Not an action */
1665 break;
1666 case ACTIVITY_EXPLORE:
1667 case ACTIVITY_IDLE:
1668 case ACTIVITY_GOTO:
1669 case ACTIVITY_FORTIFIED:
1670 case ACTIVITY_LAST:
1671 log_error("Activity %d is not supposed to appear in unit orders",
1672 order->activity);
1673 break;
1674 }
1675 }
1676}
1677
1678/************************************************************************/
1682{
1683 switch (dir) {
1684 case DIR8_NORTH:
1685 return DIR8_SOUTH;
1686 case DIR8_NORTHEAST:
1687 return DIR8_SOUTHWEST;
1688 case DIR8_EAST:
1689 return DIR8_WEST;
1690 case DIR8_SOUTHEAST:
1691 return DIR8_NORTHWEST;
1692 case DIR8_SOUTH:
1693 return DIR8_NORTH;
1694 case DIR8_SOUTHWEST:
1695 return DIR8_NORTHEAST;
1696 case DIR8_WEST:
1697 return DIR8_EAST;
1698 case DIR8_NORTHWEST:
1699 return DIR8_SOUTHEAST;
1700 }
1701
1702 return DIR8_ORIGIN;
1703}
1704
1705/************************************************************************/
1709{
1710 int i;
1711 struct tile *current_tile;
1712 struct tile *tgt_tile;
1713
1714 if (!unit_has_orders(act_unit)) {
1715 return;
1716 }
1717
1718 /* The order index is for the unit at its current tile. */
1719 current_tile = unit_tile(act_unit);
1720
1721 /* Rewind to the beginning of the orders */
1722 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1723 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1724
1725 if (!(prev_order->order == ORDER_PERFORM_ACTION
1729 current_tile = mapstep(&(wld.map), current_tile,
1730 dir_opposite(prev_order->dir));
1731 }
1732 }
1733
1734 /* Upgrade to explicit target tile */
1735 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1736 struct unit_order *order = &act_unit->orders.list[i];
1737
1738 if (order->order == ORDER_PERFORM_ACTION
1739 && order->target != NO_TARGET) {
1740 /* The target is already specified in the new format. */
1741
1742 /* The index_to_tile() call has no side-effects that we
1743 * would want also in NDEBUG builds. */
1744 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1745 return;
1746 }
1747
1748 if (!direction8_is_valid(order->dir)) {
1749 /* The target of the action is on the actor's tile. */
1750 tgt_tile = current_tile;
1751 } else {
1752 /* The target of the action is on a tile next to the actor. */
1753 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1754 }
1755
1756 if (order->order == ORDER_PERFORM_ACTION) {
1757 if (tgt_tile != NULL) {
1758 struct action *paction = action_by_number(order->action);
1759
1760 order->target = tgt_tile->index;
1761 /* Leave no traces. */
1762 order->dir = DIR8_ORIGIN;
1763
1765 /* The action moves the unit to the target tile (unless this is the
1766 * final order) */
1769 || i == act_unit->orders.length - 1);
1770 current_tile = tgt_tile;
1771 }
1772 } else {
1773 current_tile = NULL;
1774 }
1775 } else {
1776 current_tile = tgt_tile;
1777 }
1778 }
1779
1780 if (current_tile == NULL) {
1781 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1783 }
1784}
1785
1786/************************************************************************/
1790{
1791 players_iterate_alive(pplayer) {
1792 unit_list_iterate(pplayer->units, punit) {
1795 }
1798}
1799
1800/************************************************************************/
1805{
1806 /* Check status and return if not OK (sg_success FALSE). */
1807 sg_check_ret();
1808
1809 /* Action orders were new in 3.0 */
1810 if (format_class == SAVEGAME_3) {
1811 /* Only 3.0 savegames may have "Attack" action orders. */
1812 players_iterate_alive(pplayer) {
1813 unit_list_iterate(pplayer->units, punit) {
1814 int i;
1815
1816 if (!punit->has_orders) {
1817 continue;
1818 }
1819
1821 || punit->orders.list != NULL, continue);
1822
1823 for (i = 0; i < punit->orders.length; i++) {
1824 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1830 }
1831
1832 /* Production targeted actions were split from building targeted
1833 * actions in 3.1. The building sub target encoding changed. */
1835 && ((punit->orders.list[i].action
1837 || (punit->orders.list[i].action
1839 punit->orders.list[i].sub_target -= 1;
1840 }
1842 && (punit->orders.list[i].action
1844 && punit->orders.list[i].sub_target == -1) {
1847 }
1849 && (punit->orders.list[i].action
1851 && punit->orders.list[i].sub_target == -1) {
1854 }
1855 }
1858 }
1859
1860 /* Explicit server side agent was new in 3.1 */
1862
1863 /* Some activities should only be ordered in action orders. */
1864 players_iterate_alive(pplayer) {
1865 unit_list_iterate(pplayer->units, punit) {
1869
1870 /* Unit order action target isn't dir anymore */
1871 players_iterate_alive(pplayer) {
1872 unit_list_iterate(pplayer->units, punit) {
1876
1877 /* Backward compatibility: if we had any open-ended orders (pillage)
1878 * in the savegame, assign specific targets now */
1879 players_iterate_alive(pplayer) {
1880 unit_list_iterate(pplayer->units, punit) {
1882 &punit->activity,
1886}
1887
1888/************************************************************************/
1896{
1897 int i;
1898 int count;
1899 int set_count;
1900 bool gamestart_valid = FALSE;
1901
1902 /* Check status and return if not OK (sg_success FALSE). */
1903 sg_check_ret();
1904
1905 log_debug("Upgrading data from savegame to version 3.2.0");
1906
1907 {
1908 const char *str = secfile_lookup_str_default(loading->file, NULL,
1909 "savefile.orig_version");
1910
1911 if (str == NULL) {
1912 /* Make sure CURRENTLY running version does not
1913 * end as orig_version when we resave. */
1914 if (format_class == SAVEGAME_3) {
1915 secfile_insert_str(loading->file, "old savegame3, or older",
1916 "savefile.orig_version");
1917 } else {
1919
1920 secfile_insert_str(loading->file, "savegame2, or older",
1921 "savefile.orig_version");
1922 }
1923 }
1924 }
1925
1926 {
1927 int action_count;
1928
1930 "savefile.action_size");
1931
1932 if (action_count > 0) {
1933 const char **modname;
1934 const char **savemod;
1935 int j;
1936 const char *dur_name = "Transport Deboard";
1937 const char *clean_name = "Clean";
1938
1939 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1940 "savefile.action_vector");
1941
1943
1944 for (j = 0; j < action_count; j++) {
1945 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1946 savemod[j] = dur_name;
1947 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1948 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1949 savemod[j] = clean_name;
1950 } else {
1951 savemod[j] = modname[j];
1952 }
1953 }
1954
1956 "savefile.action_vector");
1957
1958 free(savemod);
1959 }
1960 }
1961
1962 {
1963 int activities_count;
1964
1966 "savefile.activities_size");
1967
1968 if (activities_count > 0) {
1969 const char **modname;
1970 const char **savemod;
1971 int j;
1972 const char *clean_name = "Clean";
1973
1974 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1975 "savefile.activities_vector");
1976
1978
1979 for (j = 0; j < activities_count; j++) {
1980 if (!fc_strcasecmp("Pollution", modname[j])
1981 || !fc_strcasecmp("Fallout", modname[j])) {
1982 savemod[j] = clean_name;
1983 } else {
1984 savemod[j] = modname[j];
1985 }
1986 }
1987
1989 "savefile.activities_vector");
1990
1991 free(savemod);
1992 }
1993 }
1994
1995 /* Server setting migration. */
1996 {
1997 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1998 int alltemperate_idx = -1, singlepole_idx = -1;
1999 bool count_changed = FALSE;
2000
2003 "settings.gamestart_valid");
2004
2005 for (i = 0; i < set_count; i++) {
2006 const char *old_name
2007 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2008 const char *name;
2009
2010 if (!old_name) {
2011 continue;
2012 }
2013
2015
2016 if (fc_strcasecmp(old_name, name)) {
2017 /* Setting's name changed */
2018 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2019 }
2020
2021 if (!gamestart_valid) {
2022 /* Older savegames saved these values even when they were not valid.
2023 * Silence warnings caused by them. */
2024 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2025 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2026 }
2027
2028 if (!fc_strcasecmp("compresstype", name)) {
2029 const char *val = secfile_lookup_str(loading->file,
2030 "settings.set%d.value", i);
2031 if (!fc_strcasecmp(val, "BZIP2")) {
2032#ifdef FREECIV_HAVE_LIBZSTD
2033 secfile_replace_str(loading->file, "ZSTD",
2034 "settings.set%d.value", i);
2035#elif FREECIV_HAVE_LIBLZMA
2036 secfile_replace_str(loading->file, "XZ",
2037 "settings.set%d.value", i);
2038#elif FREECIV_HAVE_LIBZ
2039 secfile_replace_str(loading->file, "LIBZ",
2040 "settings.set%d.value", i);
2041#else
2042 secfile_replace_str(loading->file, "PLAIN",
2043 "settings.set%d.value", i);
2044#endif
2045 }
2046
2047 if (gamestart_valid) {
2048 val = secfile_lookup_str(loading->file,
2049 "settings.set%d.gamestart", i);
2050 if (!fc_strcasecmp(val, "BZIP2")) {
2051#ifdef FREECIV_HAVE_LIBZSTD
2052 secfile_replace_str(loading->file, "ZSTD",
2053 "settings.set%d.gamestart", i);
2054#elif FREECIV_HAVE_LIBLZMA
2055 secfile_replace_str(loading->file, "XZ",
2056 "settings.set%d.gamestart", i);
2057#elif FREECIV_HAVE_LIBZ
2058 secfile_replace_str(loading->file, "LIBZ",
2059 "settings.set%d.gamestart", i);
2060#else
2061 secfile_replace_str(loading->file, "PLAIN",
2062 "settings.set%d.gamestart", i);
2063#endif
2064 }
2065 }
2066 } else if (!fc_strcasecmp("topology", name)) {
2067 struct setting *pset = setting_by_name(name);
2068 struct sf_cb_data info = { pset, TRUE };
2069 int val;
2070
2071 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2073 "settings.set%d.value", i)) {
2074 char wrap[100];
2075 char buf[100];
2076
2077 if (val & TF_OLD_WRAPX) {
2078 if (val & TF_OLD_WRAPY) {
2079 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2080 } else {
2081 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2082 }
2083 } else if (val & TF_OLD_WRAPY) {
2084 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2085 } else {
2086 fc_strlcpy(wrap, "", sizeof(wrap));
2087 }
2088
2089 if (val & TF_ISO) {
2090 if (val & TF_HEX) {
2091 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2092 } else {
2093 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2094 }
2095 } else if (val & TF_HEX) {
2096 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2097 } else {
2099 }
2100
2101 setting_value_name(pset, FALSE, buf, sizeof(buf));
2103 "settings.set%d.value", i);
2104
2106 "wrap", "settings.set%d.name", set_count);
2108 wrap, "settings.set%d.value", set_count);
2109
2110 if (gamestart_valid) {
2111 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2113 "settings.set%d.gamestart", i)) {
2114 if (val & TF_OLD_WRAPX) {
2115 if (val & TF_OLD_WRAPY) {
2116 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2117 } else {
2118 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2119 }
2120 } else if (val & TF_OLD_WRAPY) {
2121 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2122 } else {
2123 fc_strlcpy(wrap, "", sizeof(wrap));
2124 }
2125
2126 if (val & TF_ISO) {
2127 if (val & TF_HEX) {
2128 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2129 } else {
2130 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2131 }
2132 } else if (val & TF_HEX) {
2133 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2134 } else {
2136 }
2137
2138 setting_value_name(pset, FALSE, buf, sizeof(buf));
2140 "settings.set%d.gamestart", i);
2141
2143 wrap, "settings.set%d.gamestart", set_count);
2144 }
2145 }
2146
2147 set_count++;
2149 }
2150 } else if (!fc_strcasecmp("alltemperate", name)) {
2152 } else if (!fc_strcasecmp("singlepole", name)) {
2153 singlepole_idx = i;
2154 }
2155 }
2156
2157 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2158 int north_latitude, south_latitude;
2159 int north_idx, south_idx;
2161
2162 if (alltemperate_idx < 0
2164 "settings.set%d.value",
2166 /* Infer what would've been the ruleset default */
2168 }
2169
2170 if (singlepole_idx < 0
2172 "settings.set%d.value",
2173 singlepole_idx)) {
2174 /* Infer what would've been the ruleset default */
2176 }
2177
2178 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2179 * changes, that'll have to be handled in later migrations anyway */
2180 north_latitude = alltemperate ? 500 : 1000;
2181 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2182
2183 /* Replace alltemperate with northlatitude, and singlepole with
2184 * southlatitude. If only one of the two was given, add the other
2185 * at the end. */
2188
2189 secfile_replace_str(loading->file, "northlatitude",
2190 "settings.set%d.name", north_idx);
2191 secfile_replace_int(loading->file, north_latitude,
2192 "settings.set%d.value", north_idx);
2193
2194 secfile_replace_str(loading->file, "southlatitude",
2195 "settings.set%d.name", south_idx);
2196 secfile_replace_int(loading->file, south_latitude,
2197 "settings.set%d.value", south_idx);
2198
2199 if (gamestart_valid) {
2200 if (alltemperate_idx < 0
2202 "settings.set%d.gamestart",
2204 alltemperate =
2206 }
2207
2208 if (singlepole_idx < 0
2210 "settings.set%d.gamestart",
2211 singlepole_idx)) {
2213 }
2214
2215 north_latitude = alltemperate ? 500 : 1000;
2216 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2217
2218 secfile_replace_int(loading->file, north_latitude,
2219 "settings.set%d.gamestart", north_idx);
2220 secfile_replace_int(loading->file, south_latitude,
2221 "settings.set%d.gamestart", south_idx);
2222 }
2223
2224 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2225 /* only one was given and replaced ~> we added one new entry */
2226 set_count++;
2228 }
2229 }
2230
2231 if (count_changed) {
2233 "settings.set_count");
2234 }
2235 }
2236 }
2237
2238 {
2239 /* Turn old AI level field to a setting. */
2240 const char *level;
2241 enum ai_level lvl;
2242
2243 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2244 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2245 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2247 } else {
2249 }
2250
2251 if (!ai_level_is_valid(lvl)) {
2252 log_sg("Invalid AI level \"%s\". "
2253 "Changed to \"%s\".", level,
2256 }
2257
2258 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2259 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2260
2261 if (gamestart_valid) {
2262 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2263 set_count);
2264 }
2265
2266 set_count++;
2267 secfile_replace_int(loading->file, set_count, "settings.set_count");
2268 }
2269
2270 if (format_class != SAVEGAME_2) {
2271 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2272 /* Older savegames had a bug that got_tech_multi was not saved. */
2273 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2274 for (i = 0; i < count; i++) {
2275 bool got_tech = FALSE;
2276 int bulbs = 0;
2277 bool got_tech_multi
2279 "research.r%d.got_tech_multi", i);
2280
2282 "research.r%d.got_tech", i)
2283 && secfile_lookup_int(loading->file, &bulbs,
2284 "research.r%d.bulbs", i)) {
2286 got_tech || got_tech_multi ? bulbs : 0,
2287 "research.r%d.free_bulbs", i);
2288 }
2289 }
2290 }
2291
2292 /* Older savegames unnecessarily saved diplstate type order.
2293 * Silence "unused entry" warnings about those. */
2294 {
2296 "savefile.diplstate_type_size");
2297
2298 for (i = 0; i < dscount; i++) {
2300 "savefile.diplstate_type_vector,%d", i);
2301 }
2302 }
2303
2304 /* Add wl_max_length entries for players */
2305 {
2306 player_slots_iterate(pslot) {
2307 int plrno = player_slot_index(pslot);
2308 int ncities;
2309 int cnro;
2310 size_t wlist_max_length = 0;
2311 bool first_city;
2312
2313 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2314 continue;
2315 }
2316
2318 "player%d.got_first_city",
2319 plrno);
2320 if (first_city) {
2321 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2322 int flagcount = 0;
2323 const char **flags_sg;
2324 size_t nval;
2325
2327
2329 "player%d.flags", plrno);
2330
2331 for (i = 0; i < nval; i++) {
2334
2336 }
2337
2339 "player%d.flags", plrno);
2340
2342 }
2343
2345 "player%d.ncities", plrno);
2346
2347 for (cnro = 0; cnro < ncities; cnro++) {
2349 "player%d.c%d.wl_length",
2350 plrno, cnro);
2351
2353
2354 if (format_class == SAVEGAME_3) {
2356 "player%d.c%d.original",
2357 plrno, cnro) != plrno) {
2359 "player%d.c%d.acquire_t",
2360 plrno, cnro);
2361 } else {
2363 "player%d.c%d.acquire_t",
2364 plrno, cnro);
2365 }
2366
2368 "player%d.c%d.wlcb",
2369 plrno, cnro);
2370 }
2371 }
2372
2374 "player%d.wl_max_length", plrno);
2375
2376 if (format_class == SAVEGAME_3) {
2377 int nunits;
2378 int unro;
2379 size_t olist_max_length = 0;
2380
2382 "player%d.nunits", plrno);
2383
2384 for (unro = 0; unro < nunits; unro++) {
2386 "player%d.u%d.orders_length",
2387 plrno, unro);
2388
2390 }
2391
2393 "player%d.orders_max_length", plrno);
2394
2396 "player%d.routes_max_length", plrno);
2397 }
2398
2400 }
2401}
2402
2403/************************************************************************/
2406enum ai_level ai_level_convert(int old_level)
2407{
2408 switch (old_level) {
2409 case 1:
2410 return AI_LEVEL_AWAY;
2411 case 2:
2412 return AI_LEVEL_NOVICE;
2413 case 3:
2414 return AI_LEVEL_EASY;
2415 case 5:
2416 return AI_LEVEL_NORMAL;
2417 case 7:
2418 return AI_LEVEL_HARD;
2419 case 8:
2420 return AI_LEVEL_CHEATING;
2421 case 10:
2422#ifdef FREECIV_DEBUG
2423 return AI_LEVEL_EXPERIMENTAL;
2424#else /* FREECIV_DEBUG */
2425 return AI_LEVEL_HARD;
2426#endif /* FREECIV_DEBUG */
2427 }
2428
2429 return ai_level_invalid();
2430}
2431
2432/************************************************************************/
2435enum barbarian_type barb_type_convert(int old_type)
2436{
2437 switch (old_type) {
2438 case 0:
2439 return NOT_A_BARBARIAN;
2440 case 1:
2441 return LAND_BARBARIAN;
2442 case 2:
2443 return SEA_BARBARIAN;
2444 }
2445
2446 return barbarian_type_invalid();
2447}
int action_number(const struct action *action)
Definition actions.c:1969
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
#define action_iterate_end
Definition actions.h:465
#define action_get_activity(_pact_)
Definition actions.h:699
#define action_iterate(_act_)
Definition actions.h:461
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:75
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:354
#define EC_SPECIAL
Definition fc_types.h:1114
revolen_type
Definition fc_types.h:1282
@ REVOLEN_RANDOM
Definition fc_types.h:1284
@ REVOLEN_RANDQUICK
Definition fc_types.h:1286
@ REVOLEN_FIXED
Definition fc_types.h:1283
@ REVOLEN_QUICKENING
Definition fc_types.h:1285
#define DIR8_ORIGIN
Definition fc_types.h:457
#define _(String)
Definition fcintl.h:67
struct world wld
Definition game.c:63
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:738
#define GAME_DEFAULT_SCORETURN
Definition game.h:582
#define GAME_DEFAULT_SAVETURNS
Definition game.h:680
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:566
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:698
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:306
int current_compat_ver(void)
Definition savecompat.c:205
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:245
bool sg_success
Definition savecompat.c:34
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:543
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:36
static struct compatibility compat[]
Definition savecompat.c:105
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:324
static void upgrade_unit_order_targets(struct unit *act_unit)
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:215
static const int compat_num
Definition savecompat.c:128
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:686
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:85
int char2num(char ch)
Definition savecompat.c:251
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:138
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:667
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:227
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:292
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:560
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:266
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:183
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:282
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:129
#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:3306
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4264
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4220
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:4062
#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:90
const load_version_func_t load
Definition savecompat.c:89
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: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: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:1769
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:359
bool unit_has_orders(const struct unit *punit)
Definition unit.c:202
#define unit_tile(_pu)
Definition unit.h:397
@ 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:1078
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