Freeciv-3.3
Loading...
Searching...
No Matches
savecompat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "capability.h"
20#include "log.h"
21
22/* common */
23#include "map.h"
24#include "specialist.h"
25
26/* server */
27#include "aiiface.h"
28#include "plrhand.h"
29#include "setcompat.h"
30#include "settings.h"
31#include "unittools.h"
32
33#include "savecompat.h"
34
36
37static char *special_names[] =
38 {
39 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
40 "Fallout", NULL
41 };
42
43/*
44 For each savefile format after 2.3.0, compatibility functions are defined
45 which translate secfile structures from previous version to that version;
46 all necessary compat functions are called in order to
47 translate between the file and current version. See sg_load_compat().
48
49 The integer version ID should be increased every time the format is changed.
50 If the change is not backwards compatible, please state the changes in the
51 following list and update the compat functions at the end of this file.
52
53 - what was added / removed
54 - when was it added / removed (date and version)
55 - when can additional capability checks be set to mandatory (version)
56 - which compatibility checks are needed and till when (version)
57
58 freeciv | what | date | id
59 --------+------------------------------------------------+------------+----
60 current | (mapped to current savegame format) | ----/--/-- | 0
61 | first version (svn17538) | 2010/07/05 | -
62 2.3.0 | 2.3.0 release | 2010/11/?? | 3
63 2.4.0 | 2.4.0 release | 201./../.. | 10
64 | * player ai type | |
65 | * delegation | |
66 | * citizens | |
67 | * save player color | |
68 | * "known" info format change | |
69 2.5.0 | 2.5.0 release | 201./../.. | 20
70 2.6.0 | 2.6.0 release | 201./../.. | 30
71 3.0.0 | 3.0.0 release | 201./../.. | 40
72 3.1.0 | 3.1.0 release | 201./../.. | 50
73 3.2.0 | 3.2.0 release | 202./../.. | 60
74 3.3.0 | 3.3.0 release (development) | 202./../.. | 70
75 | | |
76*/
77
85static void compat_post_load_030100(struct loaddata *loading,
87static void compat_post_load_030300(struct loaddata *loading,
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.3.0, add the compatibility functions to
109 * - compat_load_030300 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 /* version 61 to 69 are reserved for possible changes in 3.2.x */
131 /* Current savefile version is listed above this line; it corresponds to
132 the definitions in this file. */
133};
134
135static const int compat_num = ARRAY_SIZE(compat);
136#define compat_current (compat_num - 1)
137
138/************************************************************************/
146{
147 int i;
148
149 /* Check status and return if not OK (sg_success FALSE). */
150 sg_check_ret();
151
152 loading->version = secfile_lookup_int_default(loading->file, -1,
153 "savefile.version");
154#ifdef FREECIV_DEBUG
155 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
156 loading->version);
157 if (loading->version > compat[compat_current].version) {
158 /* Debug build can (TRY TO!) load newer versions but ... */
159 log_error("Savegame version newer than this build found (%d > %d). "
160 "Trying to load the game nevertheless ...", loading->version,
162 }
163#else /* FREECIV_DEBUG */
164 sg_failure_ret(0 < loading->version
165 && loading->version <= compat[compat_current].version,
166 "Unknown savefile format version (%d).", loading->version);
167#endif /* FREECIV_DEBUG */
168
169
170 for (i = 0; i < compat_num; i++) {
171 if (loading->version < compat[i].version && compat[i].load != NULL) {
172 log_normal(_("Run compatibility function for version: <%d "
173 "(save file: %d; server: %d)."), compat[i].version,
176 }
177 }
178}
179
180/************************************************************************/
192{
193 int i;
194
195 /* Check status and return if not OK (sg_success FALSE). */
196 sg_check_ret();
197
198 for (i = 0; i < compat_num; i++) {
199 if (loading->version < compat[i].version
200 && compat[i].post_load != NULL) {
201 log_normal(_("Run post load compatibility function for version: <%d "
202 "(save file: %d; server: %d)."), compat[i].version,
205 }
206 }
207}
208
209/************************************************************************/
213{
215}
216
217/************************************************************************/
222char bin2ascii_hex(int value, int halfbyte_wanted)
223{
224 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
225}
226
227/************************************************************************/
235{
236 const char *pch;
237
238 if (ch == ' ') {
239 /* Sane value. It is unknown if there are savegames out there which
240 * need this fix. Savegame.c doesn't write such savegames
241 * (anymore) since the inclusion into CVS (2000-08-25). */
242 return 0;
243 }
244
246
247 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
248 "Unknown hex value: '%c' %d", ch, ch);
249 return (pch - hex_chars) << (halfbyte * 4);
250}
251
252static const char num_chars[] =
253 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
254
255/************************************************************************/
258int char2num(char ch)
259{
260 const char *pch;
261
263
265 "Unknown ascii value for num: '%c' %d", ch, ch);
266
267 return pch - num_chars;
268}
269
270/************************************************************************/
274{
275 int i;
276
277 for (i = 0; special_names[i] != NULL; i++) {
278 if (!strcmp(name, special_names[i])) {
279 return i;
280 }
281 }
282
283 return S_LAST;
284}
285
286/************************************************************************/
290{
291 fc_assert(type >= 0 && type < S_LAST);
292
293 return special_names[type];
294}
295
296/************************************************************************/
300{
302
305 }
306
307 return NULL;
308}
309
310/************************************************************************/
313struct extra_type *resource_by_identifier(const char identifier)
314{
316 if (presource->data.resource->id_old_save == identifier) {
317 return presource;
318 }
320
321 return NULL;
322}
323
324/* =======================================================================
325 * Compatibility functions for loading a game.
326 * ======================================================================= */
327
328/************************************************************************/
333{
334 /* Check status and return if not OK (sg_success FALSE). */
335 sg_check_ret();
336
337 log_debug("Upgrading data from savegame to version 2.4.0");
338
339 /* Add the default player AI. */
340 player_slots_iterate(pslot) {
341 int ncities, i, plrno = player_slot_index(pslot);
342
343 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
344 continue;
345 }
346
348 "player%d.ai_type", player_slot_index(pslot));
349
350 /* Create dummy citizens information. We do not know if citizens are
351 * activated due to the fact that this information
352 * (game.info.citizen_nationality) is not available, but adding the
353 * information does no harm. */
355 "player%d.ncities", plrno);
356 if (ncities > 0) {
357 for (i = 0; i < ncities; i++) {
359 "player%d.c%d.size", plrno, i);
360 if (size > 0) {
362 "player%d.c%d.citizen%d", plrno, i, plrno);
363 }
364 }
365 }
366
368
369 /* Player colors are assigned at the end of player loading, as this
370 * needs information not available here. */
371
372 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
373 * workaround in later 2.3.x); see gna bug #19029.
374 * (The structure of this code is odd as it avoids relying on knowledge of
375 * xsize/ysize, which haven't been extracted from the savefile yet.) */
376 {
377 if (has_capability("knownv2",
378 secfile_lookup_str(loading->file, "savefile.options"))) {
379 /* This savefile contains known information in a sane format.
380 * Just move any entries to where 2.4.x+ expect to find them. */
381 struct section *map = secfile_section_by_name(loading->file, "map");
382
383 if (map != NULL) {
385 const char *name = entry_name(pentry);
386
387 if (!fc_strncmp(name, "kvb", 3)) {
388 /* Rename the "kvb..." entry to "k..." */
389 char *name2 = fc_strdup(name), *newname = name2 + 2;
390
391 *newname = 'k';
392 /* Savefile probably contains existing "k" entries, which are bogus
393 * so we trash them. */
394 secfile_entry_delete(loading->file, "map.%s", newname);
396 FC_FREE(name2);
397 }
399 }
400 /* Could remove "knownv2" from savefile.options, but it's doing
401 * no harm there. */
402 } else {
403 /* This savefile only contains known information in the broken
404 * format. Try to recover it to a sane format. */
405 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
406 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
407 const int maxslots = 128, maxmapsize = 512;
408 const int lines = maxslots/32;
409 int xsize = 0, y, l, j, x;
410 unsigned int known_row_old[lines * maxmapsize],
412 /* Process a map row at a time */
413 for (y = 0; y < maxmapsize; y++) {
414 /* Look for broken info to convert */
415 bool found = FALSE;
417 for (l = 0; l < lines; l++) {
418 for (j = 0; j < 8; j++) {
419 const char *s =
421 "map.k%02d_%04d", l * 8 + j, y);
422 if (s) {
423 found = TRUE;
424 if (xsize == 0) {
425 xsize = strlen(s);
426 }
427 sg_failure_ret(xsize == strlen(s),
428 "Inconsistent xsize in map.k%02d_%04d",
429 l * 8 + j, y);
430 for (x = 0; x < xsize; x++) {
431 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
432 }
433 }
434 }
435 }
436 if (found) {
437 /* At least one entry found for this row. Let's hope they were
438 * all there. */
439 /* Attempt to munge into sane format */
440 int p;
441 memset(known_row, 0, sizeof(known_row));
442 /* Iterate over possible player slots */
443 for (p = 0; p < maxslots; p++) {
444 l = p / 32;
445 for (x = 0; x < xsize; x++) {
446 /* This test causes bit-shifts of >=32 (undefined behavior), but
447 * on common platforms, information happens not to be lost, just
448 * oddly arranged. */
449 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
450 known_row[l * xsize + x] |= (1u << (p - l * 32));
451 }
452 }
453 }
454 /* Save sane format back to memory representation of secfile for
455 * real loading code to pick up */
456 for (l = 0; l < lines; l++) {
457 for (j = 0; j < 8; j++) {
458 /* Save info for all slots (not just used ones). It's only
459 * memory, after all. */
460 char row[xsize+1];
461 for (x = 0; x < xsize; x++) {
462 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
463 }
464 row[xsize] = '\0';
466 "map.k%02d_%04d", l * 8 + j, y);
467 }
468 }
469 }
470 }
471 }
472 }
473
474 /* Server setting migration. */
475 {
476 int set_count;
477
478 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
479 int i, new_opt = set_count;
480 bool gamestart_valid
482 "settings.gamestart_valid");
483
484 for (i = 0; i < set_count; i++) {
485 const char *name
486 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
487
488 if (!name) {
489 continue;
490 }
491
492 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
493 * This is now controlled by the "autosaves" setting. */
494 if (!fc_strcasecmp("saveturns", name)) {
495 /* XXX: Hardcodes details from GAME_AUTOSAVES_DEFAULT
496 * and settings.c:autosaves_name() (but these defaults reflect
497 * 2.3's behavior). */
498 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
499 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
500 int nturns;
501
503 "settings.set%d.value", i)) {
504 if (nturns == 0) {
505 /* Invent a new "autosaves" setting */
507 "settings.set%d.value", new_opt);
508 /* Pick something valid for saveturns */
510 "settings.set%d.value", i);
511 } else {
513 "settings.set%d.value", new_opt);
514 }
515 } else {
516 log_sg("Setting '%s': %s", name, secfile_error());
517 }
518 if (gamestart_valid) {
520 "settings.set%d.gamestart", i)) {
521 if (nturns == 0) {
522 /* Invent a new "autosaves" setting */
524 "settings.set%d.gamestart", new_opt);
525 /* Pick something valid for saveturns */
527 "settings.set%d.gamestart", i);
528 } else {
530 "settings.set%d.gamestart", new_opt);
531 }
532 } else {
533 log_sg("Setting '%s': %s", name, secfile_error());
534 }
535 }
536 } else if (!fc_strcasecmp("autosaves", name)) {
537 /* Sanity check. This won't trigger on an option we've just
538 * invented, as the loop won't include it. */
539 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
540 "savefile. It may have been overridden.");
541 }
542 }
543 }
544 }
545}
546
547/************************************************************************/
550static const char *killcitizen_enum_str(secfile_data_t data, int bit)
551{
552 switch (bit) {
553 case UMT_LAND:
554 return "LAND";
555 case UMT_SEA:
556 return "SEA";
557 case UMT_BOTH:
558 return "BOTH";
559 }
560
561 return NULL;
562}
563
564/************************************************************************/
569{
570 const char *modname[] = { "Road", "Railroad" };
571 const char *old_activities_names[] = {
572 "Idle",
573 "Pollution",
574 "Unused Road",
575 "Mine",
576 "Irrigate",
577 "Mine",
578 "Irrigate",
579 "Fortified",
580 "Fortress",
581 "Sentry",
582 "Unused Railroad",
583 "Pillage",
584 "Goto",
585 "Explore",
586 "Transform",
587 "Unused",
588 "Unused Airbase",
589 "Fortifying",
590 "Fallout",
591 "Unused Patrol",
592 "Base"
593 };
594
595 /* Check status and return if not OK (sg_success FALSE). */
596 sg_check_ret();
597
598 log_debug("Upgrading data from savegame to version 2.5.0");
599
600 secfile_insert_int(loading->file, 2, "savefile.roads_size");
601 secfile_insert_int(loading->file, 0, "savefile.trait_size");
602
604 "savefile.roads_vector");
605
606 secfile_insert_int(loading->file, 19, "savefile.activities_size");
608 "savefile.activities_vector");
609
610 /* Server setting migration. */
611 {
612 int set_count;
613
614 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
615 int i;
616 bool gamestart_valid
618 "settings.gamestart_valid");
619 for (i = 0; i < set_count; i++) {
620 const char *name
621 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
622 if (!name) {
623 continue;
624 }
625 /* In 2.4.x and prior, "killcitizen" listed move types that
626 * killed citizens after successful attack. Now killcitizen
627 * is just boolean and classes affected are defined in ruleset. */
628 if (!fc_strcasecmp("killcitizen", name)) {
629 int value;
630
631 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
633 "settings.set%d.value", i)) {
634 /* Lowest bit of old killcitizen value indicates if
635 * land units should kill citizens. We take that as
636 * new boolean killcitizen value. */
637 if (value & 0x1) {
639 "settings.set%d.value", i);
640 } else {
642 "settings.set%d.value", i);
643 }
644 } else {
645 log_sg("Setting '%s': %s", name, secfile_error());
646 }
647 if (gamestart_valid) {
648 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
650 "settings.set%d.gamestart", i)) {
651 /* Lowest bit of old killcitizen value indicates if
652 * land units should kill citizens. We take that as
653 * new boolean killcitizen value. */
654 if (value & 0x1) {
656 "settings.set%d.gamestart", i);
657 } else {
659 "settings.set%d.gamestart", i);
660 }
661 } else {
662 log_sg("Setting '%s': %s", name, secfile_error());
663 }
664 }
665 }
666 }
667 }
668 }
669}
670
671/************************************************************************/
675{
676 switch (type) {
677 case REVOLEN_FIXED:
678 return "FIXED";
679 case REVOLEN_RANDOM:
680 return "RANDOM";
682 return "QUICKENING";
684 return "RANDQUICK";
685 }
686
687 return "";
688}
689
690/************************************************************************/
695{
696 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
697 int tsize;
698 int ti;
699 int turn;
700
701 /* Check status and return if not OK (sg_success FALSE). */
702 sg_check_ret();
703
704 log_debug("Upgrading data from savegame to version 2.6.0");
705
706 /* Terrain mapping table - use current ruleset as we have no way to know
707 * any other old values. */
708 ti = 0;
710 char buf[2];
711
712 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
714 buf[1] = '\0';
715 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
717
718 /* Server setting migration. */
719 {
720 int set_count;
721
722 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
723 char value_buffer[1024] = "";
724 char gamestart_buffer[1024] = "";
725 int i;
726 int dcost = -1;
727 int dstartcost = -1;
730 bool gamestart_valid
732 "settings.gamestart_valid");
733 int new_set_count;
734
735 for (i = 0; i < set_count; i++) {
736 const char *name
737 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
738 if (!name) {
739 continue;
740 }
741
742 /* In 2.5.x and prior, "spacerace" boolean controlled if
743 * spacerace victory condition was active. */
744 if (!fc_strcasecmp("spacerace", name)) {
745 bool value;
746
747 if (secfile_lookup_bool(loading->file, &value,
748 "settings.set%d.value", i)) {
749 if (value) {
750 if (value_buffer[0] != '\0') {
752 }
753 sz_strlcat(value_buffer, "SPACERACE");
754 }
755 } else {
756 log_sg("Setting '%s': %s", name, secfile_error());
757 }
758 if (secfile_lookup_bool(loading->file, &value,
759 "settings.set%d.gamestart", i)) {
760 if (value) {
761 if (gamestart_buffer[0] != '\0') {
763 }
764 sz_strlcat(gamestart_buffer, "SPACERACE");
765 }
766 } else {
767 log_sg("Setting '%s': %s", name, secfile_error());
768 }
769
770 /* We cannot delete old values from the secfile, or rather cannot
771 * change index of the later settings. Renumbering them is not easy as
772 * we don't know type of each setting we would encounter.
773 * So we keep old setting values and only add new "victories" setting. */
774 } else if (!fc_strcasecmp("alliedvictory", name)) {
775 bool value;
776
777 if (secfile_lookup_bool(loading->file, &value,
778 "settings.set%d.value", i)) {
779 if (value) {
780 if (value_buffer[0] != '\0') {
782 }
783 sz_strlcat(value_buffer, "ALLIED");
784 }
785 } else {
786 log_sg("Setting '%s': %s", name, secfile_error());
787 }
788 if (secfile_lookup_bool(loading->file, &value,
789 "settings.set%d.gamestart", i)) {
790 if (value) {
791 if (gamestart_buffer[0] != '\0') {
793 }
794 sz_strlcat(gamestart_buffer, "ALLIED");
795 }
796 } else {
797 log_sg("Setting '%s': %s", name, secfile_error());
798 }
799 } else if (!fc_strcasecmp("revolen", name)) {
800 int value;
801
802 if (secfile_lookup_int(loading->file, &value,
803 "settings.set%d.value", i)) {
804 /* 0 meant RANDOM 1-5 */
805 if (value == 0) {
808 "settings.set%d.value", i);
809 } else {
811 }
812 } else {
813 log_sg("Setting '%s': %s", name, secfile_error());
814 }
815 if (secfile_lookup_int(loading->file, &value,
816 "settings.set%d.gamestart", i)) {
817 /* 0 meant RANDOM 1-5 */
818 if (value == 0) {
821 "settings.set%d.gamestart", i);
822 } else {
824 }
825 } else {
826 log_sg("Setting '%s': %s", name, secfile_error());
827 }
828 } else if (!fc_strcasecmp("happyborders", name)) {
829 bool value;
830
831 if (secfile_lookup_bool(loading->file, &value,
832 "settings.set%d.value", i)) {
833 secfile_entry_delete(loading->file, "settings.set%d.value", i);
834 if (value) {
835 secfile_insert_str(loading->file, "NATIONAL",
836 "settings.set%d.value", i);
837 } else {
838 secfile_insert_str(loading->file, "DISABLED",
839 "settings.set%d.value", i);
840 }
841 } else {
842 log_sg("Setting '%s': %s", name, secfile_error());
843 }
844 if (secfile_lookup_bool(loading->file, &value,
845 "settings.set%d.gamestart", i)) {
846 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
847 if (value) {
848 secfile_insert_str(loading->file, "NATIONAL",
849 "settings.set%d.gamestart", i);
850 } else {
851 secfile_insert_str(loading->file, "DISABLED",
852 "settings.set%d.gamestart", i);
853 }
854 } else {
855 log_sg("Setting '%s': %s", name, secfile_error());
856 }
857 } else if (!fc_strcasecmp("team_pooled_research", name)) {
859 &team_pooled_research,
860 "settings.set%d.value", i),
861 "%s", secfile_error());
862 } else if (!fc_strcasecmp("diplcost", name)) {
863 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
864 if (secfile_lookup_int(loading->file, &dcost,
865 "settings.set%d.value", i)) {
866 } else {
867 log_sg("Setting '%s': %s", name, secfile_error());
868 }
869
871 "settings.set%d.gamestart", i)) {
872 } else {
873 log_sg("Setting '%s': %s", name, secfile_error());
874 }
875 } else if (!fc_strcasecmp("huts", name)) {
876 /* Scale of 'huts' changed. */
877 int hcount;
878
880 "settings.set%d.value", i)) {
881 } else {
882 log_sg("Setting '%s': %s", name, secfile_error());
883 }
884
885 /* Store old-style absolute value. */
887 }
888 }
889
890 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
891
892 if (dcost >= 0) {
893 new_set_count += 2;
894 }
895
896 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
897
898 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
899 set_count);
900 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
901 set_count);
902 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
903 set_count + 1);
904 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
905 set_count + 1);
906
907 if (dcost >= 0) {
908 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
909 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
910 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
911 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
912 }
913
914 if (gamestart_valid) {
915 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
916 set_count);
917 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
918 set_count + 1);
919
920 if (dcost >= 0) {
921 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
922 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
923 }
924 }
925 }
926 }
927
928 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
929 "Trait size: %s", secfile_error());
930
931 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
932
933 player_slots_iterate(pslot) {
934 int plrno = player_slot_index(pslot);
935 bool got_first_city;
936 int old_barb_type;
937 enum barbarian_type new_barb_type;
938 int i;
939 const char *name;
940 int score;
941 int units_num;
942
943 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
944 continue;
945 }
946
947 /* Renamed 'capital' to 'got_first_city'. */
949 "player%d.capital", plrno)) {
951 "player%d.got_first_city", plrno);
952 }
953
954 /* Add 'anonymous' qualifiers for user names */
955 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
957 "player%d.unassigned_user", plrno);
958
959 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
961 "player%d.unassigned_ranked", plrno);
962
963 /* Convert numeric barbarian type to textual */
965 "player%d.ai.is_barbarian", plrno);
968 "player%d.ai.barb_type", plrno);
969
970 /* Pre-2.6 didn't record when a player was created or died, so we have
971 * to assume they lived from the start of the game until last turn */
972 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
973
974 /* As if there never has been a war. */
975 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
976
977 /* Assume people were playing until current reload */
978 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
979
980 for (i = 0; i < tsize; i++) {
981 int val;
982
983 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
984 plrno, i);
985 if (val != -1) {
986 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
987 }
988
990 "player%d.trait.mod%d", plrno, i),
991 "Trait mod: %s", secfile_error());
992 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
993 }
994
995 score = secfile_lookup_int_default(loading->file, -1,
996 "player%d.units_built", plrno);
997 if (score >= 0) {
998 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
999 }
1000
1001 score = secfile_lookup_int_default(loading->file, -1,
1002 "player%d.units_killed", plrno);
1003 if (score >= 0) {
1004 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1005 }
1006
1007 score = secfile_lookup_int_default(loading->file, -1,
1008 "player%d.units_lost", plrno);
1009 if (score >= 0) {
1010 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1011 }
1012
1013 /* Units orders. */
1015 "player%d.nunits",
1016 plrno);
1017
1018 for (i = 0; i < units_num; i++) {
1019 int len;
1020
1022 "player%d.u%d.orders_last_move_safe",
1023 plrno, i)) {
1024 continue;
1025 }
1026
1028 "player%d.u%d.orders_length",
1029 plrno, i);
1030 if (len > 0) {
1031 char orders_str[len + 1];
1032 char *p;
1033
1036 "player%d.u%d.orders_list",
1037 plrno, i));
1038 if ((p = strrchr(orders_str, 'm'))
1039 || (p = strrchr(orders_str, 'M'))) {
1040 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1042 "player%d.u%d.orders_list", plrno, i);
1043 }
1044 }
1045 }
1047
1048 /* Add specialist order - loading time order is ok here, as we will use
1049 * that when we in later part of compatibility conversion use the specialist
1050 * values */
1052 "savefile.specialists_size");
1053 {
1054 const char **modname;
1055 int i = 0;
1056
1058
1062
1064 "savefile.specialists_vector");
1065
1066 free(modname);
1067 }
1068
1069 /* Replace all city specialist count fields with correct names */
1070 player_slots_iterate(pslot) {
1071 int plrno = player_slot_index(pslot);
1072 int ncities;
1073 int i;
1074
1075 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1076 continue;
1077 }
1078
1079 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1080
1081 for (i = 0; i < ncities; i++) {
1082 int k = 0;
1083
1085 struct specialist *psp = specialist_by_number(sp);
1086 int count;
1087
1089 "player%d.c%d.n%s",
1091 "specialist error: %s", secfile_error());
1092 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1094 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1095 plrno, i, k++);
1097 }
1099
1100 /* Build [research]. */
1101 {
1102 const struct {
1103 const char *name;
1104 enum entry_type type;
1105 } entries[] = {
1106 { "goal_name", ENTRY_STR },
1107 { "techs", ENTRY_INT },
1108 { "futuretech", ENTRY_INT },
1109 { "bulbs_before", ENTRY_INT },
1110 { "saved_name", ENTRY_STR },
1111 { "bulbs", ENTRY_INT },
1112 { "now_name", ENTRY_STR },
1113 { "got_tech", ENTRY_BOOL },
1114 { "done", ENTRY_STR }
1115 };
1116
1118 int count = 0;
1119 int i;
1120
1121 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1122 researches[i] = -1;
1123 }
1124
1125 player_slots_iterate(pslot) {
1126 int plrno = player_slot_index(pslot);
1127 int ival;
1128 bool bval;
1129 const char *sval;
1130 int j;
1131
1132 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1133 continue;
1134 }
1135
1136 /* Get the research number. */
1137 if (team_pooled_research) {
1139 "player%d.team_no", plrno);
1140 } else {
1141 i = plrno;
1142 }
1143
1145 "Research out of bounds (%d)!", i);
1146
1147 /* Find the index in [research] section. */
1148 if (researches[i] == -1) {
1149 /* This is the first player for this research. */
1150 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1151 researches[i] = count;
1152 count++;
1153 }
1154 i = researches[i];
1155
1156 /* Move entries. */
1157 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1158 switch (entries[j].type) {
1159 case ENTRY_BOOL:
1160 if (secfile_lookup_bool(loading->file, &bval,
1161 "player%d.research.%s",
1162 plrno, entries[j].name)) {
1163 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1164 i, entries[j].name);
1165 }
1166 break;
1167 case ENTRY_INT:
1168 if (secfile_lookup_int(loading->file, &ival,
1169 "player%d.research.%s",
1170 plrno, entries[j].name)) {
1171 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1172 i, entries[j].name);
1173 }
1174 break;
1175 case ENTRY_STR:
1176 if ((sval = secfile_lookup_str(loading->file,
1177 "player%d.research.%s",
1178 plrno, entries[j].name))) {
1179 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1180 i, entries[j].name);
1181 }
1182 break;
1183 case ENTRY_FLOAT:
1185 "Research related entry marked as float.");
1186 break;
1189 break;
1190 case ENTRY_LONG_COMMENT:
1192 break;
1193 case ENTRY_ILLEGAL:
1195 break;
1196 }
1197 }
1199 secfile_insert_int(loading->file, count, "research.count");
1200 }
1201
1202 /* Add diplstate type order. */
1204 "savefile.diplstate_type_size");
1205 if (DS_LAST > 0) {
1206 const char **modname;
1207 int i;
1208 int j;
1209
1210 i = 0;
1211 modname = fc_calloc(DS_LAST, sizeof(*modname));
1212
1213 for (j = 0; j < DS_LAST; j++) {
1215 }
1216
1218 DS_LAST,
1219 "savefile.diplstate_type_vector");
1220 free(modname);
1221 }
1222
1223 /* Fix save games from Freeciv versions with a bug that made it view
1224 * "Never met" as closer than "Peace" or "Alliance". */
1225 player_slots_iterate(pslot) {
1226 int plrno = player_slot_index(pslot);
1227
1228 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1229 continue;
1230 }
1231
1233 int i = player_slot_index(pslot2);
1234 char buf[32];
1235 int current;
1236 int closest;
1237
1238 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1239 continue;
1240 }
1241
1242 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1243
1244 /* Read the current diplomatic state. */
1246 "%s.type",
1247 buf);
1248
1249 /* Read the closest diplomatic state. */
1251 "%s.max_state",
1252 buf);
1253
1254 if (closest == DS_NO_CONTACT
1255 && (current == DS_PEACE
1256 || current == DS_ALLIANCE)) {
1257 const char *name1 = secfile_lookup_str_default(loading->file, "",
1258 "player%d.name", plrno);
1259 const char *name2 = secfile_lookup_str_default(loading->file, "",
1260 "player%d.name", i);
1261 /* The current relationship is closer than what the save game
1262 * claims is the closes relationship ever. */
1263
1264 log_sg(_("The save game is wrong about what the closest"
1265 " relationship %s (player %d) and %s (player %d) have had is."
1266 " Fixing it..."),
1267 name1, plrno, name2, i);
1268
1269 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1270 }
1273}
1274
1275/************************************************************************/
1278static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1279 int old_def, bool keep_default)
1280{
1281 int value;
1282
1283 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1284
1285 if (value != old_def || !keep_default) {
1286 value++;
1287 secfile_replace_int(loading->file, value, "%s", key);
1288 }
1289
1290 return value;
1291}
1292
1293/************************************************************************/
1301{
1302 bool randsaved;
1303 int num_settings;
1304 bool started;
1305 int old_turn;
1306 int event_count;
1307 int i;
1308
1309 /* Check status and return if not OK (sg_success FALSE). */
1310 sg_check_ret();
1311
1312 log_debug("Upgrading data from savegame to version 3.0.0");
1313
1314 /* Rename "random.save" as "random.saved"
1315 * Note that it's not an error if a scenario does not have [random] at all. */
1316 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1317 secfile_insert_bool(loading->file, randsaved, "random.saved");
1318 }
1319
1320 /* Already started games should have their turn counts increased by 1 */
1321 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1322 started = TRUE;
1323
1324 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1326 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1327 } else {
1328 started = FALSE;
1329 }
1330
1331 player_slots_iterate(pslot) {
1332 int plrno = player_slot_index(pslot);
1333 const char *flag_names[1];
1334
1335 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1336 continue;
1337 }
1338
1339 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1340 plrno)) {
1342
1344 "player%d.flags", plrno);
1345 }
1346
1347 if (started) {
1348 int num = secfile_lookup_int_default(loading->file, 0,
1349 "player%d.nunits",
1350 plrno);
1351
1352 for (i = 0; i < num; i++) {
1353 char buf[64];
1354
1355 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1356
1358 }
1359
1360 num = secfile_lookup_int_default(loading->file, 0,
1361 "player%d.ncities", plrno);
1362
1363 for (i = 0; i < num; i++) {
1364 char buf[64];
1365
1366 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1367
1369 }
1370 }
1372
1373 /* Settings */
1375 "settings.set_count");
1376
1377 /* User meta server message is now a setting. */
1379 "game.meta_usermessage")) {
1380 const char *metamessage;
1381
1383 "game.meta_message");
1384
1385 /* Insert the meta message as a setting */
1386 secfile_insert_str(loading->file, "metamessage",
1387 "settings.set%d.name", num_settings);
1389 "settings.set%d.value", num_settings);
1390 secfile_insert_str(loading->file, "",
1391 "settings.set%d.gamestart", num_settings);
1392 num_settings++;
1393 }
1394
1395 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1396
1397 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1398
1399 for (i = 0; i < event_count; i++) {
1400 const char *etype;
1401
1402 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1403
1404 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1405 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1406 "event_cache.events%d.event", i);
1407 }
1408 }
1409}
1410
1411/************************************************************************/
1416{
1417 int ssa_size;
1418
1419 if (format_class == SAVEGAME_2) {
1420 /* Handled in savegame2 */
1421 return;
1422 }
1423
1425 "savefile.server_side_agent_size");
1426
1427 if (ssa_size != 0) {
1428 /* Already inserted. */
1429 return;
1430 }
1431
1432 /* Add server side agent order. */
1434 "savefile.server_side_agent_size");
1435 if (SSA_COUNT > 0) {
1436 const char **modname;
1437 int i;
1438 int j;
1439
1440 i = 0;
1441 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1442
1443 for (j = 0; j < SSA_COUNT; j++) {
1445 }
1446
1448 SSA_COUNT,
1449 "savefile.server_side_agent_list");
1450 free(modname);
1451 }
1452
1453 /* Insert server_side_agent unit field. */
1454 player_slots_iterate(pslot) {
1455 int unit;
1456 int units_num;
1457 int plrno = player_slot_index(pslot);
1458
1459 if (secfile_section_lookup(loading->file, "player%d", plrno)
1460 == NULL) {
1461 continue;
1462 }
1463
1464 /* Number of units the player has. */
1466 "player%d.nunits",
1467 plrno);
1468
1469 for (unit = 0; unit < units_num; unit++) {
1470 bool ai;
1471
1473 "player%d.u%d.server_side_agent",
1474 plrno, unit)
1475 != NULL) {
1476 /* Already updated? */
1477 continue;
1478 }
1479
1481 "player%d.u%d.ai",
1482 plrno, unit);
1483
1484 if (ai) {
1485 /* Autoworker and Autoexplore are separated by
1486 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1488 "player%d.u%d.server_side_agent",
1489 plrno, unit);
1490 } else {
1492 "player%d.u%d.server_side_agent",
1493 plrno, unit);
1494 }
1495 }
1497}
1498
1499/************************************************************************/
1507{
1508 /* Check status and return if not OK (sg_success FALSE). */
1509 sg_check_ret();
1510
1511 log_debug("Upgrading data from savegame to version 3.1.0");
1512
1513 /* Actions are now stored by number. */
1514 player_slots_iterate(pslot) {
1515 int unit;
1516 int units_num;
1517 int plrno = player_slot_index(pslot);
1518
1519 if (secfile_section_lookup(loading->file, "player%d", plrno)
1520 == NULL) {
1521 continue;
1522 }
1523
1524 /* Number of units the player has. */
1526 "player%d.nunits",
1527 plrno);
1528
1529 for (unit = 0; unit < units_num; unit++) {
1530 const char *action_unitstr;
1531 int order_len;
1532
1534 "player%d.u%d.orders_length",
1535 plrno, unit);
1536
1538 "player%d.u%d.action_list",
1539 plrno, unit))) {
1540 int order_num;
1541
1544 }
1545
1546 for (order_num = 0; order_num < order_len; order_num++) {
1548
1549 if (action_unitstr[order_num] == '?') {
1551 } else {
1553 }
1554
1555 if (order_num == 0) {
1556 /* The start of a vector has no number. */
1558 "player%d.u%d.action_vec",
1559 plrno, unit);
1560 } else {
1562 "player%d.u%d.action_vec,%d",
1563 plrno, unit, order_num);
1564 }
1565 }
1566 }
1567 }
1569
1570 {
1571 int action_count;
1572
1574 "savefile.action_size");
1575
1576 if (action_count > 0) {
1577 const char **modname;
1578 const char **savemod;
1579 int j;
1580 const char *dur_name = "Disband Unit Recover";
1581
1582 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1583 "savefile.action_vector");
1584
1586
1587 for (j = 0; j < action_count; j++) {
1588 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1589 savemod[j] = dur_name;
1590 } else {
1591 savemod[j] = modname[j];
1592 }
1593 }
1594
1596 "savefile.action_vector");
1597
1598 free(savemod);
1599 }
1600 }
1601
1602 /* Server setting migration. */
1603 {
1604 int set_count;
1605
1606 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1607 int i;
1608 bool gamestart_valid
1610 "settings.gamestart_valid");
1611
1612 /* Only add gamesetdef if gamestart is valid at all */
1613 if (gamestart_valid) {
1614 for (i = 0; i < set_count; i++) {
1615 const char *name
1616 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1617
1618 if (!name) {
1619 continue;
1620 }
1621
1623 "settings.set%d.gamesetdef", i);
1624 }
1625 }
1626 }
1627 }
1628
1629 /* Explicit server side agent was new in 3.1 */
1631}
1632
1633/************************************************************************/
1637{
1638 int i;
1639
1640 for (i = 0; i < act_unit->orders.length; i++) {
1641 struct unit_order *order = &act_unit->orders.list[i];
1642
1643 if (order->order != ORDER_ACTIVITY) {
1644 continue;
1645 }
1646
1647 switch (order->activity) {
1648 case ACTIVITY_CLEAN:
1649 case ACTIVITY_MINE:
1650 case ACTIVITY_IRRIGATE:
1651 case ACTIVITY_PLANT:
1652 case ACTIVITY_CULTIVATE:
1653 case ACTIVITY_TRANSFORM:
1654 case ACTIVITY_CONVERT:
1656 case ACTIVITY_BASE:
1657 case ACTIVITY_GEN_ROAD:
1658 case ACTIVITY_PILLAGE:
1659 action_iterate(act_id) {
1660 struct action *paction = action_by_number(act_id);
1661
1662 if (action_get_activity(paction) == order->activity) {
1663 order->order = ORDER_PERFORM_ACTION;
1664 order->action = action_number(paction);
1665 order->activity = ACTIVITY_LAST;
1666 break;
1667 }
1669 break;
1670 case ACTIVITY_SENTRY:
1671 /* Not an action */
1672 break;
1673 case ACTIVITY_EXPLORE:
1674 case ACTIVITY_IDLE:
1675 case ACTIVITY_GOTO:
1676 case ACTIVITY_FORTIFIED:
1677 case ACTIVITY_LAST:
1678 log_error("Activity %d is not supposed to appear in unit orders",
1679 order->activity);
1680 break;
1681 }
1682 }
1683}
1684
1685/************************************************************************/
1689{
1690 switch (dir) {
1691 case DIR8_NORTH:
1692 return DIR8_SOUTH;
1693 case DIR8_NORTHEAST:
1694 return DIR8_SOUTHWEST;
1695 case DIR8_EAST:
1696 return DIR8_WEST;
1697 case DIR8_SOUTHEAST:
1698 return DIR8_NORTHWEST;
1699 case DIR8_SOUTH:
1700 return DIR8_NORTH;
1701 case DIR8_SOUTHWEST:
1702 return DIR8_NORTHEAST;
1703 case DIR8_WEST:
1704 return DIR8_EAST;
1705 case DIR8_NORTHWEST:
1706 return DIR8_SOUTHEAST;
1707 }
1708
1709 return DIR8_ORIGIN;
1710}
1711
1712/************************************************************************/
1716{
1717 int i;
1718 struct tile *current_tile;
1719 struct tile *tgt_tile;
1720
1721 if (!unit_has_orders(act_unit)) {
1722 return;
1723 }
1724
1725 /* The order index is for the unit at its current tile. */
1726 current_tile = unit_tile(act_unit);
1727
1728 /* Rewind to the beginning of the orders */
1729 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1730 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1731
1732 if (!(prev_order->order == ORDER_PERFORM_ACTION
1736 current_tile = mapstep(&(wld.map), current_tile,
1737 dir_opposite(prev_order->dir));
1738 }
1739 }
1740
1741 /* Upgrade to explicit target tile */
1742 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1743 struct unit_order *order = &act_unit->orders.list[i];
1744
1745 if (order->order == ORDER_PERFORM_ACTION
1746 && order->target != NO_TARGET) {
1747 /* The target is already specified in the new format. */
1748
1749 /* The index_to_tile() call has no side-effects that we
1750 * would want also in NDEBUG builds. */
1751 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1752 return;
1753 }
1754
1755 if (!direction8_is_valid(order->dir)) {
1756 /* The target of the action is on the actor's tile. */
1757 tgt_tile = current_tile;
1758 } else {
1759 /* The target of the action is on a tile next to the actor. */
1760 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1761 }
1762
1763 if (order->order == ORDER_PERFORM_ACTION) {
1764 if (tgt_tile != NULL) {
1765 struct action *paction = action_by_number(order->action);
1766
1767 order->target = tgt_tile->index;
1768 /* Leave no traces. */
1769 order->dir = DIR8_ORIGIN;
1770
1772 /* The action moves the unit to the target tile (unless this is the
1773 * final order) */
1776 || i == act_unit->orders.length - 1);
1777 current_tile = tgt_tile;
1778 }
1779 } else {
1780 current_tile = NULL;
1781 }
1782 } else {
1783 current_tile = tgt_tile;
1784 }
1785 }
1786
1787 if (current_tile == NULL) {
1788 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1790 }
1791}
1792
1793/************************************************************************/
1797{
1798 players_iterate_alive(pplayer) {
1799 unit_list_iterate(pplayer->units, punit) {
1802 }
1805}
1806
1807/************************************************************************/
1812{
1813 /* Check status and return if not OK (sg_success FALSE). */
1814 sg_check_ret();
1815
1816 /* Action orders were new in 3.0 */
1817 if (format_class == SAVEGAME_3) {
1818 /* Only 3.0 savegames may have "Attack" action orders. */
1819 players_iterate_alive(pplayer) {
1820 unit_list_iterate(pplayer->units, punit) {
1821 int i;
1822
1823 if (!punit->has_orders) {
1824 continue;
1825 }
1826
1828 || punit->orders.list != NULL, continue);
1829
1830 for (i = 0; i < punit->orders.length; i++) {
1831 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1837 }
1838
1839 /* Production targeted actions were split from building targeted
1840 * actions in 3.1. The building sub target encoding changed. */
1842 && ((punit->orders.list[i].action
1844 || (punit->orders.list[i].action
1846 punit->orders.list[i].sub_target -= 1;
1847 }
1849 && (punit->orders.list[i].action
1851 && punit->orders.list[i].sub_target == -1) {
1854 }
1856 && (punit->orders.list[i].action
1858 && punit->orders.list[i].sub_target == -1) {
1861 }
1862 }
1865 }
1866
1867 /* Explicit server side agent was new in 3.1 */
1869
1870 /* Some activities should only be ordered in action orders. */
1871 players_iterate_alive(pplayer) {
1872 unit_list_iterate(pplayer->units, punit) {
1876
1877 /* Unit order action target isn't dir anymore */
1878 players_iterate_alive(pplayer) {
1879 unit_list_iterate(pplayer->units, punit) {
1883
1884 /* Backward compatibility: if we had any open-ended orders (pillage)
1885 * in the savegame, assign specific targets now */
1886 players_iterate_alive(pplayer) {
1887 unit_list_iterate(pplayer->units, punit) {
1889 &punit->activity,
1890 punit->action,
1894}
1895
1896/************************************************************************/
1904{
1905 int i;
1906 int count;
1907 int set_count;
1908 bool gamestart_valid = FALSE;
1909
1910 /* Check status and return if not OK (sg_success FALSE). */
1911 sg_check_ret();
1912
1913 log_debug("Upgrading data from savegame to version 3.2.0");
1914
1915 {
1916 const char *str = secfile_lookup_str_default(loading->file, NULL,
1917 "savefile.orig_version");
1918
1919 if (str == NULL) {
1920 /* Make sure CURRENTLY running version does not
1921 * end as orig_version when we resave. */
1922 if (format_class == SAVEGAME_3) {
1923 secfile_insert_str(loading->file, "old savegame3, or older",
1924 "savefile.orig_version");
1925 } else {
1927
1928 secfile_insert_str(loading->file, "savegame2, or older",
1929 "savefile.orig_version");
1930 }
1931 }
1932 }
1933
1934 {
1935 int action_count;
1936
1938 "savefile.action_size");
1939
1940 if (action_count > 0) {
1941 const char **modname;
1942 const char **savemod;
1943 int j;
1944 const char *dur_name = "Transport Deboard";
1945 const char *clean_name = "Clean";
1946
1947 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1948 "savefile.action_vector");
1949
1951
1952 for (j = 0; j < action_count; j++) {
1953 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1954 savemod[j] = dur_name;
1955 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1956 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1957 savemod[j] = clean_name;
1958 } else {
1959 savemod[j] = modname[j];
1960 }
1961 }
1962
1964 "savefile.action_vector");
1965
1966 free(savemod);
1967 }
1968 }
1969
1970 {
1971 int activities_count;
1972
1974 "savefile.activities_size");
1975
1976 if (activities_count > 0) {
1977 const char **modname;
1978 const char **savemod;
1979 int j;
1980 const char *clean_name = "Clean";
1981
1982 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1983 "savefile.activities_vector");
1984
1986
1987 for (j = 0; j < activities_count; j++) {
1988 if (!fc_strcasecmp("Pollution", modname[j])
1989 || !fc_strcasecmp("Fallout", modname[j])) {
1990 savemod[j] = clean_name;
1991 } else {
1992 savemod[j] = modname[j];
1993 }
1994 }
1995
1997 "savefile.activities_vector");
1998
1999 free(savemod);
2000 }
2001 }
2002
2003 /* Server setting migration. */
2004 {
2005 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2006 int alltemperate_idx = -1, singlepole_idx = -1;
2007 bool count_changed = FALSE;
2008
2011 "settings.gamestart_valid");
2012
2013 for (i = 0; i < set_count; i++) {
2014 const char *old_name
2015 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2016 const char *name;
2017
2018 if (!old_name) {
2019 continue;
2020 }
2021
2023
2024 if (fc_strcasecmp(old_name, name)) {
2025 /* Setting's name changed */
2026 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2027 }
2028
2029 if (!gamestart_valid) {
2030 /* Older savegames saved these values even when they were not valid.
2031 * Silence warnings caused by them. */
2032 secfile_entry_ignore(loading->file, "settings.set%d.gamestart", i);
2033 secfile_entry_ignore(loading->file, "settings.set%d.gamesetdef", i);
2034 }
2035
2036 if (!fc_strcasecmp("compresstype", name)) {
2037 const char *val = secfile_lookup_str(loading->file,
2038 "settings.set%d.value", i);
2039 if (!fc_strcasecmp(val, "BZIP2")) {
2040#ifdef FREECIV_HAVE_LIBZSTD
2041 secfile_replace_str(loading->file, "ZSTD",
2042 "settings.set%d.value", i);
2043#elif FREECIV_HAVE_LIBLZMA
2044 secfile_replace_str(loading->file, "XZ",
2045 "settings.set%d.value", i);
2046#elif FREECIV_HAVE_LIBZ
2047 secfile_replace_str(loading->file, "LIBZ",
2048 "settings.set%d.value", i);
2049#else
2050 secfile_replace_str(loading->file, "PLAIN",
2051 "settings.set%d.value", i);
2052#endif
2053 }
2054
2055 if (gamestart_valid) {
2056 val = secfile_lookup_str(loading->file,
2057 "settings.set%d.gamestart", i);
2058 if (!fc_strcasecmp(val, "BZIP2")) {
2059#ifdef FREECIV_HAVE_LIBZSTD
2060 secfile_replace_str(loading->file, "ZSTD",
2061 "settings.set%d.gamestart", i);
2062#elif FREECIV_HAVE_LIBLZMA
2063 secfile_replace_str(loading->file, "XZ",
2064 "settings.set%d.gamestart", i);
2065#elif FREECIV_HAVE_LIBZ
2066 secfile_replace_str(loading->file, "LIBZ",
2067 "settings.set%d.gamestart", i);
2068#else
2069 secfile_replace_str(loading->file, "PLAIN",
2070 "settings.set%d.gamestart", i);
2071#endif
2072 }
2073 }
2074 } else if (!fc_strcasecmp("topology", name)) {
2075 struct setting *pset = setting_by_name(name);
2076 struct sf_cb_data info = { pset, TRUE };
2077 int val;
2078
2079 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2081 "settings.set%d.value", i)) {
2082 char wrap[100];
2083 char buf[100];
2084
2085 if (val & TF_OLD_WRAPX) {
2086 if (val & TF_OLD_WRAPY) {
2087 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2088 } else {
2089 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2090 }
2091 } else if (val & TF_OLD_WRAPY) {
2092 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2093 } else {
2094 fc_strlcpy(wrap, "", sizeof(wrap));
2095 }
2096
2097 if (val & TF_ISO) {
2098 if (val & TF_HEX) {
2099 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2100 } else {
2101 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2102 }
2103 } else if (val & TF_HEX) {
2104 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2105 } else {
2107 }
2108
2109 setting_value_name(pset, FALSE, buf, sizeof(buf));
2111 "settings.set%d.value", i);
2112
2114 "wrap", "settings.set%d.name", set_count);
2116 wrap, "settings.set%d.value", set_count);
2117
2118 if (gamestart_valid) {
2119 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2121 "settings.set%d.gamestart", i)) {
2122 if (val & TF_OLD_WRAPX) {
2123 if (val & TF_OLD_WRAPY) {
2124 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2125 } else {
2126 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2127 }
2128 } else if (val & TF_OLD_WRAPY) {
2129 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2130 } else {
2131 fc_strlcpy(wrap, "", sizeof(wrap));
2132 }
2133
2134 if (val & TF_ISO) {
2135 if (val & TF_HEX) {
2136 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2137 } else {
2138 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2139 }
2140 } else if (val & TF_HEX) {
2141 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2142 } else {
2144 }
2145
2146 setting_value_name(pset, FALSE, buf, sizeof(buf));
2148 "settings.set%d.gamestart", i);
2149
2151 wrap, "settings.set%d.gamestart", set_count);
2152 }
2153 }
2154
2155 set_count++;
2157 }
2158 } else if (!fc_strcasecmp("alltemperate", name)) {
2160 } else if (!fc_strcasecmp("singlepole", name)) {
2161 singlepole_idx = i;
2162 }
2163 }
2164
2165 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2166 int north_latitude, south_latitude;
2167 int north_idx, south_idx;
2169
2170 if (alltemperate_idx < 0
2172 "settings.set%d.value",
2174 /* Infer what would've been the ruleset default */
2176 }
2177
2178 if (singlepole_idx < 0
2180 "settings.set%d.value",
2181 singlepole_idx)) {
2182 /* Infer what would've been the ruleset default */
2184 }
2185
2186 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2187 * changes, that'll have to be handled in later migrations anyway */
2188 north_latitude = alltemperate ? 500 : 1000;
2189 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2190
2191 /* Replace alltemperate with northlatitude, and singlepole with
2192 * southlatitude. If only one of the two was given, add the other
2193 * at the end. */
2196
2197 secfile_replace_str(loading->file, "northlatitude",
2198 "settings.set%d.name", north_idx);
2199 secfile_replace_int(loading->file, north_latitude,
2200 "settings.set%d.value", north_idx);
2201
2202 secfile_replace_str(loading->file, "southlatitude",
2203 "settings.set%d.name", south_idx);
2204 secfile_replace_int(loading->file, south_latitude,
2205 "settings.set%d.value", south_idx);
2206
2207 if (gamestart_valid) {
2208 if (alltemperate_idx < 0
2210 "settings.set%d.gamestart",
2212 alltemperate =
2214 }
2215
2216 if (singlepole_idx < 0
2218 "settings.set%d.gamestart",
2219 singlepole_idx)) {
2221 }
2222
2223 north_latitude = alltemperate ? 500 : 1000;
2224 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2225
2226 secfile_replace_int(loading->file, north_latitude,
2227 "settings.set%d.gamestart", north_idx);
2228 secfile_replace_int(loading->file, south_latitude,
2229 "settings.set%d.gamestart", south_idx);
2230 }
2231
2232 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2233 /* only one was given and replaced ~> we added one new entry */
2234 set_count++;
2236 }
2237 }
2238
2239 if (count_changed) {
2241 "settings.set_count");
2242 }
2243 }
2244 }
2245
2246 {
2247 /* Turn old AI level field to a setting. */
2248 const char *level;
2249 enum ai_level lvl;
2250
2251 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2252 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2253 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2255 } else {
2257 }
2258
2259 if (!ai_level_is_valid(lvl)) {
2260 log_sg("Invalid AI level \"%s\". "
2261 "Changed to \"%s\".", level,
2264 }
2265
2266 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2267 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2268
2269 if (gamestart_valid) {
2270 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2271 set_count);
2272 }
2273
2274 set_count++;
2275 secfile_replace_int(loading->file, set_count, "settings.set_count");
2276 }
2277
2278 if (format_class != SAVEGAME_2) {
2279 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2280 /* Older savegames had a bug that got_tech_multi was not saved. */
2281 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2282 for (i = 0; i < count; i++) {
2283 bool got_tech = FALSE;
2284 int bulbs = 0;
2285 bool got_tech_multi
2287 "research.r%d.got_tech_multi", i);
2288
2290 "research.r%d.got_tech", i)
2291 && secfile_lookup_int(loading->file, &bulbs,
2292 "research.r%d.bulbs", i)) {
2294 got_tech || got_tech_multi ? bulbs : 0,
2295 "research.r%d.free_bulbs", i);
2296 }
2297 }
2298 }
2299
2300 /* Older savegames unnecessarily saved diplstate type order.
2301 * Silence "unused entry" warnings about those. */
2302 {
2304 "savefile.diplstate_type_size");
2305
2306 for (i = 0; i < dscount; i++) {
2308 "savefile.diplstate_type_vector,%d", i);
2309 }
2310 }
2311
2312 /* Add wl_max_length entries for players */
2313 {
2314 player_slots_iterate(pslot) {
2315 int plrno = player_slot_index(pslot);
2316 int ncities;
2317 int cnro;
2318 size_t wlist_max_length = 0;
2319 bool first_city;
2320
2321 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2322 continue;
2323 }
2324
2326 "player%d.got_first_city",
2327 plrno);
2328 if (first_city) {
2329 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2330 int flagcount = 0;
2331 const char **flags_sg;
2332 size_t nval;
2333
2335
2337 "player%d.flags", plrno);
2338
2339 for (i = 0; i < nval; i++) {
2342
2344 }
2345
2347 "player%d.flags", plrno);
2348
2350 }
2351
2353 "player%d.ncities", plrno);
2354
2355 for (cnro = 0; cnro < ncities; cnro++) {
2357 "player%d.c%d.wl_length",
2358 plrno, cnro);
2359
2361
2362 if (format_class == SAVEGAME_3) {
2364 "player%d.c%d.original",
2365 plrno, cnro) != plrno) {
2367 "player%d.c%d.acquire_t",
2368 plrno, cnro);
2369 } else {
2371 "player%d.c%d.acquire_t",
2372 plrno, cnro);
2373 }
2374
2376 "player%d.c%d.wlcb",
2377 plrno, cnro);
2378 }
2379 }
2380
2382 "player%d.wl_max_length", plrno);
2383
2384 if (format_class == SAVEGAME_3) {
2385 int nunits;
2386 int unro;
2387 size_t olist_max_length = 0;
2388
2390 "player%d.nunits", plrno);
2391
2392 for (unro = 0; unro < nunits; unro++) {
2394 "player%d.u%d.orders_length",
2395 plrno, unro);
2396
2398 }
2399
2401 "player%d.orders_max_length", plrno);
2402
2404 "player%d.routes_max_length", plrno);
2405 }
2406
2408 }
2409}
2410
2411/************************************************************************/
2419{
2420 /* Check status and return if not OK (sg_success != TRUE). */
2421 sg_check_ret();
2422
2423 log_debug("Upgrading data from savegame to version 3.3.0");
2424
2425 /* World Peace has never started in the old savegame. */
2426 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2427
2428 if (format_class != SAVEGAME_2) {
2429 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2430
2431 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2432 }
2433
2434 /* Last turn change time as a float, not integer multiplied by 100 */
2435 {
2436 float tct = secfile_lookup_int_default(loading->file, 0,
2437 "game.last_turn_change_time") / 100.0;
2438
2439 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2440 }
2441
2442 {
2443 int ssa_count;
2444
2446 "savefile.server_side_agent_size");
2447 if (ssa_count > 0) {
2448 const char **modname;
2449 const char **savemod;
2450 int j;
2451 const char *aw_name = "AutoWorker";
2452
2453 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2454 "savefile.server_side_agent_list");
2455
2456 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2457
2458 for (j = 0; j < ssa_count; j++) {
2459 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2460 savemod[j] = aw_name;
2461 } else {
2462 savemod[j] = modname[j];
2463 }
2464 }
2465
2467 "savefile.server_side_agent_list");
2468
2469 free(savemod);
2470 }
2471 }
2472
2473 {
2474 int action_count;
2475
2477 "savefile.action_size");
2478
2479 if (action_count > 0) {
2480 const char **modname;
2481 const char **savemod;
2482 int j;
2483 const char *cc1_name = "Conquer City Shrink";
2484 const char *cc2_name = "Conquer City Shrink 2";
2485 const char *cc3_name = "Conquer City Shrink 3";
2486 const char *cc4_name = "Conquer City Shrink 4";
2487
2488 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2489 "savefile.action_vector");
2490
2492
2493 for (j = 0; j < action_count; j++) {
2494 if (!fc_strcasecmp("Conquer City", modname[j])) {
2495 savemod[j] = cc1_name;
2496 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
2497 savemod[j] = cc2_name;
2498 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
2499 savemod[j] = cc3_name;
2500 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
2501 savemod[j] = cc4_name;
2502 } else {
2503 savemod[j] = modname[j];
2504 }
2505 }
2506
2508 "savefile.action_vector");
2509
2510 free(savemod);
2511 }
2512 }
2513
2514 /* Add actions for unit activities */
2515 if (format_class == SAVEGAME_3) {
2516 loading->activities.size
2518 "savefile.activities_size");
2519 if (loading->activities.size) {
2520 loading->activities.order
2521 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2522 "savefile.activities_vector");
2523 sg_failure_ret(loading->activities.size != 0,
2524 "Failed to load activity order: %s",
2525 secfile_error());
2526 }
2527
2528 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2529 "savefile.action_size");
2530
2531 sg_failure_ret(loading->action.size > 0,
2532 "Failed to load action order: %s",
2533 secfile_error());
2534
2535 if (loading->action.size) {
2536 const char **modname;
2537 int j;
2538
2539 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2540 "savefile.action_vector");
2541
2542 loading->action.order = fc_calloc(loading->action.size,
2543 sizeof(*loading->action.order));
2544
2545 for (j = 0; j < loading->action.size; j++) {
2547
2548 if (real_action != nullptr) {
2549 loading->action.order[j] = real_action->id;
2550 } else {
2551 log_sg("Unknown action \'%s\'", modname[j]);
2552 loading->action.order[j] = ACTION_NONE;
2553 }
2554 }
2555
2556 free(modname);
2557 }
2558
2559 player_slots_iterate(pslot) {
2560 int plrno = player_slot_index(pslot);
2561 int nunits;
2562 int unro;
2563
2564 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2565 continue;
2566 }
2567
2569 "player%d.nunits", plrno);
2570
2571 for (unro = 0; unro < nunits; unro++) {
2572 int ei;
2573 int i;
2574 enum unit_activity activity;
2575 enum gen_action act;
2576
2578 "player%d.u%d.activity", plrno, unro);
2579
2580 if (ei >= 0 && ei < loading->activities.size) {
2581 bool found = FALSE;
2582
2583 activity = unit_activity_by_name(loading->activities.order[ei],
2585
2586 act = activity_default_action(activity);
2587
2588 for (i = 0; i < loading->action.size; i++) {
2589 if (act == loading->action.order[i]) {
2590 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2591 plrno, unro);
2592 found = TRUE;
2593 break;
2594 }
2595 }
2596
2597 if (!found) {
2598 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
2599 plrno, unro);
2600 }
2601 }
2602 }
2604 }
2605
2606 /* Researches */
2607 {
2608 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2609 int i;
2610
2611 for (i = 0; i < count; i++) {
2612 /* It's ok for old savegames to have these entries. */
2613 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
2614 }
2615 }
2616
2617 player_slots_iterate(pslot) {
2618 int plrno = player_slot_index(pslot);
2619 int ncities;
2620 int cnro;
2621
2622 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2623 continue;
2624 }
2625
2627 "player%d.dc_total", plrno);
2628
2629 for (cnro = 0; cnro < ncities; cnro++) {
2630 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
2631 plrno, cnro);
2632 }
2634}
2635
2636/************************************************************************/
2641{
2642 /* Check status and return if not OK (sg_success FALSE). */
2643 sg_check_ret();
2644
2645 /* Capital information was not saved in older savegames,
2646 * so we have no capital setup at all at the moment.
2647 * Best we can do is to do recalculation now. It might be
2648 * a bit off compared to the situation before the game was saved,
2649 * but definitely better than not setting capitals at all. */
2650 players_iterate_alive(pplayer) {
2651 update_capital(pplayer);
2653}
2654
2655/************************************************************************/
2658enum ai_level ai_level_convert(int old_level)
2659{
2660 switch (old_level) {
2661 case 1:
2662 return AI_LEVEL_AWAY;
2663 case 2:
2664 return AI_LEVEL_NOVICE;
2665 case 3:
2666 return AI_LEVEL_EASY;
2667 case 5:
2668 return AI_LEVEL_NORMAL;
2669 case 7:
2670 return AI_LEVEL_HARD;
2671 case 8:
2672 return AI_LEVEL_CHEATING;
2673 case 10:
2674#ifdef FREECIV_DEBUG
2675 return AI_LEVEL_EXPERIMENTAL;
2676#else /* FREECIV_DEBUG */
2677 return AI_LEVEL_HARD;
2678#endif /* FREECIV_DEBUG */
2679 }
2680
2681 return ai_level_invalid();
2682}
2683
2684/************************************************************************/
2687enum barbarian_type barb_type_convert(int old_type)
2688{
2689 switch (old_type) {
2690 case 0:
2691 return NOT_A_BARBARIAN;
2692 case 1:
2693 return LAND_BARBARIAN;
2694 case 2:
2695 return SEA_BARBARIAN;
2696 }
2697
2698 return barbarian_type_invalid();
2699}
struct action * action_by_rule_name(const char *name)
Definition actions.c:1079
int action_number(const struct action *action)
Definition actions.c:1208
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_iterate_end
Definition actions.h:218
#define action_get_activity(_pact_)
Definition actions.h:464
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_NONE
Definition actions.h:59
struct @130::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:249
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
char * incite_cost
Definition comments.c:76
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define NO_TARGET
Definition fc_types.h:214
#define EC_SPECIAL
Definition fc_types.h:821
revolen_type
Definition fc_types.h:990
@ REVOLEN_RANDOM
Definition fc_types.h:992
@ REVOLEN_RANDQUICK
Definition fc_types.h:994
@ REVOLEN_FIXED
Definition fc_types.h:991
@ REVOLEN_QUICKENING
Definition fc_types.h:993
#define DIR8_ORIGIN
Definition fc_types.h:315
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
#define GAME_DEFAULT_REVOLENTYPE
Definition game.h:743
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_SAVETURNS
Definition game.h:685
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:571
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:703
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c: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:528
#define players_iterate_alive_end
Definition player.h:552
#define player_slots_iterate_end
Definition player.h:532
#define players_iterate_alive(_pplayer)
Definition player.h:547
void update_capital(struct player *pplayer)
Definition plrhand.c:731
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
bool secfile_entry_delete(struct section_file *secfile, const char *path,...)
bool entry_set_name(struct entry *pentry, const char *name)
bool secfile_lookup_enum_data(const struct section_file *secfile, int *pvalue, bool bitwise, secfile_enum_name_data_fn_t name_fn, secfile_data_t data, const char *path,...)
const struct entry_list * section_entries(const struct section *psection)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct section * secfile_section_by_name(const struct section_file *secfile, const char *name)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_replace_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
entry_type
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_replace_int(secfile, value, path,...)
#define entry_list_iterate_end
#define secfile_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define entry_list_iterate(entlist, pentry)
#define secfile_replace_float(secfile, value, path,...)
#define secfile_replace_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
struct extra_type * resource_by_identifier(const char identifier)
Definition savecompat.c:313
int current_compat_ver(void)
Definition savecompat.c:212
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:252
bool sg_success
Definition savecompat.c:35
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:550
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:37
static struct compatibility compat[]
Definition savecompat.c:110
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:331
static void upgrade_unit_order_targets(struct unit *act_unit)
static void compat_load_030300(struct loaddata *loading, enum sgf_version format_class)
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:222
static const int compat_num
Definition savecompat.c:135
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:693
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:258
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:145
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:674
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:234
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:299
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:567
static void compat_load_030200(struct loaddata *loading, enum sgf_version format_class)
static void compat_post_load_030300(struct loaddata *loading, enum sgf_version format_class)
enum tile_special_type special_by_rule_name(const char *name)
Definition savecompat.c:273
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:190
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:289
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:136
#define sg_check_ret(...)
Definition savecompat.h:148
#define sg_warn(condition, message,...)
Definition savecompat.h:158
tile_special_type
Definition savecompat.h:29
@ S_LAST
Definition savecompat.h:38
#define hex_chars
Definition savecompat.h:203
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:182
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:175
#define MAX_TRADE_ROUTES_OLD
Definition savecompat.h:220
sgf_version
Definition savecompat.h:27
@ SAVEGAME_2
Definition savecompat.h:27
@ SAVEGAME_3
Definition savecompat.h:27
#define log_sg
Definition savecompat.h:144
const char * setcompat_S3_2_name_from_S3_1(const char *old_name)
Definition setcompat.c:62
struct setting * setting_by_name(const char *name)
Definition settings.c:3309
const char * setting_value_name(const struct setting *pset, bool pretty, char *buf, size_t buf_len)
Definition settings.c:4267
bool setting_bitwise_set(struct setting *pset, const char *val, struct connection *caller, char *reject_msg, size_t reject_msg_len)
Definition settings.c:4223
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:4065
#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
struct packet_game_info info
Definition game.h:89
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@44::@46 server
int huts_absolute
Definition map_types.h:108
const load_version_func_t post_load
Definition savecompat.c: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:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
Definition unit.h:139
int length
Definition unit.h:197
bool has_orders
Definition unit.h:195
enum unit_activity activity
Definition unit.h:158
enum gen_action action
Definition unit.h:159
struct unit::@83 orders
struct extra_type * activity_target
Definition unit.h:166
struct unit_order * list
Definition unit.h:200
enum server_side_agent ssa_controller
Definition unit.h:174
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:125
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:246
#define terrain_type_iterate(_p)
Definition terrain.h:267
#define terrain_type_iterate_end
Definition terrain.h:273
void free_unit_orders(struct unit *punit)
Definition unit.c:1832
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:401
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2956
bool unit_has_orders(const struct unit *punit)
Definition unit.c:220
#define unit_tile(_pu)
Definition unit.h:406
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_PERFORM_ACTION
Definition unit.h:47
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1083
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1253
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1591
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c:1292