Freeciv-3.4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 | 202./../.. | 60
73 3.3.0 | 3.3.0 release | 202./../.. | 70
74 3.4.0 | 3.4.0 release (development) | 202./../.. | 80
75 | | |
76*/
77
86static void compat_post_load_030100(struct loaddata *loading,
88
89#ifdef FREECIV_DEV_SAVE_COMPAT
90static void compat_load_dev(struct loaddata *loading);
91static void compat_post_load_dev(struct loaddata *loading);
92#endif /* FREECIV_DEV_SAVE_COMPAT */
93
95
101
102/* The struct below contains the information about the savegame versions. It
103 * is identified by the version number (first element), which should be
104 * steadily increasing. It is saved as 'savefile.version'. The support
105 * string (first element of 'name') is not saved in the savegame; it is
106 * saved in settings files (so, once assigned, cannot be changed). The
107 * 'pretty' string (second element of 'name') can be changed if necessary
108 * For changes in the development version, edit the definitions above and
109 * add the needed code to load the old version below. Thus, old
110 * savegames can still be loaded while the main definition
111 * represents the current state of the art. */
112/* While developing freeciv 3.4.0, add the compatibility functions to
113 * - compat_load_030400 to load old savegame. */
114static struct compatibility compat[] = {
115 /* dummy; equal to the current version (last element) */
116 { 0, NULL, NULL },
117 /* version 1 and 2 is not used */
118 /* version 3: first savegame2 format, so no compat functions for translation
119 * from previous format */
120 { 3, NULL, NULL },
121 /* version 4 to 9 are reserved for possible changes in 2.3.x */
122 { 10, compat_load_020400, NULL },
123 /* version 11 to 19 are reserved for possible changes in 2.4.x */
124 { 20, compat_load_020500, NULL },
125 /* version 21 to 29 are reserved for possible changes in 2.5.x */
126 { 30, compat_load_020600, NULL },
127 /* version 31 to 39 are reserved for possible changes in 2.6.x */
128 { 40, compat_load_030000, NULL },
129 /* version 41 to 49 are reserved for possible changes in 3.0.x */
131 /* version 51 to 59 are reserved for possible changes in 3.1.x */
132 { 60, compat_load_030200, NULL },
133 /* version 61 to 69 are reserved for possible changes in 3.2.x */
134 { 70, compat_load_030300, NULL },
135 /* version 71 to 79 are reserved for possible changes in 3.3.x */
136 { 80, compat_load_030400, NULL },
137 /* Current savefile version is listed above this line; it corresponds to
138 the definitions in this file. */
139};
140
141static const int compat_num = ARRAY_SIZE(compat);
142#define compat_current (compat_num - 1)
143
144/************************************************************************/
152{
153 int i;
154
155 /* Check status and return if not OK (sg_success FALSE). */
156 sg_check_ret();
157
158 loading->version = secfile_lookup_int_default(loading->file, -1,
159 "savefile.version");
160#ifdef FREECIV_DEBUG
161 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
162 loading->version);
163 if (loading->version > compat[compat_current].version) {
164 /* Debug build can (TRY TO!) load newer versions but ... */
165 log_error("Savegame version newer than this build found (%d > %d). "
166 "Trying to load the game nevertheless ...", loading->version,
168 }
169#else /* FREECIV_DEBUG */
170 sg_failure_ret(0 < loading->version
171 && loading->version <= compat[compat_current].version,
172 "Unknown savefile format version (%d).", loading->version);
173#endif /* FREECIV_DEBUG */
174
175
176 for (i = 0; i < compat_num; i++) {
177 if (loading->version < compat[i].version && compat[i].load != NULL) {
178 log_normal(_("Run compatibility function for version: <%d "
179 "(save file: %d; server: %d)."), compat[i].version,
182 }
183 }
184
185#ifdef FREECIV_DEV_SAVE_COMPAT
186 if (loading->version == compat[compat_current].version) {
188 }
189#endif /* FREECIV_DEV_SAVE_COMPAT */
190}
191
192/************************************************************************/
204{
205 int i;
206
207 /* Check status and return if not OK (sg_success FALSE). */
208 sg_check_ret();
209
210 for (i = 0; i < compat_num; i++) {
211 if (loading->version < compat[i].version
212 && compat[i].post_load != NULL) {
213 log_normal(_("Run post load compatibility function for version: <%d "
214 "(save file: %d; server: %d)."), compat[i].version,
217 }
218 }
219
220#ifdef FREECIV_DEV_SAVE_COMPAT
221 if (loading->version == compat[compat_current].version) {
223 }
224#endif /* FREECIV_DEV_SAVE_COMPAT */
225}
226
227/************************************************************************/
231{
233}
234
235/************************************************************************/
240char bin2ascii_hex(int value, int halfbyte_wanted)
241{
242 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
243}
244
245/************************************************************************/
253{
254 const char *pch;
255
256 if (ch == ' ') {
257 /* Sane value. It is unknown if there are savegames out there which
258 * need this fix. Savegame.c doesn't write such savegames
259 * (anymore) since the inclusion into CVS (2000-08-25). */
260 return 0;
261 }
262
264
265 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
266 "Unknown hex value: '%c' %d", ch, ch);
267 return (pch - hex_chars) << (halfbyte * 4);
268}
269
270static const char num_chars[] =
271 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
272
273/************************************************************************/
276int char2num(char ch)
277{
278 const char *pch;
279
281
283 "Unknown ascii value for num: '%c' %d", ch, ch);
284
285 return pch - num_chars;
286}
287
288/************************************************************************/
292{
293 int i;
294
295 for (i = 0; special_names[i] != NULL; i++) {
296 if (!strcmp(name, special_names[i])) {
297 return i;
298 }
299 }
300
301 return S_LAST;
302}
303
304/************************************************************************/
308{
309 fc_assert(type >= 0 && type < S_LAST);
310
311 return special_names[type];
312}
313
314/************************************************************************/
318{
320
323 }
324
325 return NULL;
326}
327
328/************************************************************************/
331struct extra_type *resource_by_identifier(const char identifier)
332{
334 if (presource->data.resource->id_old_save == identifier) {
335 return presource;
336 }
338
339 return NULL;
340}
341
342/* =======================================================================
343 * Compatibility functions for loading a game.
344 * ======================================================================= */
345
346/************************************************************************/
351{
352 /* Check status and return if not OK (sg_success FALSE). */
353 sg_check_ret();
354
355 log_debug("Upgrading data from savegame to version 2.4.0");
356
357 /* Add the default player AI. */
358 player_slots_iterate(pslot) {
359 int ncities, i, plrno = player_slot_index(pslot);
360
361 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
362 continue;
363 }
364
366 "player%d.ai_type", player_slot_index(pslot));
367
368 /* Create dummy citizens information. We do not know if citizens are
369 * activated due to the fact that this information
370 * (game.info.citizen_nationality) is not available, but adding the
371 * information does no harm. */
373 "player%d.ncities", plrno);
374 if (ncities > 0) {
375 for (i = 0; i < ncities; i++) {
377 "player%d.c%d.size", plrno, i);
378 if (size > 0) {
380 "player%d.c%d.citizen%d", plrno, i, plrno);
381 }
382 }
383 }
384
386
387 /* Player colors are assigned at the end of player loading, as this
388 * needs information not available here. */
389
390 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
391 * workaround in later 2.3.x); see gna bug #19029.
392 * (The structure of this code is odd as it avoids relying on knowledge of
393 * xsize/ysize, which haven't been extracted from the savefile yet.) */
394 {
395 if (has_capability("knownv2",
396 secfile_lookup_str(loading->file, "savefile.options"))) {
397 /* This savefile contains known information in a sane format.
398 * Just move any entries to where 2.4.x+ expect to find them. */
399 struct section *map = secfile_section_by_name(loading->file, "map");
400
401 if (map != NULL) {
403 const char *name = entry_name(pentry);
404
405 if (!fc_strncmp(name, "kvb", 3)) {
406 /* Rename the "kvb..." entry to "k..." */
407 char *name2 = fc_strdup(name), *newname = name2 + 2;
408
409 *newname = 'k';
410 /* Savefile probably contains existing "k" entries, which are bogus
411 * so we trash them. */
412 secfile_entry_delete(loading->file, "map.%s", newname);
414 FC_FREE(name2);
415 }
417 }
418 /* Could remove "knownv2" from savefile.options, but it's doing
419 * no harm there. */
420 } else {
421 /* This savefile only contains known information in the broken
422 * format. Try to recover it to a sane format. */
423 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
424 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
425 const int maxslots = 128, maxmapsize = 512;
426 const int lines = maxslots/32;
427 int xsize = 0, y, l, j, x;
428 unsigned int known_row_old[lines * maxmapsize],
430 /* Process a map row at a time */
431 for (y = 0; y < maxmapsize; y++) {
432 /* Look for broken info to convert */
433 bool found = FALSE;
435 for (l = 0; l < lines; l++) {
436 for (j = 0; j < 8; j++) {
437 const char *s =
439 "map.k%02d_%04d", l * 8 + j, y);
440 if (s) {
441 found = TRUE;
442 if (xsize == 0) {
443 xsize = strlen(s);
444 }
445 sg_failure_ret(xsize == strlen(s),
446 "Inconsistent xsize in map.k%02d_%04d",
447 l * 8 + j, y);
448 for (x = 0; x < xsize; x++) {
449 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
450 }
451 }
452 }
453 }
454 if (found) {
455 /* At least one entry found for this row. Let's hope they were
456 * all there. */
457 /* Attempt to munge into sane format */
458 int p;
459 memset(known_row, 0, sizeof(known_row));
460 /* Iterate over possible player slots */
461 for (p = 0; p < maxslots; p++) {
462 l = p / 32;
463 for (x = 0; x < xsize; x++) {
464 /* This test causes bit-shifts of >=32 (undefined behaviour), but
465 * on common platforms, information happens not to be lost, just
466 * oddly arranged. */
467 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
468 known_row[l * xsize + x] |= (1u << (p - l * 32));
469 }
470 }
471 }
472 /* Save sane format back to memory representation of secfile for
473 * real loading code to pick up */
474 for (l = 0; l < lines; l++) {
475 for (j = 0; j < 8; j++) {
476 /* Save info for all slots (not just used ones). It's only
477 * memory, after all. */
478 char row[xsize+1];
479 for (x = 0; x < xsize; x++) {
480 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
481 }
482 row[xsize] = '\0';
484 "map.k%02d_%04d", l * 8 + j, y);
485 }
486 }
487 }
488 }
489 }
490 }
491
492 /* Server setting migration. */
493 {
494 int set_count;
495
496 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
497 int i, new_opt = set_count;
498 bool gamestart_valid
500 "settings.gamestart_valid");
501
502 for (i = 0; i < set_count; i++) {
503 const char *name
504 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
505
506 if (!name) {
507 continue;
508 }
509
510 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
511 * This is now controlled by the "autosaves" setting. */
512 if (!fc_strcasecmp("saveturns", name)) {
513 /* XXX: hardcodes details from GAME_AUTOSAVES_DEFAULT
514 * and settings.c:autosaves_name() (but these defaults reflect
515 * 2.3's behaviour). */
516 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
517 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
518 int nturns;
519
521 "settings.set%d.value", i)) {
522 if (nturns == 0) {
523 /* Invent a new "autosaves" setting */
525 "settings.set%d.value", new_opt);
526 /* Pick something valid for saveturns */
528 "settings.set%d.value", i);
529 } else {
531 "settings.set%d.value", new_opt);
532 }
533 } else {
534 log_sg("Setting '%s': %s", name, secfile_error());
535 }
536 if (gamestart_valid) {
538 "settings.set%d.gamestart", i)) {
539 if (nturns == 0) {
540 /* Invent a new "autosaves" setting */
542 "settings.set%d.gamestart", new_opt);
543 /* Pick something valid for saveturns */
545 "settings.set%d.gamestart", i);
546 } else {
548 "settings.set%d.gamestart", new_opt);
549 }
550 } else {
551 log_sg("Setting '%s': %s", name, secfile_error());
552 }
553 }
554 } else if (!fc_strcasecmp("autosaves", name)) {
555 /* Sanity check. This won't trigger on an option we've just
556 * invented, as the loop won't include it. */
557 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
558 "savefile. It may have been overridden.");
559 }
560 }
561 }
562 }
563}
564
565/************************************************************************/
568static const char *killcitizen_enum_str(secfile_data_t data, int bit)
569{
570 switch (bit) {
571 case UMT_LAND:
572 return "LAND";
573 case UMT_SEA:
574 return "SEA";
575 case UMT_BOTH:
576 return "BOTH";
577 }
578
579 return NULL;
580}
581
582/************************************************************************/
587{
588 const char *modname[] = { "Road", "Railroad" };
589 const char *old_activities_names[] = {
590 "Idle",
591 "Pollution",
592 "Unused Road",
593 "Mine",
594 "Irrigate",
595 "Mine",
596 "Irrigate",
597 "Fortified",
598 "Fortress",
599 "Sentry",
600 "Unused Railroad",
601 "Pillage",
602 "Goto",
603 "Explore",
604 "Transform",
605 "Unused",
606 "Unused Airbase",
607 "Fortifying",
608 "Fallout",
609 "Unused Patrol",
610 "Base"
611 };
612
613 /* Check status and return if not OK (sg_success FALSE). */
614 sg_check_ret();
615
616 log_debug("Upgrading data from savegame to version 2.5.0");
617
618 secfile_insert_int(loading->file, 2, "savefile.roads_size");
619 secfile_insert_int(loading->file, 0, "savefile.trait_size");
620
622 "savefile.roads_vector");
623
624 secfile_insert_int(loading->file, 19, "savefile.activities_size");
626 "savefile.activities_vector");
627
628 /* Server setting migration. */
629 {
630 int set_count;
631
632 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
633 int i;
634 bool gamestart_valid
636 "settings.gamestart_valid");
637 for (i = 0; i < set_count; i++) {
638 const char *name
639 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
640 if (!name) {
641 continue;
642 }
643 /* In 2.4.x and prior, "killcitizen" listed move types that
644 * killed citizens after successful attack. Now killcitizen
645 * is just boolean and classes affected are defined in ruleset. */
646 if (!fc_strcasecmp("killcitizen", name)) {
647 int value;
648
649 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
651 "settings.set%d.value", i)) {
652 /* Lowest bit of old killcitizen value indicates if
653 * land units should kill citizens. We take that as
654 * new boolean killcitizen value. */
655 if (value & 0x1) {
657 "settings.set%d.value", i);
658 } else {
660 "settings.set%d.value", i);
661 }
662 } else {
663 log_sg("Setting '%s': %s", name, secfile_error());
664 }
665 if (gamestart_valid) {
666 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
668 "settings.set%d.gamestart", i)) {
669 /* Lowest bit of old killcitizen value indicates if
670 * land units should kill citizens. We take that as
671 * new boolean killcitizen value. */
672 if (value & 0x1) {
674 "settings.set%d.gamestart", i);
675 } else {
677 "settings.set%d.gamestart", i);
678 }
679 } else {
680 log_sg("Setting '%s': %s", name, secfile_error());
681 }
682 }
683 }
684 }
685 }
686 }
687}
688
689/************************************************************************/
693{
694 switch (type) {
695 case REVOLEN_FIXED:
696 return "FIXED";
697 case REVOLEN_RANDOM:
698 return "RANDOM";
700 return "QUICKENING";
702 return "RANDQUICK";
703 }
704
705 return "";
706}
707
708/************************************************************************/
713{
714 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
715 int tsize;
716 int ti;
717 int turn;
718
719 /* Check status and return if not OK (sg_success FALSE). */
720 sg_check_ret();
721
722 log_debug("Upgrading data from savegame to version 2.6.0");
723
724 /* Terrain mapping table - use current ruleset as we have no way to know
725 * any other old values. */
726 ti = 0;
728 char buf[2];
729
730 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
732 buf[1] = '\0';
733 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
735
736 /* Server setting migration. */
737 {
738 int set_count;
739
740 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
741 char value_buffer[1024] = "";
742 char gamestart_buffer[1024] = "";
743 int i;
744 int dcost = -1;
745 int dstartcost = -1;
748 bool gamestart_valid
750 "settings.gamestart_valid");
751 int new_set_count;
752
753 for (i = 0; i < set_count; i++) {
754 const char *name
755 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
756 if (!name) {
757 continue;
758 }
759
760 /* In 2.5.x and prior, "spacerace" boolean controlled if
761 * spacerace victory condition was active. */
762 if (!fc_strcasecmp("spacerace", name)) {
763 bool value;
764
765 if (secfile_lookup_bool(loading->file, &value,
766 "settings.set%d.value", i)) {
767 if (value) {
768 if (value_buffer[0] != '\0') {
770 }
771 sz_strlcat(value_buffer, "SPACERACE");
772 }
773 } else {
774 log_sg("Setting '%s': %s", name, secfile_error());
775 }
776 if (secfile_lookup_bool(loading->file, &value,
777 "settings.set%d.gamestart", i)) {
778 if (value) {
779 if (gamestart_buffer[0] != '\0') {
781 }
782 sz_strlcat(gamestart_buffer, "SPACERACE");
783 }
784 } else {
785 log_sg("Setting '%s': %s", name, secfile_error());
786 }
787
788 /* We cannot delete old values from the secfile, or rather cannot
789 * change index of the later settings. Renumbering them is not easy as
790 * we don't know type of each setting we would encounter.
791 * So we keep old setting values and only add new "victories" setting. */
792 } else if (!fc_strcasecmp("alliedvictory", name)) {
793 bool value;
794
795 if (secfile_lookup_bool(loading->file, &value,
796 "settings.set%d.value", i)) {
797 if (value) {
798 if (value_buffer[0] != '\0') {
800 }
801 sz_strlcat(value_buffer, "ALLIED");
802 }
803 } else {
804 log_sg("Setting '%s': %s", name, secfile_error());
805 }
806 if (secfile_lookup_bool(loading->file, &value,
807 "settings.set%d.gamestart", i)) {
808 if (value) {
809 if (gamestart_buffer[0] != '\0') {
811 }
812 sz_strlcat(gamestart_buffer, "ALLIED");
813 }
814 } else {
815 log_sg("Setting '%s': %s", name, secfile_error());
816 }
817 } else if (!fc_strcasecmp("revolen", name)) {
818 int value;
819
820 if (secfile_lookup_int(loading->file, &value,
821 "settings.set%d.value", i)) {
822 /* 0 meant RANDOM 1-5 */
823 if (value == 0) {
826 "settings.set%d.value", i);
827 } else {
829 }
830 } else {
831 log_sg("Setting '%s': %s", name, secfile_error());
832 }
833 if (secfile_lookup_int(loading->file, &value,
834 "settings.set%d.gamestart", i)) {
835 /* 0 meant RANDOM 1-5 */
836 if (value == 0) {
839 "settings.set%d.gamestart", i);
840 } else {
842 }
843 } else {
844 log_sg("Setting '%s': %s", name, secfile_error());
845 }
846 } else if (!fc_strcasecmp("happyborders", name)) {
847 bool value;
848
849 if (secfile_lookup_bool(loading->file, &value,
850 "settings.set%d.value", i)) {
851 secfile_entry_delete(loading->file, "settings.set%d.value", i);
852 if (value) {
853 secfile_insert_str(loading->file, "NATIONAL",
854 "settings.set%d.value", i);
855 } else {
856 secfile_insert_str(loading->file, "DISABLED",
857 "settings.set%d.value", i);
858 }
859 } else {
860 log_sg("Setting '%s': %s", name, secfile_error());
861 }
862 if (secfile_lookup_bool(loading->file, &value,
863 "settings.set%d.gamestart", i)) {
864 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
865 if (value) {
866 secfile_insert_str(loading->file, "NATIONAL",
867 "settings.set%d.gamestart", i);
868 } else {
869 secfile_insert_str(loading->file, "DISABLED",
870 "settings.set%d.gamestart", i);
871 }
872 } else {
873 log_sg("Setting '%s': %s", name, secfile_error());
874 }
875 } else if (!fc_strcasecmp("team_pooled_research", name)) {
877 &team_pooled_research,
878 "settings.set%d.value", i),
879 "%s", secfile_error());
880 } else if (!fc_strcasecmp("diplcost", name)) {
881 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
882 if (secfile_lookup_int(loading->file, &dcost,
883 "settings.set%d.value", i)) {
884 } else {
885 log_sg("Setting '%s': %s", name, secfile_error());
886 }
887
889 "settings.set%d.gamestart", i)) {
890 } else {
891 log_sg("Setting '%s': %s", name, secfile_error());
892 }
893 } else if (!fc_strcasecmp("huts", name)) {
894 /* Scale of 'huts' changed. */
895 int hcount;
896
898 "settings.set%d.value", i)) {
899 } else {
900 log_sg("Setting '%s': %s", name, secfile_error());
901 }
902
903 /* Store old-style absolute value. */
905 }
906 }
907
908 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
909
910 if (dcost >= 0) {
911 new_set_count += 2;
912 }
913
914 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
915
916 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
917 set_count);
918 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
919 set_count);
920 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
921 set_count + 1);
922 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
923 set_count + 1);
924
925 if (dcost >= 0) {
926 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
927 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
928 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
929 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
930 }
931
932 if (gamestart_valid) {
933 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
934 set_count);
935 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
936 set_count + 1);
937
938 if (dcost >= 0) {
939 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
940 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
941 }
942 }
943 }
944 }
945
946 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
947 "Trait size: %s", secfile_error());
948
949 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
950
951 player_slots_iterate(pslot) {
952 int plrno = player_slot_index(pslot);
953 bool got_first_city;
954 int old_barb_type;
955 enum barbarian_type new_barb_type;
956 int i;
957 const char *name;
958 int score;
959 int units_num;
960
961 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
962 continue;
963 }
964
965 /* Renamed 'capital' to 'got_first_city'. */
967 "player%d.capital", plrno)) {
969 "player%d.got_first_city", plrno);
970 }
971
972 /* Add 'anonymous' qualifiers for user names */
973 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
975 "player%d.unassigned_user", plrno);
976
977 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
979 "player%d.unassigned_ranked", plrno);
980
981 /* Convert numeric barbarian type to textual */
983 "player%d.ai.is_barbarian", plrno);
986 "player%d.ai.barb_type", plrno);
987
988 /* Pre-2.6 didn't record when a player was created or died, so we have
989 * to assume they lived from the start of the game until last turn */
990 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
991
992 /* As if there never has been a war. */
993 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
994
995 /* Assume people were playing until current reload */
996 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
997
998 for (i = 0; i < tsize; i++) {
999 int val;
1000
1001 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
1002 plrno, i);
1003 if (val != -1) {
1004 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
1005 }
1006
1008 "player%d.trait.mod%d", plrno, i),
1009 "Trait mod: %s", secfile_error());
1010 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1011 }
1012
1013 score = secfile_lookup_int_default(loading->file, -1,
1014 "player%d.units_built", plrno);
1015 if (score >= 0) {
1016 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1017 }
1018
1019 score = secfile_lookup_int_default(loading->file, -1,
1020 "player%d.units_killed", plrno);
1021 if (score >= 0) {
1022 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1023 }
1024
1025 score = secfile_lookup_int_default(loading->file, -1,
1026 "player%d.units_lost", plrno);
1027 if (score >= 0) {
1028 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1029 }
1030
1031 /* Units orders. */
1033 "player%d.nunits",
1034 plrno);
1035
1036 for (i = 0; i < units_num; i++) {
1037 int len;
1038
1040 "player%d.u%d.orders_last_move_safe",
1041 plrno, i)) {
1042 continue;
1043 }
1044
1046 "player%d.u%d.orders_length",
1047 plrno, i);
1048 if (len > 0) {
1049 char orders_str[len + 1];
1050 char *p;
1051
1054 "player%d.u%d.orders_list",
1055 plrno, i));
1056 if ((p = strrchr(orders_str, 'm'))
1057 || (p = strrchr(orders_str, 'M'))) {
1058 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1060 "player%d.u%d.orders_list", plrno, i);
1061 }
1062 }
1063 }
1065
1066 /* Add specialist order - loading time order is ok here, as we will use
1067 * that when we in later part of compatibility conversion use the specialist
1068 * values */
1070 "savefile.specialists_size");
1071 {
1072 const char **modname;
1073 int i = 0;
1074
1076
1080
1082 "savefile.specialists_vector");
1083
1084 free(modname);
1085 }
1086
1087 /* Replace all city specialist count fields with correct names */
1088 player_slots_iterate(pslot) {
1089 int plrno = player_slot_index(pslot);
1090 int ncities;
1091 int i;
1092
1093 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1094 continue;
1095 }
1096
1097 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1098
1099 for (i = 0; i < ncities; i++) {
1100 int k = 0;
1101
1103 struct specialist *psp = specialist_by_number(sp);
1104 int count;
1105
1107 "player%d.c%d.n%s",
1109 "specialist error: %s", secfile_error());
1110 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1112 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1113 plrno, i, k++);
1115 }
1117
1118 /* Build [research]. */
1119 {
1120 const struct {
1121 const char *name;
1122 enum entry_type type;
1123 } entries[] = {
1124 { "goal_name", ENTRY_STR },
1125 { "techs", ENTRY_INT },
1126 { "futuretech", ENTRY_INT },
1127 { "bulbs_before", ENTRY_INT },
1128 { "saved_name", ENTRY_STR },
1129 { "bulbs", ENTRY_INT },
1130 { "now_name", ENTRY_STR },
1131 { "got_tech", ENTRY_BOOL },
1132 { "done", ENTRY_STR }
1133 };
1134
1136 int count = 0;
1137 int i;
1138
1139 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1140 researches[i] = -1;
1141 }
1142
1143 player_slots_iterate(pslot) {
1144 int plrno = player_slot_index(pslot);
1145 int ival;
1146 bool bval;
1147 const char *sval;
1148 int j;
1149
1150 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1151 continue;
1152 }
1153
1154 /* Get the research number. */
1155 if (team_pooled_research) {
1157 "player%d.team_no", plrno);
1158 } else {
1159 i = plrno;
1160 }
1161
1163 "Research out of bounds (%d)!", i);
1164
1165 /* Find the index in [research] section. */
1166 if (researches[i] == -1) {
1167 /* This is the first player for this research. */
1168 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1169 researches[i] = count;
1170 count++;
1171 }
1172 i = researches[i];
1173
1174 /* Move entries. */
1175 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1176 switch (entries[j].type) {
1177 case ENTRY_BOOL:
1178 if (secfile_lookup_bool(loading->file, &bval,
1179 "player%d.research.%s",
1180 plrno, entries[j].name)) {
1181 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1182 i, entries[j].name);
1183 }
1184 break;
1185 case ENTRY_INT:
1186 if (secfile_lookup_int(loading->file, &ival,
1187 "player%d.research.%s",
1188 plrno, entries[j].name)) {
1189 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1190 i, entries[j].name);
1191 }
1192 break;
1193 case ENTRY_STR:
1194 if ((sval = secfile_lookup_str(loading->file,
1195 "player%d.research.%s",
1196 plrno, entries[j].name))) {
1197 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1198 i, entries[j].name);
1199 }
1200 break;
1201 case ENTRY_FLOAT:
1203 "Research related entry marked as float.");
1204 break;
1207 break;
1208 case ENTRY_LONG_COMMENT:
1210 break;
1211 case ENTRY_ILLEGAL:
1213 break;
1214 }
1215 }
1217 secfile_insert_int(loading->file, count, "research.count");
1218 }
1219
1220 /* Add diplstate type order. */
1222 "savefile.diplstate_type_size");
1223 if (DS_LAST > 0) {
1224 const char **modname;
1225 int i;
1226 int j;
1227
1228 i = 0;
1229 modname = fc_calloc(DS_LAST, sizeof(*modname));
1230
1231 for (j = 0; j < DS_LAST; j++) {
1233 }
1234
1236 DS_LAST,
1237 "savefile.diplstate_type_vector");
1238 free(modname);
1239 }
1240
1241 /* Fix save games from Freeciv versions with a bug that made it view
1242 * "Never met" as closer than "Peace" or "Alliance". */
1243 player_slots_iterate(pslot) {
1244 int plrno = player_slot_index(pslot);
1245
1246 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1247 continue;
1248 }
1249
1251 int i = player_slot_index(pslot2);
1252 char buf[32];
1253 int current;
1254 int closest;
1255
1256 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1257 continue;
1258 }
1259
1260 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1261
1262 /* Read the current diplomatic state. */
1264 "%s.type",
1265 buf);
1266
1267 /* Read the closest diplomatic state. */
1269 "%s.max_state",
1270 buf);
1271
1272 if (closest == DS_NO_CONTACT
1273 && (current == DS_PEACE
1274 || current == DS_ALLIANCE)) {
1275 const char *name1 = secfile_lookup_str_default(loading->file, "",
1276 "player%d.name", plrno);
1277 const char *name2 = secfile_lookup_str_default(loading->file, "",
1278 "player%d.name", i);
1279 /* The current relationship is closer than what the save game
1280 * claims is the closes relationship ever. */
1281
1282 log_sg(_("The save game is wrong about what the closest"
1283 " relationship %s (player %d) and %s (player %d) have had is."
1284 " Fixing it..."),
1285 name1, plrno, name2, i);
1286
1287 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1288 }
1291}
1292
1293/************************************************************************/
1296static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1297 int old_def, bool keep_default)
1298{
1299 int value;
1300
1301 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1302
1303 if (value != old_def || !keep_default) {
1304 value++;
1305 secfile_replace_int(loading->file, value, "%s", key);
1306 }
1307
1308 return value;
1309}
1310
1311/************************************************************************/
1319{
1320 bool randsaved;
1321 int num_settings;
1322 bool started;
1323 int old_turn;
1324 int event_count;
1325 int i;
1326
1327 /* Check status and return if not OK (sg_success FALSE). */
1328 sg_check_ret();
1329
1330 log_debug("Upgrading data from savegame to version 3.0.0");
1331
1332 /* Rename "random.save" as "random.saved"
1333 * Note that it's not an error if a scenario does not have [random] at all. */
1334 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1335 secfile_insert_bool(loading->file, randsaved, "random.saved");
1336 }
1337
1338 /* Already started games should have their turn counts increased by 1 */
1339 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1340 started = TRUE;
1341
1342 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1344 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1345 } else {
1346 started = FALSE;
1347 }
1348
1349 player_slots_iterate(pslot) {
1350 int plrno = player_slot_index(pslot);
1351 const char *flag_names[1];
1352
1353 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1354 continue;
1355 }
1356
1357 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1358 plrno)) {
1360
1362 "player%d.flags", plrno);
1363 }
1364
1365 if (started) {
1366 int num = secfile_lookup_int_default(loading->file, 0,
1367 "player%d.nunits",
1368 plrno);
1369
1370 for (i = 0; i < num; i++) {
1371 char buf[64];
1372
1373 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1374
1376 }
1377
1378 num = secfile_lookup_int_default(loading->file, 0,
1379 "player%d.ncities", plrno);
1380
1381 for (i = 0; i < num; i++) {
1382 char buf[64];
1383
1384 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1385
1387 }
1388 }
1390
1391 /* Settings */
1393 "settings.set_count");
1394
1395 /* User meta server message is now a setting. */
1397 "game.meta_usermessage")) {
1398 const char *metamessage;
1399
1401 "game.meta_message");
1402
1403 /* Insert the meta message as a setting */
1404 secfile_insert_str(loading->file, "metamessage",
1405 "settings.set%d.name", num_settings);
1407 "settings.set%d.value", num_settings);
1408 secfile_insert_str(loading->file, "",
1409 "settings.set%d.gamestart", num_settings);
1410 num_settings++;
1411 }
1412
1413 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1414
1415 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1416
1417 for (i = 0; i < event_count; i++) {
1418 const char *etype;
1419
1420 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1421
1422 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1423 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1424 "event_cache.events%d.event", i);
1425 }
1426 }
1427}
1428
1429/************************************************************************/
1434{
1435 int ssa_size;
1436
1437 if (format_class == SAVEGAME_2) {
1438 /* Handled in savegame2 */
1439 return;
1440 }
1441
1443 "savefile.server_side_agent_size");
1444
1445 if (ssa_size != 0) {
1446 /* Already inserted. */
1447 return;
1448 }
1449
1450 /* Add server side agent order. */
1452 "savefile.server_side_agent_size");
1453 if (SSA_COUNT > 0) {
1454 const char **modname;
1455 int i;
1456 int j;
1457
1458 i = 0;
1459 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1460
1461 for (j = 0; j < SSA_COUNT; j++) {
1463 }
1464
1466 SSA_COUNT,
1467 "savefile.server_side_agent_list");
1468 free(modname);
1469 }
1470
1471 /* Insert server_side_agent unit field. */
1472 player_slots_iterate(pslot) {
1473 int unit;
1474 int units_num;
1475 int plrno = player_slot_index(pslot);
1476
1477 if (secfile_section_lookup(loading->file, "player%d", plrno)
1478 == NULL) {
1479 continue;
1480 }
1481
1482 /* Number of units the player has. */
1484 "player%d.nunits",
1485 plrno);
1486
1487 for (unit = 0; unit < units_num; unit++) {
1488 bool ai;
1489
1491 "player%d.u%d.server_side_agent",
1492 plrno, unit)
1493 != NULL) {
1494 /* Already updated? */
1495 continue;
1496 }
1497
1499 "player%d.u%d.ai",
1500 plrno, unit);
1501
1502 if (ai) {
1503 /* Autoworker and Autoexplore are separated by
1504 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1506 "player%d.u%d.server_side_agent",
1507 plrno, unit);
1508 } else {
1510 "player%d.u%d.server_side_agent",
1511 plrno, unit);
1512 }
1513 }
1515}
1516
1517/************************************************************************/
1525{
1526 /* Check status and return if not OK (sg_success FALSE). */
1527 sg_check_ret();
1528
1529 log_debug("Upgrading data from savegame to version 3.1.0");
1530
1531 /* Actions are now stored by number. */
1532 player_slots_iterate(pslot) {
1533 int unit;
1534 int units_num;
1535 int plrno = player_slot_index(pslot);
1536
1537 if (secfile_section_lookup(loading->file, "player%d", plrno)
1538 == NULL) {
1539 continue;
1540 }
1541
1542 /* Number of units the player has. */
1544 "player%d.nunits",
1545 plrno);
1546
1547 for (unit = 0; unit < units_num; unit++) {
1548 const char *action_unitstr;
1549 int order_len;
1550
1552 "player%d.u%d.orders_length",
1553 plrno, unit);
1554
1556 "player%d.u%d.action_list",
1557 plrno, unit))) {
1558 int order_num;
1559
1562 }
1563
1564 for (order_num = 0; order_num < order_len; order_num++) {
1566
1567 if (action_unitstr[order_num] == '?') {
1569 } else {
1571 }
1572
1573 if (order_num == 0) {
1574 /* The start of a vector has no number. */
1576 "player%d.u%d.action_vec",
1577 plrno, unit);
1578 } else {
1580 "player%d.u%d.action_vec,%d",
1581 plrno, unit, order_num);
1582 }
1583 }
1584 }
1585 }
1587
1588 {
1589 int action_count;
1590
1592 "savefile.action_size");
1593
1594 if (action_count > 0) {
1595 const char **modname;
1596 const char **savemod;
1597 int j;
1598 const char *dur_name = "Disband Unit Recover";
1599
1600 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1601 "savefile.action_vector");
1602
1604
1605 for (j = 0; j < action_count; j++) {
1606 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1607 savemod[j] = dur_name;
1608 } else {
1609 savemod[j] = modname[j];
1610 }
1611 }
1612
1614 "savefile.action_vector");
1615
1616 free(savemod);
1617 }
1618 }
1619
1620 /* Server setting migration. */
1621 {
1622 int set_count;
1623
1624 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1625 int i;
1626 bool gamestart_valid
1628 "settings.gamestart_valid");
1629
1630 /* Only add gamesetdef if gamestart is valid at all */
1631 if (gamestart_valid) {
1632 for (i = 0; i < set_count; i++) {
1633 const char *name
1634 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1635
1636 if (!name) {
1637 continue;
1638 }
1639
1641 "settings.set%d.gamesetdef", i);
1642 }
1643 }
1644 }
1645 }
1646
1647 /* Explicit server side agent was new in 3.1 */
1649}
1650
1651/************************************************************************/
1655{
1656 int i;
1657
1658 for (i = 0; i < act_unit->orders.length; i++) {
1659 struct unit_order *order = &act_unit->orders.list[i];
1660
1661 if (order->order != ORDER_ACTIVITY) {
1662 continue;
1663 }
1664
1665 switch (order->activity) {
1666 case ACTIVITY_CLEAN:
1667 case ACTIVITY_MINE:
1668 case ACTIVITY_IRRIGATE:
1669 case ACTIVITY_PLANT:
1670 case ACTIVITY_CULTIVATE:
1671 case ACTIVITY_TRANSFORM:
1672 case ACTIVITY_CONVERT:
1674 case ACTIVITY_BASE:
1675 case ACTIVITY_GEN_ROAD:
1676 case ACTIVITY_PILLAGE:
1677 action_iterate(act_id) {
1678 struct action *paction = action_by_number(act_id);
1679
1680 if (action_get_activity(paction) == order->activity) {
1681 order->order = ORDER_PERFORM_ACTION;
1682 order->action = action_number(paction);
1683 order->activity = ACTIVITY_LAST;
1684 break;
1685 }
1687 break;
1688 case ACTIVITY_SENTRY:
1689 /* Not an action */
1690 break;
1691 case ACTIVITY_EXPLORE:
1692 case ACTIVITY_IDLE:
1693 case ACTIVITY_GOTO:
1694 case ACTIVITY_FORTIFIED:
1695 case ACTIVITY_LAST:
1696 log_error("Activity %d is not supposed to appear in unit orders",
1697 order->activity);
1698 break;
1699 }
1700 }
1701}
1702
1703/************************************************************************/
1707{
1708 switch (dir) {
1709 case DIR8_NORTH:
1710 return DIR8_SOUTH;
1711 case DIR8_NORTHEAST:
1712 return DIR8_SOUTHWEST;
1713 case DIR8_EAST:
1714 return DIR8_WEST;
1715 case DIR8_SOUTHEAST:
1716 return DIR8_NORTHWEST;
1717 case DIR8_SOUTH:
1718 return DIR8_NORTH;
1719 case DIR8_SOUTHWEST:
1720 return DIR8_NORTHEAST;
1721 case DIR8_WEST:
1722 return DIR8_EAST;
1723 case DIR8_NORTHWEST:
1724 return DIR8_SOUTHEAST;
1725 }
1726
1727 return DIR8_ORIGIN;
1728}
1729
1730/************************************************************************/
1734{
1735 int i;
1736 struct tile *current_tile;
1737 struct tile *tgt_tile;
1738
1739 if (!unit_has_orders(act_unit)) {
1740 return;
1741 }
1742
1743 /* The order index is for the unit at its current tile. */
1744 current_tile = unit_tile(act_unit);
1745
1746 /* Rewind to the beginning of the orders */
1747 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1748 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1749
1750 if (!(prev_order->order == ORDER_PERFORM_ACTION
1754 current_tile = mapstep(&(wld.map), current_tile,
1755 dir_opposite(prev_order->dir));
1756 }
1757 }
1758
1759 /* Upgrade to explicit target tile */
1760 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1761 struct unit_order *order = &act_unit->orders.list[i];
1762
1763 if (order->order == ORDER_PERFORM_ACTION
1764 && order->target != NO_TARGET) {
1765 /* The target is already specified in the new format. */
1766
1767 /* The index_to_tile() call has no side-effects that we
1768 * would want also in NDEBUG builds. */
1769 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1770 return;
1771 }
1772
1773 if (!direction8_is_valid(order->dir)) {
1774 /* The target of the action is on the actor's tile. */
1775 tgt_tile = current_tile;
1776 } else {
1777 /* The target of the action is on a tile next to the actor. */
1778 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1779 }
1780
1781 if (order->order == ORDER_PERFORM_ACTION) {
1782 if (tgt_tile != NULL) {
1783 struct action *paction = action_by_number(order->action);
1784
1785 order->target = tgt_tile->index;
1786 /* Leave no traces. */
1787 order->dir = DIR8_ORIGIN;
1788
1790 /* The action moves the unit to the target tile (unless this is the
1791 * final order) */
1794 || i == act_unit->orders.length - 1);
1795 current_tile = tgt_tile;
1796 }
1797 } else {
1798 current_tile = NULL;
1799 }
1800 } else {
1801 current_tile = tgt_tile;
1802 }
1803 }
1804
1805 if (current_tile == NULL) {
1806 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1808 }
1809}
1810
1811/************************************************************************/
1815{
1816 players_iterate_alive(pplayer) {
1817 unit_list_iterate(pplayer->units, punit) {
1820 }
1823}
1824
1825/************************************************************************/
1830{
1831 /* Check status and return if not OK (sg_success FALSE). */
1832 sg_check_ret();
1833
1834 /* Action orders were new in 3.0 */
1835 if (format_class == SAVEGAME_3) {
1836 /* Only 3.0 savegames may have "Attack" action orders. */
1837 players_iterate_alive(pplayer) {
1838 unit_list_iterate(pplayer->units, punit) {
1839 int i;
1840
1841 if (!punit->has_orders) {
1842 continue;
1843 }
1844
1846 || punit->orders.list != NULL, continue);
1847
1848 for (i = 0; i < punit->orders.length; i++) {
1849 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1855 }
1856
1857 /* Production targeted actions were split from building targeted
1858 * actions in 3.1. The building sub target encoding changed. */
1860 && ((punit->orders.list[i].action
1862 || (punit->orders.list[i].action
1864 punit->orders.list[i].sub_target -= 1;
1865 }
1867 && (punit->orders.list[i].action
1869 && punit->orders.list[i].sub_target == -1) {
1872 }
1874 && (punit->orders.list[i].action
1876 && punit->orders.list[i].sub_target == -1) {
1879 }
1880 }
1883 }
1884
1885 /* Explicit server side agent was new in 3.1 */
1887
1888 /* Some activities should only be ordered in action orders. */
1889 players_iterate_alive(pplayer) {
1890 unit_list_iterate(pplayer->units, punit) {
1894
1895 /* Unit order action target isn't dir anymore */
1896 players_iterate_alive(pplayer) {
1897 unit_list_iterate(pplayer->units, punit) {
1901
1902 /* Backward compatibility: if we had any open-ended orders (pillage)
1903 * in the savegame, assign specific targets now */
1904 players_iterate_alive(pplayer) {
1905 unit_list_iterate(pplayer->units, punit) {
1907 &punit->activity,
1911}
1912
1913/************************************************************************/
1921{
1922 int i;
1923 int count;
1924 int set_count;
1925 bool gamestart_valid = FALSE;
1926
1927 /* Check status and return if not OK (sg_success FALSE). */
1928 sg_check_ret();
1929
1930 log_debug("Upgrading data from savegame to version 3.2.0");
1931
1932 {
1933 const char *str = secfile_lookup_str_default(loading->file, NULL,
1934 "savefile.orig_version");
1935
1936 if (str == NULL) {
1937 /* Make sure CURRENTLY running version does not
1938 * end as orig_version when we resave. */
1939 if (format_class == SAVEGAME_3) {
1940 secfile_insert_str(loading->file, "old savegame3, or older",
1941 "savefile.orig_version");
1942 } else {
1944
1945 secfile_insert_str(loading->file, "savegame2, or older",
1946 "savefile.orig_version");
1947 }
1948 }
1949 }
1950
1951 {
1952 int action_count;
1953
1955 "savefile.action_size");
1956
1957 if (action_count > 0) {
1958 const char **modname;
1959 const char **savemod;
1960 int j;
1961 const char *dur_name = "Transport Deboard";
1962 const char *clean_name = "Clean";
1963
1964 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1965 "savefile.action_vector");
1966
1968
1969 for (j = 0; j < action_count; j++) {
1970 if (!fc_strcasecmp("Transport Alight", modname[j])) {
1971 savemod[j] = dur_name;
1972 } else if (!fc_strcasecmp("Clean Pollution", modname[j])
1973 || !fc_strcasecmp("Clean Fallout", modname[j])) {
1974 savemod[j] = clean_name;
1975 } else {
1976 savemod[j] = modname[j];
1977 }
1978 }
1979
1981 "savefile.action_vector");
1982
1983 free(savemod);
1984 }
1985 }
1986
1987 {
1988 int activities_count;
1989
1991 "savefile.activities_size");
1992
1993 if (activities_count > 0) {
1994 const char **modname;
1995 const char **savemod;
1996 int j;
1997 const char *clean_name = "Clean";
1998
1999 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2000 "savefile.activities_vector");
2001
2003
2004 for (j = 0; j < activities_count; j++) {
2005 if (!fc_strcasecmp("Pollution", modname[j])
2006 || !fc_strcasecmp("Fallout", modname[j])) {
2007 savemod[j] = clean_name;
2008 } else {
2009 savemod[j] = modname[j];
2010 }
2011 }
2012
2014 "savefile.activities_vector");
2015
2016 free(savemod);
2017 }
2018 }
2019
2020 /* Server setting migration. */
2021 {
2022 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2023 int alltemperate_idx = -1, singlepole_idx = -1;
2024 bool count_changed = FALSE;
2025
2028 "settings.gamestart_valid");
2029
2030 for (i = 0; i < set_count; i++) {
2031 const char *old_name
2032 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
2033 const char *name;
2034
2035 if (!old_name) {
2036 continue;
2037 }
2038
2040
2041 if (fc_strcasecmp(old_name, name)) {
2042 /* Setting's name changed */
2043 secfile_replace_str(loading->file, name, "settings.set%d.name", i);
2044 }
2045
2046 if (!gamestart_valid) {
2047 /* Older savegames saved these values even when they were not valid.
2048 * Silence warnings caused by them. */
2049 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2050 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2051 }
2052
2053 if (!fc_strcasecmp("compresstype", name)) {
2054 const char *val = secfile_lookup_str(loading->file,
2055 "settings.set%d.value", i);
2056 if (!fc_strcasecmp(val, "BZIP2")) {
2057#ifdef FREECIV_HAVE_LIBZSTD
2058 secfile_replace_str(loading->file, "ZSTD",
2059 "settings.set%d.value", i);
2060#elif FREECIV_HAVE_LIBLZMA
2061 secfile_replace_str(loading->file, "XZ",
2062 "settings.set%d.value", i);
2063#elif FREECIV_HAVE_LIBZ
2064 secfile_replace_str(loading->file, "LIBZ",
2065 "settings.set%d.value", i);
2066#else
2067 secfile_replace_str(loading->file, "PLAIN",
2068 "settings.set%d.value", i);
2069#endif
2070 }
2071
2072 if (gamestart_valid) {
2073 val = secfile_lookup_str(loading->file,
2074 "settings.set%d.gamestart", i);
2075 if (!fc_strcasecmp(val, "BZIP2")) {
2076#ifdef FREECIV_HAVE_LIBZSTD
2077 secfile_replace_str(loading->file, "ZSTD",
2078 "settings.set%d.gamestart", i);
2079#elif FREECIV_HAVE_LIBLZMA
2080 secfile_replace_str(loading->file, "XZ",
2081 "settings.set%d.gamestart", i);
2082#elif FREECIV_HAVE_LIBZ
2083 secfile_replace_str(loading->file, "LIBZ",
2084 "settings.set%d.gamestart", i);
2085#else
2086 secfile_replace_str(loading->file, "PLAIN",
2087 "settings.set%d.gamestart", i);
2088#endif
2089 }
2090 }
2091 } else if (!fc_strcasecmp("topology", name)) {
2092 struct setting *pset = setting_by_name(name);
2093 struct sf_cb_data info = { pset, TRUE };
2094 int val;
2095
2096 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2098 "settings.set%d.value", i)) {
2099 char wrap[100];
2100 char buf[100];
2101
2102 if (val & TF_OLD_WRAPX) {
2103 if (val & TF_OLD_WRAPY) {
2104 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2105 } else {
2106 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2107 }
2108 } else if (val & TF_OLD_WRAPY) {
2109 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2110 } else {
2111 fc_strlcpy(wrap, "", sizeof(wrap));
2112 }
2113
2114 if (val & TF_ISO) {
2115 if (val & TF_HEX) {
2116 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2117 } else {
2118 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2119 }
2120 } else if (val & TF_HEX) {
2121 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2122 } else {
2124 }
2125
2126 setting_value_name(pset, FALSE, buf, sizeof(buf));
2128 "settings.set%d.value", i);
2129
2131 "wrap", "settings.set%d.name", set_count);
2133 wrap, "settings.set%d.value", set_count);
2134
2135 if (gamestart_valid) {
2136 if (secfile_lookup_enum_data(loading->file, &val, TRUE,
2138 "settings.set%d.gamestart", i)) {
2139 if (val & TF_OLD_WRAPX) {
2140 if (val & TF_OLD_WRAPY) {
2141 fc_strlcpy(wrap, "WrapX|WrapY", sizeof(wrap));
2142 } else {
2143 fc_strlcpy(wrap, "WrapX", sizeof(wrap));
2144 }
2145 } else if (val & TF_OLD_WRAPY) {
2146 fc_strlcpy(wrap, "WrapY", sizeof(wrap));
2147 } else {
2148 fc_strlcpy(wrap, "", sizeof(wrap));
2149 }
2150
2151 if (val & TF_ISO) {
2152 if (val & TF_HEX) {
2153 setting_bitwise_set(pset, "ISO|HEX", NULL, NULL, 0);
2154 } else {
2155 setting_bitwise_set(pset, "ISO", NULL, NULL, 0);
2156 }
2157 } else if (val & TF_HEX) {
2158 setting_bitwise_set(pset, "HEX", NULL, NULL, 0);
2159 } else {
2161 }
2162
2163 setting_value_name(pset, FALSE, buf, sizeof(buf));
2165 "settings.set%d.gamestart", i);
2166
2168 wrap, "settings.set%d.gamestart", set_count);
2169 }
2170 }
2171
2172 set_count++;
2174 }
2175 } else if (!fc_strcasecmp("alltemperate", name)) {
2177 } else if (!fc_strcasecmp("singlepole", name)) {
2178 singlepole_idx = i;
2179 }
2180 }
2181
2182 if (alltemperate_idx >= 0 || singlepole_idx >= 0) {
2183 int north_latitude, south_latitude;
2184 int north_idx, south_idx;
2186
2187 if (alltemperate_idx < 0
2189 "settings.set%d.value",
2191 /* Infer what would've been the ruleset default */
2193 }
2194
2195 if (singlepole_idx < 0
2197 "settings.set%d.value",
2198 singlepole_idx)) {
2199 /* Infer what would've been the ruleset default */
2201 }
2202
2203 /* Note: hard-coding 1000-based latitudes here; if MAX_LATITUDE ever
2204 * changes, that'll have to be handled in later migrations anyway */
2205 north_latitude = alltemperate ? 500 : 1000;
2206 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2207
2208 /* Replace alltemperate with northlatitude, and singlepole with
2209 * southlatitude. If only one of the two was given, add the other
2210 * at the end. */
2213
2214 secfile_replace_str(loading->file, "northlatitude",
2215 "settings.set%d.name", north_idx);
2216 secfile_replace_int(loading->file, north_latitude,
2217 "settings.set%d.value", north_idx);
2218
2219 secfile_replace_str(loading->file, "southlatitude",
2220 "settings.set%d.name", south_idx);
2221 secfile_replace_int(loading->file, south_latitude,
2222 "settings.set%d.value", south_idx);
2223
2224 if (gamestart_valid) {
2225 if (alltemperate_idx < 0
2227 "settings.set%d.gamestart",
2229 alltemperate =
2231 }
2232
2233 if (singlepole_idx < 0
2235 "settings.set%d.gamestart",
2236 singlepole_idx)) {
2238 }
2239
2240 north_latitude = alltemperate ? 500 : 1000;
2241 south_latitude = alltemperate ? 500 : (singlepole ? 0 : -1000);
2242
2243 secfile_replace_int(loading->file, north_latitude,
2244 "settings.set%d.gamestart", north_idx);
2245 secfile_replace_int(loading->file, south_latitude,
2246 "settings.set%d.gamestart", south_idx);
2247 }
2248
2249 if (alltemperate_idx < 0 || singlepole_idx < 0) {
2250 /* only one was given and replaced ~> we added one new entry */
2251 set_count++;
2253 }
2254 }
2255
2256 if (count_changed) {
2258 "settings.set_count");
2259 }
2260 }
2261 }
2262
2263 {
2264 /* Turn old AI level field to a setting. */
2265 const char *level;
2266 enum ai_level lvl;
2267
2268 level = secfile_lookup_str_default(loading->file, NULL, "game.level");
2269 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
2270 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
2272 } else {
2274 }
2275
2276 if (!ai_level_is_valid(lvl)) {
2277 log_sg("Invalid AI level \"%s\". "
2278 "Changed to \"%s\".", level,
2281 }
2282
2283 secfile_insert_str(loading->file, "ailevel", "settings.set%d.name", set_count);
2284 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.value", set_count);
2285
2286 if (gamestart_valid) {
2287 secfile_insert_enum(loading->file, lvl, ai_level, "settings.set%d.gamestart",
2288 set_count);
2289 }
2290
2291 set_count++;
2292 secfile_replace_int(loading->file, set_count, "settings.set_count");
2293 }
2294
2295 if (format_class != SAVEGAME_2) {
2296 /* Replace got_tech[_multi] bools on free_bulbs integers. */
2297 /* Older savegames had a bug that got_tech_multi was not saved. */
2298 count = secfile_lookup_int_default(loading->file, 0, "research.count");
2299 for (i = 0; i < count; i++) {
2300 bool got_tech = FALSE;
2301 int bulbs = 0;
2302 bool got_tech_multi
2304 "research.r%d.got_tech_multi", i);
2305
2307 "research.r%d.got_tech", i)
2308 && secfile_lookup_int(loading->file, &bulbs,
2309 "research.r%d.bulbs", i)) {
2311 got_tech || got_tech_multi ? bulbs : 0,
2312 "research.r%d.free_bulbs", i);
2313 }
2314 }
2315 }
2316
2317 /* Older savegames unnecessarily saved diplstate type order.
2318 * Silence "unused entry" warnings about those. */
2319 {
2321 "savefile.diplstate_type_size");
2322
2323 for (i = 0; i < dscount; i++) {
2325 "savefile.diplstate_type_vector,%d", i);
2326 }
2327 }
2328
2329 /* Add wl_max_length entries for players */
2330 {
2331 player_slots_iterate(pslot) {
2332 int plrno = player_slot_index(pslot);
2333 int ncities;
2334 int cnro;
2335 size_t wlist_max_length = 0;
2336 bool first_city;
2337
2338 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2339 continue;
2340 }
2341
2343 "player%d.got_first_city",
2344 plrno);
2345 if (first_city) {
2346 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2347 int flagcount = 0;
2348 const char **flags_sg;
2349 size_t nval;
2350
2352
2354 "player%d.flags", plrno);
2355
2356 for (i = 0; i < nval; i++) {
2359
2361 }
2362
2364 "player%d.flags", plrno);
2365
2367 }
2368
2370 "player%d.ncities", plrno);
2371
2372 for (cnro = 0; cnro < ncities; cnro++) {
2374 "player%d.c%d.wl_length",
2375 plrno, cnro);
2376
2378
2379 if (format_class == SAVEGAME_3) {
2381 "player%d.c%d.original",
2382 plrno, cnro) != plrno) {
2384 "player%d.c%d.acquire_t",
2385 plrno, cnro);
2386 } else {
2388 "player%d.c%d.acquire_t",
2389 plrno, cnro);
2390 }
2391
2393 "player%d.c%d.wlcb",
2394 plrno, cnro);
2395 }
2396 }
2397
2399 "player%d.wl_max_length", plrno);
2400
2401 if (format_class == SAVEGAME_3) {
2402 int nunits;
2403 int unro;
2404 size_t olist_max_length = 0;
2405
2407 "player%d.nunits", plrno);
2408
2409 for (unro = 0; unro < nunits; unro++) {
2411 "player%d.u%d.orders_length",
2412 plrno, unro);
2413
2415 }
2416
2418 "player%d.orders_max_length", plrno);
2419
2421 "player%d.routes_max_length", plrno);
2422 }
2423
2425 }
2426}
2427
2428/************************************************************************/
2436{
2437 /* Check status and return if not OK (sg_success != TRUE). */
2438 sg_check_ret();
2439
2440 log_debug("Upgrading data from savegame to version 3.3.0");
2441
2442 /* World Peace has never started in the old savegame. */
2443 game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
2444
2445 if (format_class != SAVEGAME_2) {
2446 secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
2447
2448 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2449 }
2450
2451 /* Last turn change time as a float, not integer multiplied by 100 */
2452 {
2453 float tct = secfile_lookup_int_default(loading->file, 0,
2454 "game.last_turn_change_time") / 100.0;
2455
2456 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2457 }
2458
2459 {
2460 int ssa_count;
2461
2463 "savefile.server_side_agent_size");
2464 if (ssa_count > 0) {
2465 const char **modname;
2466 const char **savemod;
2467 int j;
2468 const char *aw_name = "AutoWorker";
2469
2470 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2471 "savefile.server_side_agent_list");
2472
2473 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2474
2475 for (j = 0; j < ssa_count; j++) {
2476 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2477 savemod[j] = aw_name;
2478 } else {
2479 savemod[j] = modname[j];
2480 }
2481 }
2482
2484 "savefile.server_side_agent_list");
2485
2486 free(savemod);
2487 }
2488 }
2489
2490 {
2491 int action_count;
2492
2494 "savefile.action_size");
2495
2496 if (action_count > 0) {
2497 const char **modname;
2498 const char **savemod;
2499 int j;
2500 const char *cc1_name = "Conquer City Shrink";
2501 const char *cc2_name = "Conquer City Shrink 2";
2502 const char *cc3_name = "Conquer City Shrink 3";
2503 const char *cc4_name = "Conquer City Shrink 4";
2504
2505 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2506 "savefile.action_vector");
2507
2509
2510 for (j = 0; j < action_count; j++) {
2511 if (!fc_strcasecmp("Conquer City", modname[j])) {
2512 savemod[j] = cc1_name;
2513 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
2514 savemod[j] = cc2_name;
2515 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
2516 savemod[j] = cc3_name;
2517 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
2518 savemod[j] = cc4_name;
2519 } else {
2520 savemod[j] = modname[j];
2521 }
2522 }
2523
2525 "savefile.action_vector");
2526
2527 free(savemod);
2528 }
2529 }
2530
2531 /* Add actions for unit activities */
2532 if (format_class == SAVEGAME_3) {
2533 loading->activities.size
2535 "savefile.activities_size");
2536 if (loading->activities.size) {
2537 loading->activities.order
2538 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2539 "savefile.activities_vector");
2540 sg_failure_ret(loading->activities.size != 0,
2541 "Failed to load activity order: %s",
2542 secfile_error());
2543 }
2544
2545 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2546 "savefile.action_size");
2547
2548 sg_failure_ret(loading->action.size > 0,
2549 "Failed to load action order: %s",
2550 secfile_error());
2551
2552 if (loading->action.size) {
2553 const char **modname;
2554 int j;
2555
2556 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2557 "savefile.action_vector");
2558
2559 loading->action.order = fc_calloc(loading->action.size,
2560 sizeof(*loading->action.order));
2561
2562 for (j = 0; j < loading->action.size; j++) {
2564
2565 if (real_action != nullptr) {
2566 loading->action.order[j] = real_action->id;
2567 } else {
2568 log_sg("Unknown action \'%s\'", modname[j]);
2569 loading->action.order[j] = ACTION_NONE;
2570 }
2571 }
2572
2573 free(modname);
2574 }
2575
2576 player_slots_iterate(pslot) {
2577 int plrno = player_slot_index(pslot);
2578 int nunits;
2579 int unro;
2580
2581 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2582 continue;
2583 }
2584
2586 "player%d.nunits", plrno);
2587
2588 for (unro = 0; unro < nunits; unro++) {
2589 int ei;
2590 int i;
2591 enum unit_activity activity;
2592 enum gen_action act;
2593
2595 "player%d.u%d.activity", plrno, unro);
2596
2597 if (ei >= 0 && ei < loading->activities.size) {
2598 bool found = FALSE;
2599
2600 activity = unit_activity_by_name(loading->activities.order[ei],
2602
2603 act = activity_default_action(activity);
2604
2605 for (i = 0; i < loading->action.size; i++) {
2606 if (act == loading->action.order[i]) {
2607 secfile_insert_int(loading->file, i, "player%d.u%d.action",
2608 plrno, unro);
2609 found = TRUE;
2610 break;
2611 }
2612 }
2613
2614 if (!found) {
2615 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
2616 plrno, unro);
2617 }
2618 }
2619 }
2621 }
2622
2623 /* Researches */
2624 {
2625 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
2626 int i;
2627
2628 for (i = 0; i < count; i++) {
2629 /* It's ok for old savegames to have these entries. */
2630 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
2631 }
2632 }
2633
2634 player_slots_iterate(pslot) {
2635 int plrno = player_slot_index(pslot);
2636 int ncities;
2637 int cnro;
2638
2639 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2640 continue;
2641 }
2642
2644 "player%d.dc_total", plrno);
2645
2646 for (cnro = 0; cnro < ncities; cnro++) {
2647 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
2648 plrno, cnro);
2649 }
2651}
2652
2653/************************************************************************/
2661{
2662 /* Check status and return if not OK (sg_success != TRUE). */
2663 sg_check_ret();
2664
2665 log_debug("Upgrading data from savegame to version 3.4.0");
2666}
2667
2668/************************************************************************/
2672#ifdef FREECIV_DEV_SAVE_COMPAT
2673static void compat_load_dev(struct loaddata *loading)
2674{
2675 int game_version;
2676
2677 /* Check status and return if not OK (sg_success FALSE). */
2678 sg_check_ret();
2679
2680 log_verbose("Upgrading data between development revisions");
2681
2682 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2683 "No save version found");
2684
2685#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
2686
2687 if (game_version < 3029100) {
2688 /* Before version number bump to 3.2.91, September 2023 */
2689
2690 {
2691 const char *str = secfile_lookup_str_default(loading->file, NULL,
2692 "savefile.orig_version");
2693
2694 if (str == NULL) {
2695 /* Make sure CURRENTLY running version does not
2696 * end as orig_version when we resave. */
2697 secfile_insert_str(loading->file, "old savegame3, or older",
2698 "savefile.orig_version");
2699 }
2700 }
2701
2702 /* Add acquire_t entries for cities */
2703 {
2704 player_slots_iterate(pslot) {
2705 int plrno = player_slot_index(pslot);
2706 int ncities;
2707 int cnro;
2708 bool first_city;
2709
2710 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2711 continue;
2712 }
2713
2715 "player%d.got_first_city",
2716 plrno);
2717 if (first_city) {
2718 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2719 int flagcount = 0;
2720 const char **flags_sg;
2721 size_t nval;
2722 int i;
2723
2725
2727 "player%d.flags", plrno);
2728
2729 for (i = 0; i < nval; i++) {
2732
2734 }
2735
2737 "player%d.flags", plrno);
2738
2740 }
2741
2743 "player%d.ncities", plrno);
2744
2745 for (cnro = 0; cnro < ncities; cnro++) {
2746 if (secfile_entry_lookup(loading->file,
2747 "player%d.c%d.acquire_t",
2748 plrno, cnro) == NULL) {
2750 "player%d.c%d.original",
2751 plrno, cnro) != plrno) {
2753 "player%d.c%d.acquire_t",
2754 plrno, cnro);
2755 } else {
2757 "player%d.c%d.acquire_t",
2758 plrno, cnro);
2759 }
2760 }
2761 if (secfile_entry_lookup(loading->file,
2762 "player%d.c%d.wlcb",
2763 plrno, cnro) == NULL) {
2765 "player%d.c%d.wlcb",
2766 plrno, cnro);
2767 }
2768 }
2770 }
2771
2772 /* Add orders_max_length entries for players */
2773 {
2774 player_slots_iterate(pslot) {
2775 int plrno = player_slot_index(pslot);
2776
2777 if (secfile_section_lookup(loading->file, "player%d", plrno) != NULL
2779 "player%d.orders_max_length", plrno)
2780 == NULL) {
2781 size_t nunits;
2782 int unro;
2783 size_t olist_max_length = 0;
2784
2786 "player%d.nunits", plrno);
2787
2788 for (unro = 0; unro < nunits; unro++) {
2789 int ol_length
2791 "player%d.u%d.orders_length",
2792 plrno, unro);
2793
2795 }
2796
2798 "player%d.orders_max_length", plrno);
2799 }
2801 }
2802
2803 {
2804 int action_count;
2805
2807 "savefile.action_size");
2808
2809 if (action_count > 0) {
2810 const char **modname;
2811 const char **savemod;
2812 int j;
2813 const char *clean_name = "Clean";
2814
2815 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2816 "savefile.action_vector");
2817
2819
2820 for (j = 0; j < action_count; j++) {
2821 if (!fc_strcasecmp("Clean Pollution", modname[j])
2822 || !fc_strcasecmp("Clean Fallout", modname[j])) {
2823 savemod[j] = clean_name;
2824 } else {
2825 savemod[j] = modname[j];
2826 }
2827 }
2828
2830 "savefile.action_vector");
2831
2832 free(savemod);
2833 }
2834 }
2835
2836 {
2837 int activities_count;
2838
2840 "savefile.activities_size");
2841
2842 if (activities_count > 0) {
2843 const char **modname;
2844 const char **savemod;
2845 int j;
2846 const char *clean_name = "Clean";
2847
2848 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2849 "savefile.activities_vector");
2850
2852
2853 for (j = 0; j < activities_count; j++) {
2854 if (!fc_strcasecmp("Pollution", modname[j])
2855 || !fc_strcasecmp("Fallout", modname[j])) {
2856 savemod[j] = clean_name;
2857 } else {
2858 savemod[j] = modname[j];
2859 }
2860 }
2861
2863 "savefile.activities_vector");
2864
2865 free(savemod);
2866 }
2867 }
2868
2869 /* Server setting migration. */
2870 {
2871 int set_count;
2872
2873 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2874 bool gamestart_valid = FALSE;
2875
2878 "settings.gamestart_valid");
2879
2880 if (!gamestart_valid) {
2881 int i;
2882
2883 /* Older savegames saved gamestart values even when they were not valid.
2884 * Silence warnings caused by them. */
2885 for (i = 0; i < set_count; i++) {
2886 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2887 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2888 }
2889 }
2890 }
2891 }
2892
2893 {
2894 int ssa_count;
2895
2897 "savefile.server_side_agent_size");
2898 if (ssa_count > 0) {
2899 const char **modname;
2900 const char **savemod;
2901 int j;
2902 const char *aw_name = "AutoWorker";
2903
2904 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2905 "savefile.server_side_agent_list");
2906
2907 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2908
2909 for (j = 0; j < ssa_count; j++) {
2910 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2911 savemod[j] = aw_name;
2912 } else {
2913 savemod[j] = modname[j];
2914 }
2915 }
2916
2918 "savefile.server_side_agent_list");
2919
2920 free(savemod);
2921 }
2922 }
2923
2924 } /* Version < 3.2.91 */
2925
2926 if (game_version < 3029200) {
2927 /* Before version number bump to 3.2.92, June 2024 */
2928
2929 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2930
2931 /* World Peace has never started in the old savegame. */
2932 game.info.turn
2933 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2936 "game.world_peace_start");
2938 "game.world_peace_start");
2939
2940 /* Last turn change time as a float, not integer multiplied by 100 */
2941 {
2942 float tct = secfile_lookup_int_default(loading->file, 0,
2943 "game.last_turn_change_time") / 100.0;
2944
2945 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2946 }
2947
2948 /* Add actions for unit activities */
2949 loading->activities.size
2951 "savefile.activities_size");
2952 if (loading->activities.size) {
2953 loading->activities.order
2954 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2955 "savefile.activities_vector");
2956 sg_failure_ret(loading->activities.size != 0,
2957 "Failed to load activity order: %s",
2958 secfile_error());
2959 }
2960
2961 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2962 "savefile.action_size");
2963
2964 sg_failure_ret(loading->action.size > 0,
2965 "Failed to load action order: %s",
2966 secfile_error());
2967
2968 if (loading->action.size) {
2969 const char **modname;
2970 int j;
2971
2972 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2973 "savefile.action_vector");
2974
2975 loading->action.order = fc_calloc(loading->action.size,
2976 sizeof(*loading->action.order));
2977
2978 for (j = 0; j < loading->action.size; j++) {
2980
2981 if (real_action) {
2982 loading->action.order[j] = real_action->id;
2983 } else {
2984 log_sg("Unknown action \'%s\'", modname[j]);
2985 loading->action.order[j] = ACTION_NONE;
2986 }
2987 }
2988
2989 free(modname);
2990 }
2991
2992 player_slots_iterate(pslot) {
2993 int plrno = player_slot_index(pslot);
2994 int nunits;
2995 int unro;
2996
2997 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
2998 continue;
2999 }
3000
3002 "player%d.nunits", plrno);
3003
3004 for (unro = 0; unro < nunits; unro++) {
3005 int ei;
3006 int i;
3007 enum unit_activity activity;
3008 enum gen_action act;
3009
3011 "player%d.u%d.activity", plrno, unro);
3012
3013 if (ei >= 0 && ei < loading->activities.size) {
3014 bool found = FALSE;
3015
3016 activity = unit_activity_by_name(loading->activities.order[ei],
3018 act = activity_default_action(activity);
3019
3020 for (i = 0; i < loading->action.size; i++) {
3021 if (act == loading->action.order[i]) {
3022 secfile_insert_int(loading->file, i, "player%d.u%d.action",
3023 plrno, unro);
3024 found = TRUE;
3025 break;
3026 }
3027 }
3028
3029 if (!found) {
3030 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
3031 plrno, unro);
3032 }
3033 }
3034 }
3036
3037 /* Researches */
3038 {
3039 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
3040 int i;
3041
3042 for (i = 0; i < count; i++) {
3043 /* It's ok for old savegames to have these entries. */
3044 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
3045 }
3046 }
3047
3048 } /* Version < 3.2.92 */
3049
3050 if (game_version < 3029300) {
3051 /* Before version number bump to 3.2.93 */
3052
3053 {
3054 int action_count;
3055
3057 "savefile.action_size");
3058
3059 if (action_count > 0) {
3060 const char **modname;
3061 const char **savemod;
3062 int j;
3063 const char *cc1_name = "Conquer City Shrink";
3064 const char *cc2_name = "Conquer City Shrink 2";
3065 const char *cc3_name = "Conquer City Shrink 3";
3066 const char *cc4_name = "Conquer City Shrink 4";
3067
3068 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3069 "savefile.action_vector");
3070
3072
3073 for (j = 0; j < action_count; j++) {
3074 if (!fc_strcasecmp("Conquer City", modname[j])) {
3075 savemod[j] = cc1_name;
3076 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
3077 savemod[j] = cc2_name;
3078 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
3079 savemod[j] = cc3_name;
3080 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
3081 savemod[j] = cc4_name;
3082 } else {
3083 savemod[j] = modname[j];
3084 }
3085 }
3086
3088 "savefile.action_vector");
3089
3090 free(savemod);
3091 }
3092 }
3093
3094 player_slots_iterate(pslot) {
3095 int plrno = player_slot_index(pslot);
3096 int ncities;
3097 int cnro;
3098
3099 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3100 continue;
3101 }
3102
3104 "player%d.dc_total", plrno);
3105
3106 for (cnro = 0; cnro < ncities; cnro++) {
3107 if (!secfile_entry_lookup(loading->file, "player%d.dc%d.original",
3108 plrno, cnro)) {
3109 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
3110 plrno, cnro);
3111 }
3112 }
3114 } /* Version < 3.2.93 */
3115
3116#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3117
3118#ifdef FREECIV_DEV_SAVE_COMPAT_3_4
3119
3120 if (game_version < 3039100) {
3121 /* Before version number bump to 3.3.91 */
3122
3123 } /* Version < 3.3.91 */
3124
3125#endif /* FREECIV_DEV_SAVE_COMPAT_3_4 */
3126}
3127
3128/************************************************************************/
3132static void compat_post_load_dev(struct loaddata *loading)
3133{
3134 int game_version;
3135
3136 /* Check status and return if not OK (sg_success FALSE). */
3137 sg_check_ret();
3138
3139 if (!secfile_lookup_int(loading->file, &game_version, "scenario.game_version")) {
3140 game_version = 2060000;
3141 }
3142
3143#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
3144
3145 if (game_version < 3029100) {
3146 /* Before version number bump to 3.2.91 */
3147
3148 } /* Version < 3.2.91 */
3149
3150#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
3151}
3152#endif /* FREECIV_DEV_SAVE_COMPAT */
3153
3154/************************************************************************/
3157enum ai_level ai_level_convert(int old_level)
3158{
3159 switch (old_level) {
3160 case 1:
3161 return AI_LEVEL_AWAY;
3162 case 2:
3163 return AI_LEVEL_NOVICE;
3164 case 3:
3165 return AI_LEVEL_EASY;
3166 case 5:
3167 return AI_LEVEL_NORMAL;
3168 case 7:
3169 return AI_LEVEL_HARD;
3170 case 8:
3171 return AI_LEVEL_CHEATING;
3172 case 10:
3173#ifdef FREECIV_DEBUG
3174 return AI_LEVEL_EXPERIMENTAL;
3175#else /* FREECIV_DEBUG */
3176 return AI_LEVEL_HARD;
3177#endif /* FREECIV_DEBUG */
3178 }
3179
3180 return ai_level_invalid();
3181}
3182
3183/************************************************************************/
3186enum barbarian_type barb_type_convert(int old_type)
3187{
3188 switch (old_type) {
3189 case 0:
3190 return NOT_A_BARBARIAN;
3191 case 1:
3192 return LAND_BARBARIAN;
3193 case 2:
3194 return SEA_BARBARIAN;
3195 }
3196
3197 return barbarian_type_invalid();
3198}
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:396
#define action_iterate_end
Definition actions.h:214
#define action_get_activity(_pact_)
Definition actions.h:460
#define action_iterate(_act_)
Definition actions.h:210
#define ACTION_NONE
Definition actions.h:55
struct @129::my_agent entries[MAX_AGENTS]
@ BODYGUARD_NONE
Definition aiguard.c:37
const char * default_ai_type_name(void)
Definition aiiface.c:264
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
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:213
#define EC_SPECIAL
Definition fc_types.h:822
revolen_type
Definition fc_types.h:991
@ REVOLEN_RANDOM
Definition fc_types.h:993
@ REVOLEN_RANDQUICK
Definition fc_types.h:995
@ REVOLEN_FIXED
Definition fc_types.h:992
@ REVOLEN_QUICKENING
Definition fc_types.h:994
#define DIR8_ORIGIN
Definition fc_types.h:314
#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:739
#define GAME_DEFAULT_SCORETURN
Definition game.h:583
#define GAME_DEFAULT_SAVETURNS
Definition game.h:681
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:567
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:699
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c: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
const char * secfile_error(void)
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
bool secfile_entry_delete(struct section_file *secfile, const char *path,...)
bool entry_set_name(struct entry *pentry, const char *name)
bool secfile_lookup_enum_data(const struct section_file *secfile, int *pvalue, bool bitwise, secfile_enum_name_data_fn_t name_fn, secfile_data_t data, const char *path,...)
const struct entry_list * section_entries(const struct section *psection)
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
const char * entry_name(const struct entry *pentry)
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
struct section * secfile_section_by_name(const struct section_file *secfile, const char *name)
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
#define secfile_replace_str_vec(secfile, strings, dim, path,...)
#define secfile_insert_int(secfile, value, path,...)
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
entry_type
@ ENTRY_FILEREFERENCE
@ ENTRY_LONG_COMMENT
@ ENTRY_INT
@ ENTRY_FLOAT
@ ENTRY_STR
@ ENTRY_ILLEGAL
@ ENTRY_BOOL
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
#define secfile_replace_int(secfile, value, path,...)
#define entry_list_iterate_end
#define secfile_entry_ignore(_sfile_, _fmt_,...)
#define secfile_insert_str(secfile, string, path,...)
#define secfile_insert_bool(secfile, value, path,...)
#define secfile_replace_str(secfile, string, path,...)
#define entry_list_iterate(entlist, pentry)
#define secfile_replace_float(secfile, value, path,...)
#define secfile_replace_bool(secfile, value, path,...)
const void * secfile_data_t
static void compat_post_load_030100(struct loaddata *loading, enum sgf_version format_class)
struct extra_type * resource_by_identifier(const char identifier)
Definition savecompat.c:331
int current_compat_ver(void)
Definition savecompat.c:230
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:270
bool sg_success
Definition savecompat.c:34
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:568
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:36
static struct compatibility compat[]
Definition savecompat.c:114
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:349
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:240
static const int compat_num
Definition savecompat.c:141
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:711
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:94
int char2num(char ch)
Definition savecompat.c:276
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:151
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:692
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:252
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:317
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:585
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:291
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:202
static void compat_load_030400(struct loaddata *loading, enum sgf_version format_class)
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:307
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:142
#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: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
int world_peace_start
Definition game.h:241
struct packet_game_info info
Definition game.h:89
struct civ_game::@32::@36 server
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@43::@45 server
int huts_absolute
Definition map_types.h:108
const load_version_func_t post_load
Definition savecompat.c:99
const load_version_func_t load
Definition savecompat.c:98
struct name_translation name
Definition specialist.h:31
Definition tile.h:50
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int length
Definition unit.h:198
bool has_orders
Definition unit.h:196
struct unit::@82 orders
enum unit_activity activity
Definition unit.h:159
struct extra_type * activity_target
Definition unit.h:167
struct unit_order * list
Definition unit.h:201
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
#define terrain_type_iterate(_p)
Definition terrain.h:266
#define terrain_type_iterate_end
Definition terrain.h:272
void free_unit_orders(struct unit *punit)
Definition unit.c:1806
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:383
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2930
bool unit_has_orders(const struct unit *punit)
Definition unit.c:202
#define unit_tile(_pu)
Definition unit.h:404
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1082
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Definition unittype.c: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