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
90#ifdef FREECIV_DEV_SAVE_COMPAT
91static void compat_load_dev(struct loaddata *loading);
92static void compat_post_load_dev(struct loaddata *loading);
93#endif /* FREECIV_DEV_SAVE_COMPAT */
94
96
102
103/* The struct below contains the information about the savegame versions. It
104 * is identified by the version number (first element), which should be
105 * steadily increasing. It is saved as 'savefile.version'. The support
106 * string (first element of 'name') is not saved in the savegame; it is
107 * saved in settings files (so, once assigned, cannot be changed). The
108 * 'pretty' string (second element of 'name') can be changed if necessary
109 * For changes in the development version, edit the definitions above and
110 * add the needed code to load the old version below. Thus, old
111 * savegames can still be loaded while the main definition
112 * represents the current state of the art. */
113/* While developing freeciv 3.3.0, add the compatibility functions to
114 * - compat_load_030300 to load old savegame. */
115static struct compatibility compat[] = {
116 /* dummy; equal to the current version (last element) */
117 { 0, NULL, NULL },
118 /* version 1 and 2 is not used */
119 /* version 3: first savegame2 format, so no compat functions for translation
120 * from previous format */
121 { 3, NULL, NULL },
122 /* version 4 to 9 are reserved for possible changes in 2.3.x */
123 { 10, compat_load_020400, NULL },
124 /* version 11 to 19 are reserved for possible changes in 2.4.x */
125 { 20, compat_load_020500, NULL },
126 /* version 21 to 29 are reserved for possible changes in 2.5.x */
127 { 30, compat_load_020600, NULL },
128 /* version 31 to 39 are reserved for possible changes in 2.6.x */
129 { 40, compat_load_030000, NULL },
130 /* version 41 to 49 are reserved for possible changes in 3.0.x */
132 /* version 51 to 59 are reserved for possible changes in 3.1.x */
133 { 60, compat_load_030200, NULL },
134 /* version 61 to 69 are reserved for possible changes in 3.2.x */
136 /* Current savefile version is listed above this line; it corresponds to
137 the definitions in this file. */
138};
139
140static const int compat_num = ARRAY_SIZE(compat);
141#define compat_current (compat_num - 1)
142
143/************************************************************************/
151{
152 int i;
153
154 /* Check status and return if not OK (sg_success FALSE). */
155 sg_check_ret();
156
157 loading->version = secfile_lookup_int_default(loading->file, -1,
158 "savefile.version");
159#ifdef FREECIV_DEBUG
160 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
161 loading->version);
162 if (loading->version > compat[compat_current].version) {
163 /* Debug build can (TRY TO!) load newer versions but ... */
164 log_error("Savegame version newer than this build found (%d > %d). "
165 "Trying to load the game nevertheless ...", loading->version,
167 }
168#else /* FREECIV_DEBUG */
169 sg_failure_ret(0 < loading->version
170 && loading->version <= compat[compat_current].version,
171 "Unknown savefile format version (%d).", loading->version);
172#endif /* FREECIV_DEBUG */
173
174
175 for (i = 0; i < compat_num; i++) {
176 if (loading->version < compat[i].version && compat[i].load != NULL) {
177 log_normal(_("Run compatibility function for version: <%d "
178 "(save file: %d; server: %d)."), compat[i].version,
181 }
182 }
183
184#ifdef FREECIV_DEV_SAVE_COMPAT
185 if (loading->version == compat[compat_current].version) {
187 }
188#endif /* FREECIV_DEV_SAVE_COMPAT */
189}
190
191/************************************************************************/
203{
204 int i;
205
206 /* Check status and return if not OK (sg_success FALSE). */
207 sg_check_ret();
208
209 for (i = 0; i < compat_num; i++) {
210 if (loading->version < compat[i].version
211 && compat[i].post_load != NULL) {
212 log_normal(_("Run post load compatibility function for version: <%d "
213 "(save file: %d; server: %d)."), compat[i].version,
216 }
217 }
218
219#ifdef FREECIV_DEV_SAVE_COMPAT
220 if (loading->version == compat[compat_current].version) {
222 }
223#endif /* FREECIV_DEV_SAVE_COMPAT */
224}
225
226/************************************************************************/
230{
232}
233
234/************************************************************************/
239char bin2ascii_hex(int value, int halfbyte_wanted)
240{
241 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
242}
243
244/************************************************************************/
252{
253 const char *pch;
254
255 if (ch == ' ') {
256 /* Sane value. It is unknown if there are savegames out there which
257 * need this fix. Savegame.c doesn't write such savegames
258 * (anymore) since the inclusion into CVS (2000-08-25). */
259 return 0;
260 }
261
263
264 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
265 "Unknown hex value: '%c' %d", ch, ch);
266 return (pch - hex_chars) << (halfbyte * 4);
267}
268
269static const char num_chars[] =
270 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+";
271
272/************************************************************************/
275int char2num(char ch)
276{
277 const char *pch;
278
280
282 "Unknown ascii value for num: '%c' %d", ch, ch);
283
284 return pch - num_chars;
285}
286
287/************************************************************************/
291{
292 int i;
293
294 for (i = 0; special_names[i] != NULL; i++) {
295 if (!strcmp(name, special_names[i])) {
296 return i;
297 }
298 }
299
300 return S_LAST;
301}
302
303/************************************************************************/
307{
308 fc_assert(type >= 0 && type < S_LAST);
309
310 return special_names[type];
311}
312
313/************************************************************************/
317{
319
322 }
323
324 return NULL;
325}
326
327/************************************************************************/
330struct extra_type *resource_by_identifier(const char identifier)
331{
333 if (presource->data.resource->id_old_save == identifier) {
334 return presource;
335 }
337
338 return NULL;
339}
340
341/* =======================================================================
342 * Compatibility functions for loading a game.
343 * ======================================================================= */
344
345/************************************************************************/
350{
351 /* Check status and return if not OK (sg_success FALSE). */
352 sg_check_ret();
353
354 log_debug("Upgrading data from savegame to version 2.4.0");
355
356 /* Add the default player AI. */
357 player_slots_iterate(pslot) {
358 int ncities, i, plrno = player_slot_index(pslot);
359
360 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
361 continue;
362 }
363
365 "player%d.ai_type", player_slot_index(pslot));
366
367 /* Create dummy citizens information. We do not know if citizens are
368 * activated due to the fact that this information
369 * (game.info.citizen_nationality) is not available, but adding the
370 * information does no harm. */
372 "player%d.ncities", plrno);
373 if (ncities > 0) {
374 for (i = 0; i < ncities; i++) {
376 "player%d.c%d.size", plrno, i);
377 if (size > 0) {
379 "player%d.c%d.citizen%d", plrno, i, plrno);
380 }
381 }
382 }
383
385
386 /* Player colors are assigned at the end of player loading, as this
387 * needs information not available here. */
388
389 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
390 * workaround in later 2.3.x); see gna bug #19029.
391 * (The structure of this code is odd as it avoids relying on knowledge of
392 * xsize/ysize, which haven't been extracted from the savefile yet.) */
393 {
394 if (has_capability("knownv2",
395 secfile_lookup_str(loading->file, "savefile.options"))) {
396 /* This savefile contains known information in a sane format.
397 * Just move any entries to where 2.4.x+ expect to find them. */
398 struct section *map = secfile_section_by_name(loading->file, "map");
399
400 if (map != NULL) {
402 const char *name = entry_name(pentry);
403
404 if (!fc_strncmp(name, "kvb", 3)) {
405 /* Rename the "kvb..." entry to "k..." */
406 char *name2 = fc_strdup(name), *newname = name2 + 2;
407
408 *newname = 'k';
409 /* Savefile probably contains existing "k" entries, which are bogus
410 * so we trash them. */
411 secfile_entry_delete(loading->file, "map.%s", newname);
413 FC_FREE(name2);
414 }
416 }
417 /* Could remove "knownv2" from savefile.options, but it's doing
418 * no harm there. */
419 } else {
420 /* This savefile only contains known information in the broken
421 * format. Try to recover it to a sane format. */
422 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
423 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
424 const int maxslots = 128, maxmapsize = 512;
425 const int lines = maxslots/32;
426 int xsize = 0, y, l, j, x;
427 unsigned int known_row_old[lines * maxmapsize],
429 /* Process a map row at a time */
430 for (y = 0; y < maxmapsize; y++) {
431 /* Look for broken info to convert */
432 bool found = FALSE;
434 for (l = 0; l < lines; l++) {
435 for (j = 0; j < 8; j++) {
436 const char *s =
438 "map.k%02d_%04d", l * 8 + j, y);
439 if (s) {
440 found = TRUE;
441 if (xsize == 0) {
442 xsize = strlen(s);
443 }
444 sg_failure_ret(xsize == strlen(s),
445 "Inconsistent xsize in map.k%02d_%04d",
446 l * 8 + j, y);
447 for (x = 0; x < xsize; x++) {
448 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
449 }
450 }
451 }
452 }
453 if (found) {
454 /* At least one entry found for this row. Let's hope they were
455 * all there. */
456 /* Attempt to munge into sane format */
457 int p;
458 memset(known_row, 0, sizeof(known_row));
459 /* Iterate over possible player slots */
460 for (p = 0; p < maxslots; p++) {
461 l = p / 32;
462 for (x = 0; x < xsize; x++) {
463 /* This test causes bit-shifts of >=32 (undefined behavior), but
464 * on common platforms, information happens not to be lost, just
465 * oddly arranged. */
466 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
467 known_row[l * xsize + x] |= (1u << (p - l * 32));
468 }
469 }
470 }
471 /* Save sane format back to memory representation of secfile for
472 * real loading code to pick up */
473 for (l = 0; l < lines; l++) {
474 for (j = 0; j < 8; j++) {
475 /* Save info for all slots (not just used ones). It's only
476 * memory, after all. */
477 char row[xsize+1];
478 for (x = 0; x < xsize; x++) {
479 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
480 }
481 row[xsize] = '\0';
483 "map.k%02d_%04d", l * 8 + j, y);
484 }
485 }
486 }
487 }
488 }
489 }
490
491 /* Server setting migration. */
492 {
493 int set_count;
494
495 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
496 int i, new_opt = set_count;
497 bool gamestart_valid
499 "settings.gamestart_valid");
500
501 for (i = 0; i < set_count; i++) {
502 const char *name
503 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
504
505 if (!name) {
506 continue;
507 }
508
509 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
510 * This is now controlled by the "autosaves" setting. */
511 if (!fc_strcasecmp("saveturns", name)) {
512 /* XXX: Hardcodes details from GAME_AUTOSAVES_DEFAULT
513 * and settings.c:autosaves_name() (but these defaults reflect
514 * 2.3's behavior). */
515 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
516 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
517 int nturns;
518
520 "settings.set%d.value", i)) {
521 if (nturns == 0) {
522 /* Invent a new "autosaves" setting */
524 "settings.set%d.value", new_opt);
525 /* Pick something valid for saveturns */
527 "settings.set%d.value", i);
528 } else {
530 "settings.set%d.value", new_opt);
531 }
532 } else {
533 log_sg("Setting '%s': %s", name, secfile_error());
534 }
535 if (gamestart_valid) {
537 "settings.set%d.gamestart", i)) {
538 if (nturns == 0) {
539 /* Invent a new "autosaves" setting */
541 "settings.set%d.gamestart", new_opt);
542 /* Pick something valid for saveturns */
544 "settings.set%d.gamestart", i);
545 } else {
547 "settings.set%d.gamestart", new_opt);
548 }
549 } else {
550 log_sg("Setting '%s': %s", name, secfile_error());
551 }
552 }
553 } else if (!fc_strcasecmp("autosaves", name)) {
554 /* Sanity check. This won't trigger on an option we've just
555 * invented, as the loop won't include it. */
556 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
557 "savefile. It may have been overridden.");
558 }
559 }
560 }
561 }
562}
563
564/************************************************************************/
567static const char *killcitizen_enum_str(secfile_data_t data, int bit)
568{
569 switch (bit) {
570 case UMT_LAND:
571 return "LAND";
572 case UMT_SEA:
573 return "SEA";
574 case UMT_BOTH:
575 return "BOTH";
576 }
577
578 return NULL;
579}
580
581/************************************************************************/
586{
587 const char *modname[] = { "Road", "Railroad" };
588 const char *old_activities_names[] = {
589 "Idle",
590 "Pollution",
591 "Unused Road",
592 "Mine",
593 "Irrigate",
594 "Mine",
595 "Irrigate",
596 "Fortified",
597 "Fortress",
598 "Sentry",
599 "Unused Railroad",
600 "Pillage",
601 "Goto",
602 "Explore",
603 "Transform",
604 "Unused",
605 "Unused Airbase",
606 "Fortifying",
607 "Fallout",
608 "Unused Patrol",
609 "Base"
610 };
611
612 /* Check status and return if not OK (sg_success FALSE). */
613 sg_check_ret();
614
615 log_debug("Upgrading data from savegame to version 2.5.0");
616
617 secfile_insert_int(loading->file, 2, "savefile.roads_size");
618 secfile_insert_int(loading->file, 0, "savefile.trait_size");
619
621 "savefile.roads_vector");
622
623 secfile_insert_int(loading->file, 19, "savefile.activities_size");
625 "savefile.activities_vector");
626
627 /* Server setting migration. */
628 {
629 int set_count;
630
631 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
632 int i;
633 bool gamestart_valid
635 "settings.gamestart_valid");
636 for (i = 0; i < set_count; i++) {
637 const char *name
638 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
639 if (!name) {
640 continue;
641 }
642 /* In 2.4.x and prior, "killcitizen" listed move types that
643 * killed citizens after successful attack. Now killcitizen
644 * is just boolean and classes affected are defined in ruleset. */
645 if (!fc_strcasecmp("killcitizen", name)) {
646 int value;
647
648 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
650 "settings.set%d.value", 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.value", i);
657 } else {
659 "settings.set%d.value", i);
660 }
661 } else {
662 log_sg("Setting '%s': %s", name, secfile_error());
663 }
664 if (gamestart_valid) {
665 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
667 "settings.set%d.gamestart", i)) {
668 /* Lowest bit of old killcitizen value indicates if
669 * land units should kill citizens. We take that as
670 * new boolean killcitizen value. */
671 if (value & 0x1) {
673 "settings.set%d.gamestart", i);
674 } else {
676 "settings.set%d.gamestart", i);
677 }
678 } else {
679 log_sg("Setting '%s': %s", name, secfile_error());
680 }
681 }
682 }
683 }
684 }
685 }
686}
687
688/************************************************************************/
692{
693 switch (type) {
694 case REVOLEN_FIXED:
695 return "FIXED";
696 case REVOLEN_RANDOM:
697 return "RANDOM";
699 return "QUICKENING";
701 return "RANDQUICK";
702 }
703
704 return "";
705}
706
707/************************************************************************/
712{
713 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
714 int tsize;
715 int ti;
716 int turn;
717
718 /* Check status and return if not OK (sg_success FALSE). */
719 sg_check_ret();
720
721 log_debug("Upgrading data from savegame to version 2.6.0");
722
723 /* Terrain mapping table - use current ruleset as we have no way to know
724 * any other old values. */
725 ti = 0;
727 char buf[2];
728
729 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
731 buf[1] = '\0';
732 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
734
735 /* Server setting migration. */
736 {
737 int set_count;
738
739 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
740 char value_buffer[1024] = "";
741 char gamestart_buffer[1024] = "";
742 int i;
743 int dcost = -1;
744 int dstartcost = -1;
747 bool gamestart_valid
749 "settings.gamestart_valid");
750 int new_set_count;
751
752 for (i = 0; i < set_count; i++) {
753 const char *name
754 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
755 if (!name) {
756 continue;
757 }
758
759 /* In 2.5.x and prior, "spacerace" boolean controlled if
760 * spacerace victory condition was active. */
761 if (!fc_strcasecmp("spacerace", name)) {
762 bool value;
763
764 if (secfile_lookup_bool(loading->file, &value,
765 "settings.set%d.value", i)) {
766 if (value) {
767 if (value_buffer[0] != '\0') {
769 }
770 sz_strlcat(value_buffer, "SPACERACE");
771 }
772 } else {
773 log_sg("Setting '%s': %s", name, secfile_error());
774 }
775 if (secfile_lookup_bool(loading->file, &value,
776 "settings.set%d.gamestart", i)) {
777 if (value) {
778 if (gamestart_buffer[0] != '\0') {
780 }
781 sz_strlcat(gamestart_buffer, "SPACERACE");
782 }
783 } else {
784 log_sg("Setting '%s': %s", name, secfile_error());
785 }
786
787 /* We cannot delete old values from the secfile, or rather cannot
788 * change index of the later settings. Renumbering them is not easy as
789 * we don't know type of each setting we would encounter.
790 * So we keep old setting values and only add new "victories" setting. */
791 } else if (!fc_strcasecmp("alliedvictory", name)) {
792 bool value;
793
794 if (secfile_lookup_bool(loading->file, &value,
795 "settings.set%d.value", i)) {
796 if (value) {
797 if (value_buffer[0] != '\0') {
799 }
800 sz_strlcat(value_buffer, "ALLIED");
801 }
802 } else {
803 log_sg("Setting '%s': %s", name, secfile_error());
804 }
805 if (secfile_lookup_bool(loading->file, &value,
806 "settings.set%d.gamestart", i)) {
807 if (value) {
808 if (gamestart_buffer[0] != '\0') {
810 }
811 sz_strlcat(gamestart_buffer, "ALLIED");
812 }
813 } else {
814 log_sg("Setting '%s': %s", name, secfile_error());
815 }
816 } else if (!fc_strcasecmp("revolen", name)) {
817 int value;
818
819 if (secfile_lookup_int(loading->file, &value,
820 "settings.set%d.value", i)) {
821 /* 0 meant RANDOM 1-5 */
822 if (value == 0) {
825 "settings.set%d.value", i);
826 } else {
828 }
829 } else {
830 log_sg("Setting '%s': %s", name, secfile_error());
831 }
832 if (secfile_lookup_int(loading->file, &value,
833 "settings.set%d.gamestart", i)) {
834 /* 0 meant RANDOM 1-5 */
835 if (value == 0) {
838 "settings.set%d.gamestart", i);
839 } else {
841 }
842 } else {
843 log_sg("Setting '%s': %s", name, secfile_error());
844 }
845 } else if (!fc_strcasecmp("happyborders", name)) {
846 bool value;
847
848 if (secfile_lookup_bool(loading->file, &value,
849 "settings.set%d.value", i)) {
850 secfile_entry_delete(loading->file, "settings.set%d.value", i);
851 if (value) {
852 secfile_insert_str(loading->file, "NATIONAL",
853 "settings.set%d.value", i);
854 } else {
855 secfile_insert_str(loading->file, "DISABLED",
856 "settings.set%d.value", i);
857 }
858 } else {
859 log_sg("Setting '%s': %s", name, secfile_error());
860 }
861 if (secfile_lookup_bool(loading->file, &value,
862 "settings.set%d.gamestart", i)) {
863 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
864 if (value) {
865 secfile_insert_str(loading->file, "NATIONAL",
866 "settings.set%d.gamestart", i);
867 } else {
868 secfile_insert_str(loading->file, "DISABLED",
869 "settings.set%d.gamestart", i);
870 }
871 } else {
872 log_sg("Setting '%s': %s", name, secfile_error());
873 }
874 } else if (!fc_strcasecmp("team_pooled_research", name)) {
876 &team_pooled_research,
877 "settings.set%d.value", i),
878 "%s", secfile_error());
879 } else if (!fc_strcasecmp("diplcost", name)) {
880 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
881 if (secfile_lookup_int(loading->file, &dcost,
882 "settings.set%d.value", i)) {
883 } else {
884 log_sg("Setting '%s': %s", name, secfile_error());
885 }
886
888 "settings.set%d.gamestart", i)) {
889 } else {
890 log_sg("Setting '%s': %s", name, secfile_error());
891 }
892 } else if (!fc_strcasecmp("huts", name)) {
893 /* Scale of 'huts' changed. */
894 int hcount;
895
897 "settings.set%d.value", i)) {
898 } else {
899 log_sg("Setting '%s': %s", name, secfile_error());
900 }
901
902 /* Store old-style absolute value. */
904 }
905 }
906
907 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
908
909 if (dcost >= 0) {
910 new_set_count += 2;
911 }
912
913 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
914
915 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
916 set_count);
917 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
918 set_count);
919 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
920 set_count + 1);
921 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
922 set_count + 1);
923
924 if (dcost >= 0) {
925 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
926 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
927 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
928 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
929 }
930
931 if (gamestart_valid) {
932 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
933 set_count);
934 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
935 set_count + 1);
936
937 if (dcost >= 0) {
938 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
939 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
940 }
941 }
942 }
943 }
944
945 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
946 "Trait size: %s", secfile_error());
947
948 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
949
950 player_slots_iterate(pslot) {
951 int plrno = player_slot_index(pslot);
952 bool got_first_city;
953 int old_barb_type;
954 enum barbarian_type new_barb_type;
955 int i;
956 const char *name;
957 int score;
958 int units_num;
959
960 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
961 continue;
962 }
963
964 /* Renamed 'capital' to 'got_first_city'. */
966 "player%d.capital", plrno)) {
968 "player%d.got_first_city", plrno);
969 }
970
971 /* Add 'anonymous' qualifiers for user names */
972 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
974 "player%d.unassigned_user", plrno);
975
976 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
978 "player%d.unassigned_ranked", plrno);
979
980 /* Convert numeric barbarian type to textual */
982 "player%d.ai.is_barbarian", plrno);
985 "player%d.ai.barb_type", plrno);
986
987 /* Pre-2.6 didn't record when a player was created or died, so we have
988 * to assume they lived from the start of the game until last turn */
989 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
990
991 /* As if there never has been a war. */
992 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
993
994 /* Assume people were playing until current reload */
995 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
996
997 for (i = 0; i < tsize; i++) {
998 int val;
999
1000 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
1001 plrno, i);
1002 if (val != -1) {
1003 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
1004 }
1005
1007 "player%d.trait.mod%d", plrno, i),
1008 "Trait mod: %s", secfile_error());
1009 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
1010 }
1011
1012 score = secfile_lookup_int_default(loading->file, -1,
1013 "player%d.units_built", plrno);
1014 if (score >= 0) {
1015 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
1016 }
1017
1018 score = secfile_lookup_int_default(loading->file, -1,
1019 "player%d.units_killed", plrno);
1020 if (score >= 0) {
1021 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
1022 }
1023
1024 score = secfile_lookup_int_default(loading->file, -1,
1025 "player%d.units_lost", plrno);
1026 if (score >= 0) {
1027 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
1028 }
1029
1030 /* Units orders. */
1032 "player%d.nunits",
1033 plrno);
1034
1035 for (i = 0; i < units_num; i++) {
1036 int len;
1037
1039 "player%d.u%d.orders_last_move_safe",
1040 plrno, i)) {
1041 continue;
1042 }
1043
1045 "player%d.u%d.orders_length",
1046 plrno, i);
1047 if (len > 0) {
1048 char orders_str[len + 1];
1049 char *p;
1050
1053 "player%d.u%d.orders_list",
1054 plrno, i));
1055 if ((p = strrchr(orders_str, 'm'))
1056 || (p = strrchr(orders_str, 'M'))) {
1057 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
1059 "player%d.u%d.orders_list", plrno, i);
1060 }
1061 }
1062 }
1064
1065 /* Add specialist order - loading time order is ok here, as we will use
1066 * that when we in later part of compatibility conversion use the specialist
1067 * values */
1069 "savefile.specialists_size");
1070 {
1071 const char **modname;
1072 int i = 0;
1073
1075
1079
1081 "savefile.specialists_vector");
1082
1083 free(modname);
1084 }
1085
1086 /* Replace all city specialist count fields with correct names */
1087 player_slots_iterate(pslot) {
1088 int plrno = player_slot_index(pslot);
1089 int ncities;
1090 int i;
1091
1092 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1093 continue;
1094 }
1095
1096 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
1097
1098 for (i = 0; i < ncities; i++) {
1099 int k = 0;
1100
1102 struct specialist *psp = specialist_by_number(sp);
1103 int count;
1104
1106 "player%d.c%d.n%s",
1108 "specialist error: %s", secfile_error());
1109 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
1111 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
1112 plrno, i, k++);
1114 }
1116
1117 /* Build [research]. */
1118 {
1119 const struct {
1120 const char *name;
1121 enum entry_type type;
1122 } entries[] = {
1123 { "goal_name", ENTRY_STR },
1124 { "techs", ENTRY_INT },
1125 { "futuretech", ENTRY_INT },
1126 { "bulbs_before", ENTRY_INT },
1127 { "saved_name", ENTRY_STR },
1128 { "bulbs", ENTRY_INT },
1129 { "now_name", ENTRY_STR },
1130 { "got_tech", ENTRY_BOOL },
1131 { "done", ENTRY_STR }
1132 };
1133
1135 int count = 0;
1136 int i;
1137
1138 for (i = 0; i < ARRAY_SIZE(researches); i++) {
1139 researches[i] = -1;
1140 }
1141
1142 player_slots_iterate(pslot) {
1143 int plrno = player_slot_index(pslot);
1144 int ival;
1145 bool bval;
1146 const char *sval;
1147 int j;
1148
1149 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1150 continue;
1151 }
1152
1153 /* Get the research number. */
1154 if (team_pooled_research) {
1156 "player%d.team_no", plrno);
1157 } else {
1158 i = plrno;
1159 }
1160
1162 "Research out of bounds (%d)!", i);
1163
1164 /* Find the index in [research] section. */
1165 if (researches[i] == -1) {
1166 /* This is the first player for this research. */
1167 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1168 researches[i] = count;
1169 count++;
1170 }
1171 i = researches[i];
1172
1173 /* Move entries. */
1174 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1175 switch (entries[j].type) {
1176 case ENTRY_BOOL:
1177 if (secfile_lookup_bool(loading->file, &bval,
1178 "player%d.research.%s",
1179 plrno, entries[j].name)) {
1180 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1181 i, entries[j].name);
1182 }
1183 break;
1184 case ENTRY_INT:
1185 if (secfile_lookup_int(loading->file, &ival,
1186 "player%d.research.%s",
1187 plrno, entries[j].name)) {
1188 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1189 i, entries[j].name);
1190 }
1191 break;
1192 case ENTRY_STR:
1193 if ((sval = secfile_lookup_str(loading->file,
1194 "player%d.research.%s",
1195 plrno, entries[j].name))) {
1196 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1197 i, entries[j].name);
1198 }
1199 break;
1200 case ENTRY_FLOAT:
1202 "Research related entry marked as float.");
1203 break;
1206 break;
1207 case ENTRY_LONG_COMMENT:
1209 break;
1210 case ENTRY_ILLEGAL:
1212 break;
1213 }
1214 }
1216 secfile_insert_int(loading->file, count, "research.count");
1217 }
1218
1219 /* Add diplstate type order. */
1221 "savefile.diplstate_type_size");
1222 if (DS_LAST > 0) {
1223 const char **modname;
1224 int i;
1225 int j;
1226
1227 i = 0;
1228 modname = fc_calloc(DS_LAST, sizeof(*modname));
1229
1230 for (j = 0; j < DS_LAST; j++) {
1232 }
1233
1235 DS_LAST,
1236 "savefile.diplstate_type_vector");
1237 free(modname);
1238 }
1239
1240 /* Fix save games from Freeciv versions with a bug that made it view
1241 * "Never met" as closer than "Peace" or "Alliance". */
1242 player_slots_iterate(pslot) {
1243 int plrno = player_slot_index(pslot);
1244
1245 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1246 continue;
1247 }
1248
1250 int i = player_slot_index(pslot2);
1251 char buf[32];
1252 int current;
1253 int closest;
1254
1255 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1256 continue;
1257 }
1258
1259 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1260
1261 /* Read the current diplomatic state. */
1263 "%s.type",
1264 buf);
1265
1266 /* Read the closest diplomatic state. */
1268 "%s.max_state",
1269 buf);
1270
1271 if (closest == DS_NO_CONTACT
1272 && (current == DS_PEACE
1273 || current == DS_ALLIANCE)) {
1274 const char *name1 = secfile_lookup_str_default(loading->file, "",
1275 "player%d.name", plrno);
1276 const char *name2 = secfile_lookup_str_default(loading->file, "",
1277 "player%d.name", i);
1278 /* The current relationship is closer than what the save game
1279 * claims is the closes relationship ever. */
1280
1281 log_sg(_("The save game is wrong about what the closest"
1282 " relationship %s (player %d) and %s (player %d) have had is."
1283 " Fixing it..."),
1284 name1, plrno, name2, i);
1285
1286 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1287 }
1290}
1291
1292/************************************************************************/
1295static int increase_secfile_turn_int(struct loaddata *loading, const char *key,
1296 int old_def, bool keep_default)
1297{
1298 int value;
1299
1300 value = secfile_lookup_int_default(loading->file, old_def, "%s", key);
1301
1302 if (value != old_def || !keep_default) {
1303 value++;
1304 secfile_replace_int(loading->file, value, "%s", key);
1305 }
1306
1307 return value;
1308}
1309
1310/************************************************************************/
1318{
1319 bool randsaved;
1320 int num_settings;
1321 bool started;
1322 int old_turn;
1323 int event_count;
1324 int i;
1325
1326 /* Check status and return if not OK (sg_success FALSE). */
1327 sg_check_ret();
1328
1329 log_debug("Upgrading data from savegame to version 3.0.0");
1330
1331 /* Rename "random.save" as "random.saved"
1332 * Note that it's not an error if a scenario does not have [random] at all. */
1333 if (secfile_lookup_bool(loading->file, &randsaved, "random.save")) {
1334 secfile_insert_bool(loading->file, randsaved, "random.saved");
1335 }
1336
1337 /* Already started games should have their turn counts increased by 1 */
1338 if (secfile_lookup_bool_default(loading->file, TRUE, "game.save_players")) {
1339 started = TRUE;
1340
1341 old_turn = increase_secfile_turn_int(loading, "game.turn", 0, FALSE) - 1;
1343 increase_secfile_turn_int(loading, "history.turn", -2, TRUE);
1344 } else {
1345 started = FALSE;
1346 }
1347
1348 player_slots_iterate(pslot) {
1349 int plrno = player_slot_index(pslot);
1350 const char *flag_names[1];
1351
1352 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
1353 continue;
1354 }
1355
1356 if (secfile_lookup_bool_default(loading->file, FALSE, "player%d.ai.control",
1357 plrno)) {
1359
1361 "player%d.flags", plrno);
1362 }
1363
1364 if (started) {
1365 int num = secfile_lookup_int_default(loading->file, 0,
1366 "player%d.nunits",
1367 plrno);
1368
1369 for (i = 0; i < num; i++) {
1370 char buf[64];
1371
1372 fc_snprintf(buf, sizeof(buf), "player%d.u%d.born", plrno, i);
1373
1375 }
1376
1377 num = secfile_lookup_int_default(loading->file, 0,
1378 "player%d.ncities", plrno);
1379
1380 for (i = 0; i < num; i++) {
1381 char buf[64];
1382
1383 fc_snprintf(buf, sizeof(buf), "player%d.c%d.turn_founded", plrno, i);
1384
1386 }
1387 }
1389
1390 /* Settings */
1392 "settings.set_count");
1393
1394 /* User meta server message is now a setting. */
1396 "game.meta_usermessage")) {
1397 const char *metamessage;
1398
1400 "game.meta_message");
1401
1402 /* Insert the meta message as a setting */
1403 secfile_insert_str(loading->file, "metamessage",
1404 "settings.set%d.name", num_settings);
1406 "settings.set%d.value", num_settings);
1407 secfile_insert_str(loading->file, "",
1408 "settings.set%d.gamestart", num_settings);
1409 num_settings++;
1410 }
1411
1412 secfile_replace_int(loading->file, num_settings, "settings.set_count");
1413
1414 event_count = secfile_lookup_int_default(loading->file, 0, "event_cache.count");
1415
1416 for (i = 0; i < event_count; i++) {
1417 const char *etype;
1418
1419 etype = secfile_lookup_str(loading->file, "event_cache.events%d.event", i);
1420
1421 if (etype != NULL && !fc_strcasecmp("E_UNIT_WIN", etype)) {
1422 secfile_replace_str(loading->file, "E_UNIT_WIN_DEF",
1423 "event_cache.events%d.event", i);
1424 }
1425 }
1426}
1427
1428/************************************************************************/
1433{
1434 int ssa_size;
1435
1436 if (format_class == SAVEGAME_2) {
1437 /* Handled in savegame2 */
1438 return;
1439 }
1440
1442 "savefile.server_side_agent_size");
1443
1444 if (ssa_size != 0) {
1445 /* Already inserted. */
1446 return;
1447 }
1448
1449 /* Add server side agent order. */
1451 "savefile.server_side_agent_size");
1452 if (SSA_COUNT > 0) {
1453 const char **modname;
1454 int i;
1455 int j;
1456
1457 i = 0;
1458 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
1459
1460 for (j = 0; j < SSA_COUNT; j++) {
1462 }
1463
1465 SSA_COUNT,
1466 "savefile.server_side_agent_list");
1467 free(modname);
1468 }
1469
1470 /* Insert server_side_agent unit field. */
1471 player_slots_iterate(pslot) {
1472 int unit;
1473 int units_num;
1474 int plrno = player_slot_index(pslot);
1475
1476 if (secfile_section_lookup(loading->file, "player%d", plrno)
1477 == NULL) {
1478 continue;
1479 }
1480
1481 /* Number of units the player has. */
1483 "player%d.nunits",
1484 plrno);
1485
1486 for (unit = 0; unit < units_num; unit++) {
1487 bool ai;
1488
1490 "player%d.u%d.server_side_agent",
1491 plrno, unit)
1492 != NULL) {
1493 /* Already updated? */
1494 continue;
1495 }
1496
1498 "player%d.u%d.ai",
1499 plrno, unit);
1500
1501 if (ai) {
1502 /* Autoworker and Autoexplore are separated by
1503 * compat_post_load_030100() when set to SSA_AUTOWORKER */
1505 "player%d.u%d.server_side_agent",
1506 plrno, unit);
1507 } else {
1509 "player%d.u%d.server_side_agent",
1510 plrno, unit);
1511 }
1512 }
1514}
1515
1516/************************************************************************/
1524{
1525 /* Check status and return if not OK (sg_success FALSE). */
1526 sg_check_ret();
1527
1528 log_debug("Upgrading data from savegame to version 3.1.0");
1529
1530 /* Actions are now stored by number. */
1531 player_slots_iterate(pslot) {
1532 int unit;
1533 int units_num;
1534 int plrno = player_slot_index(pslot);
1535
1536 if (secfile_section_lookup(loading->file, "player%d", plrno)
1537 == NULL) {
1538 continue;
1539 }
1540
1541 /* Number of units the player has. */
1543 "player%d.nunits",
1544 plrno);
1545
1546 for (unit = 0; unit < units_num; unit++) {
1547 const char *action_unitstr;
1548 int order_len;
1549
1551 "player%d.u%d.orders_length",
1552 plrno, unit);
1553
1555 "player%d.u%d.action_list",
1556 plrno, unit))) {
1557 int order_num;
1558
1561 }
1562
1563 for (order_num = 0; order_num < order_len; order_num++) {
1565
1566 if (action_unitstr[order_num] == '?') {
1568 } else {
1570 }
1571
1572 if (order_num == 0) {
1573 /* The start of a vector has no number. */
1575 "player%d.u%d.action_vec",
1576 plrno, unit);
1577 } else {
1579 "player%d.u%d.action_vec,%d",
1580 plrno, unit, order_num);
1581 }
1582 }
1583 }
1584 }
1586
1587 {
1588 int action_count;
1589
1591 "savefile.action_size");
1592
1593 if (action_count > 0) {
1594 const char **modname;
1595 const char **savemod;
1596 int j;
1597 const char *dur_name = "Disband Unit Recover";
1598
1599 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1600 "savefile.action_vector");
1601
1603
1604 for (j = 0; j < action_count; j++) {
1605 if (!fc_strcasecmp("Recycle Unit", modname[j])) {
1606 savemod[j] = dur_name;
1607 } else {
1608 savemod[j] = modname[j];
1609 }
1610 }
1611
1613 "savefile.action_vector");
1614
1615 free(savemod);
1616 }
1617 }
1618
1619 /* Server setting migration. */
1620 {
1621 int set_count;
1622
1623 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
1624 int i;
1625 bool gamestart_valid
1627 "settings.gamestart_valid");
1628
1629 /* Only add gamesetdef if gamestart is valid at all */
1630 if (gamestart_valid) {
1631 for (i = 0; i < set_count; i++) {
1632 const char *name
1633 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
1634
1635 if (!name) {
1636 continue;
1637 }
1638
1640 "settings.set%d.gamesetdef", i);
1641 }
1642 }
1643 }
1644 }
1645
1646 /* Explicit server side agent was new in 3.1 */
1648}
1649
1650/************************************************************************/
1654{
1655 int i;
1656
1657 for (i = 0; i < act_unit->orders.length; i++) {
1658 struct unit_order *order = &act_unit->orders.list[i];
1659
1660 if (order->order != ORDER_ACTIVITY) {
1661 continue;
1662 }
1663
1664 switch (order->activity) {
1665 case ACTIVITY_CLEAN:
1666 case ACTIVITY_MINE:
1667 case ACTIVITY_IRRIGATE:
1668 case ACTIVITY_PLANT:
1669 case ACTIVITY_CULTIVATE:
1670 case ACTIVITY_TRANSFORM:
1671 case ACTIVITY_CONVERT:
1673 case ACTIVITY_BASE:
1674 case ACTIVITY_GEN_ROAD:
1675 case ACTIVITY_PILLAGE:
1676 action_iterate(act_id) {
1677 struct action *paction = action_by_number(act_id);
1678
1679 if (action_get_activity(paction) == order->activity) {
1680 order->order = ORDER_PERFORM_ACTION;
1681 order->action = action_number(paction);
1682 order->activity = ACTIVITY_LAST;
1683 break;
1684 }
1686 break;
1687 case ACTIVITY_SENTRY:
1688 /* Not an action */
1689 break;
1690 case ACTIVITY_EXPLORE:
1691 case ACTIVITY_IDLE:
1692 case ACTIVITY_GOTO:
1693 case ACTIVITY_FORTIFIED:
1694 case ACTIVITY_LAST:
1695 log_error("Activity %d is not supposed to appear in unit orders",
1696 order->activity);
1697 break;
1698 }
1699 }
1700}
1701
1702/************************************************************************/
1706{
1707 switch (dir) {
1708 case DIR8_NORTH:
1709 return DIR8_SOUTH;
1710 case DIR8_NORTHEAST:
1711 return DIR8_SOUTHWEST;
1712 case DIR8_EAST:
1713 return DIR8_WEST;
1714 case DIR8_SOUTHEAST:
1715 return DIR8_NORTHWEST;
1716 case DIR8_SOUTH:
1717 return DIR8_NORTH;
1718 case DIR8_SOUTHWEST:
1719 return DIR8_NORTHEAST;
1720 case DIR8_WEST:
1721 return DIR8_EAST;
1722 case DIR8_NORTHWEST:
1723 return DIR8_SOUTHEAST;
1724 }
1725
1726 return DIR8_ORIGIN;
1727}
1728
1729/************************************************************************/
1733{
1734 int i;
1735 struct tile *current_tile;
1736 struct tile *tgt_tile;
1737
1738 if (!unit_has_orders(act_unit)) {
1739 return;
1740 }
1741
1742 /* The order index is for the unit at its current tile. */
1743 current_tile = unit_tile(act_unit);
1744
1745 /* Rewind to the beginning of the orders */
1746 for (i = act_unit->orders.index; i > 0 && current_tile != NULL; i--) {
1747 struct unit_order *prev_order = &act_unit->orders.list[i - 1];
1748
1749 if (!(prev_order->order == ORDER_PERFORM_ACTION
1753 current_tile = mapstep(&(wld.map), current_tile,
1754 dir_opposite(prev_order->dir));
1755 }
1756 }
1757
1758 /* Upgrade to explicit target tile */
1759 for (i = 0; i < act_unit->orders.length && current_tile != NULL; i++) {
1760 struct unit_order *order = &act_unit->orders.list[i];
1761
1762 if (order->order == ORDER_PERFORM_ACTION
1763 && order->target != NO_TARGET) {
1764 /* The target is already specified in the new format. */
1765
1766 /* The index_to_tile() call has no side-effects that we
1767 * would want also in NDEBUG builds. */
1768 fc_assert(index_to_tile(&(wld.map), order->target) != NULL);
1769 return;
1770 }
1771
1772 if (!direction8_is_valid(order->dir)) {
1773 /* The target of the action is on the actor's tile. */
1774 tgt_tile = current_tile;
1775 } else {
1776 /* The target of the action is on a tile next to the actor. */
1777 tgt_tile = mapstep(&(wld.map), current_tile, order->dir);
1778 }
1779
1780 if (order->order == ORDER_PERFORM_ACTION) {
1781 if (tgt_tile != NULL) {
1782 struct action *paction = action_by_number(order->action);
1783
1784 order->target = tgt_tile->index;
1785 /* Leave no traces. */
1786 order->dir = DIR8_ORIGIN;
1787
1789 /* The action moves the unit to the target tile (unless this is the
1790 * final order) */
1793 || i == act_unit->orders.length - 1);
1794 current_tile = tgt_tile;
1795 }
1796 } else {
1797 current_tile = NULL;
1798 }
1799 } else {
1800 current_tile = tgt_tile;
1801 }
1802 }
1803
1804 if (current_tile == NULL) {
1805 log_sg("Illegal orders for %s. Cancelling.", unit_rule_name(act_unit));
1807 }
1808}
1809
1810/************************************************************************/
1814{
1815 players_iterate_alive(pplayer) {
1816 unit_list_iterate(pplayer->units, punit) {
1819 }
1822}
1823
1824/************************************************************************/
1829{
1830 /* Check status and return if not OK (sg_success FALSE). */
1831 sg_check_ret();
1832
1833 /* Action orders were new in 3.0 */
1834 if (format_class == SAVEGAME_3) {
1835 /* Only 3.0 savegames may have "Attack" action orders. */
1836 players_iterate_alive(pplayer) {
1837 unit_list_iterate(pplayer->units, punit) {
1838 int i;
1839
1840 if (!punit->has_orders) {
1841 continue;
1842 }
1843
1845 || punit->orders.list != NULL, continue);
1846
1847 for (i = 0; i < punit->orders.length; i++) {
1848 /* "Attack" was split in "Suicide Attack" and "Attack" in 3.1. */
1854 }
1855
1856 /* Production targeted actions were split from building targeted
1857 * actions in 3.1. The building sub target encoding changed. */
1859 && ((punit->orders.list[i].action
1861 || (punit->orders.list[i].action
1863 punit->orders.list[i].sub_target -= 1;
1864 }
1866 && (punit->orders.list[i].action
1868 && punit->orders.list[i].sub_target == -1) {
1871 }
1873 && (punit->orders.list[i].action
1875 && punit->orders.list[i].sub_target == -1) {
1878 }
1879 }
1882 }
1883
1884 /* Explicit server side agent was new in 3.1 */
1886
1887 /* Some activities should only be ordered in action orders. */
1888 players_iterate_alive(pplayer) {
1889 unit_list_iterate(pplayer->units, punit) {
1893
1894 /* Unit order action target isn't dir anymore */
1895 players_iterate_alive(pplayer) {
1896 unit_list_iterate(pplayer->units, punit) {
1900
1901 /* Backward compatibility: if we had any open-ended orders (pillage)
1902 * in the savegame, assign specific targets now */
1903 players_iterate_alive(pplayer) {
1904 unit_list_iterate(pplayer->units, punit) {
1906 &punit->activity,
1907 punit->action,
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/************************************************************************/
2658{
2659 /* Check status and return if not OK (sg_success FALSE). */
2660 sg_check_ret();
2661
2662 /* Capital information was not saved in older savegames,
2663 * so we have no capital setup at all at the moment.
2664 * Best we can do is to do recalculation now. It might be
2665 * a bit off compared to the situation before the game was saved,
2666 * but definitely better than not setting capitals at all. */
2667 players_iterate_alive(pplayer) {
2668 update_capital(pplayer);
2670}
2671
2672/************************************************************************/
2676#ifdef FREECIV_DEV_SAVE_COMPAT
2677static void compat_load_dev(struct loaddata *loading)
2678{
2679 int game_version;
2680
2681 /* Check status and return if not OK (sg_success FALSE). */
2682 sg_check_ret();
2683
2684 log_verbose("Upgrading data between development revisions");
2685
2686 sg_failure_ret(secfile_lookup_int(loading->file, &game_version, "scenario.game_version"),
2687 "No save version found");
2688
2689#ifdef FREECIV_DEV_SAVE_COMPAT_3_3
2690
2691 if (game_version < 3029100) {
2692 /* Before version number bump to 3.2.91, September 2023 */
2693
2694 {
2695 const char *str = secfile_lookup_str_default(loading->file, NULL,
2696 "savefile.orig_version");
2697
2698 if (str == NULL) {
2699 /* Make sure CURRENTLY running version does not
2700 * end as orig_version when we resave. */
2701 secfile_insert_str(loading->file, "old savegame3, or older",
2702 "savefile.orig_version");
2703 }
2704 }
2705
2706 /* Add acquire_t entries for cities */
2707 {
2708 player_slots_iterate(pslot) {
2709 int plrno = player_slot_index(pslot);
2710 int ncities;
2711 int cnro;
2712 bool first_city;
2713
2714 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
2715 continue;
2716 }
2717
2719 "player%d.got_first_city",
2720 plrno);
2721 if (first_city) {
2722 const char **flag_names = fc_calloc(PLRF_COUNT, sizeof(char *));
2723 int flagcount = 0;
2724 const char **flags_sg;
2725 size_t nval;
2726 int i;
2727
2729
2731 "player%d.flags", plrno);
2732
2733 for (i = 0; i < nval; i++) {
2736
2738 }
2739
2741 "player%d.flags", plrno);
2742
2744 }
2745
2747 "player%d.ncities", plrno);
2748
2749 for (cnro = 0; cnro < ncities; cnro++) {
2750 if (secfile_entry_lookup(loading->file,
2751 "player%d.c%d.acquire_t",
2752 plrno, cnro) == NULL) {
2754 "player%d.c%d.original",
2755 plrno, cnro) != plrno) {
2757 "player%d.c%d.acquire_t",
2758 plrno, cnro);
2759 } else {
2761 "player%d.c%d.acquire_t",
2762 plrno, cnro);
2763 }
2764 }
2765 if (secfile_entry_lookup(loading->file,
2766 "player%d.c%d.wlcb",
2767 plrno, cnro) == NULL) {
2769 "player%d.c%d.wlcb",
2770 plrno, cnro);
2771 }
2772 }
2774 }
2775
2776 /* Add orders_max_length entries for players */
2777 {
2778 player_slots_iterate(pslot) {
2779 int plrno = player_slot_index(pslot);
2780
2781 if (secfile_section_lookup(loading->file, "player%d", plrno) != NULL
2783 "player%d.orders_max_length", plrno)
2784 == NULL) {
2785 size_t nunits;
2786 int unro;
2787 size_t olist_max_length = 0;
2788
2790 "player%d.nunits", plrno);
2791
2792 for (unro = 0; unro < nunits; unro++) {
2793 int ol_length
2795 "player%d.u%d.orders_length",
2796 plrno, unro);
2797
2799 }
2800
2802 "player%d.orders_max_length", plrno);
2803 }
2805 }
2806
2807 {
2808 int action_count;
2809
2811 "savefile.action_size");
2812
2813 if (action_count > 0) {
2814 const char **modname;
2815 const char **savemod;
2816 int j;
2817 const char *clean_name = "Clean";
2818
2819 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2820 "savefile.action_vector");
2821
2823
2824 for (j = 0; j < action_count; j++) {
2825 if (!fc_strcasecmp("Clean Pollution", modname[j])
2826 || !fc_strcasecmp("Clean Fallout", modname[j])) {
2827 savemod[j] = clean_name;
2828 } else {
2829 savemod[j] = modname[j];
2830 }
2831 }
2832
2834 "savefile.action_vector");
2835
2836 free(savemod);
2837 }
2838 }
2839
2840 {
2841 int activities_count;
2842
2844 "savefile.activities_size");
2845
2846 if (activities_count > 0) {
2847 const char **modname;
2848 const char **savemod;
2849 int j;
2850 const char *clean_name = "Clean";
2851
2852 modname = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2853 "savefile.activities_vector");
2854
2856
2857 for (j = 0; j < activities_count; j++) {
2858 if (!fc_strcasecmp("Pollution", modname[j])
2859 || !fc_strcasecmp("Fallout", modname[j])) {
2860 savemod[j] = clean_name;
2861 } else {
2862 savemod[j] = modname[j];
2863 }
2864 }
2865
2867 "savefile.activities_vector");
2868
2869 free(savemod);
2870 }
2871 }
2872
2873 /* Server setting migration. */
2874 {
2875 int set_count;
2876
2877 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
2878 bool gamestart_valid = FALSE;
2879
2882 "settings.gamestart_valid");
2883
2884 if (!gamestart_valid) {
2885 int i;
2886
2887 /* Older savegames saved gamestart values even when they were not valid.
2888 * Silence warnings caused by them. */
2889 for (i = 0; i < set_count; i++) {
2890 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamestart", i);
2891 (void) secfile_entry_lookup(loading->file, "settings.set%d.gamesetdef", i);
2892 }
2893 }
2894 }
2895 }
2896
2897 {
2898 int ssa_count;
2899
2901 "savefile.server_side_agent_size");
2902 if (ssa_count > 0) {
2903 const char **modname;
2904 const char **savemod;
2905 int j;
2906 const char *aw_name = "AutoWorker";
2907
2908 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
2909 "savefile.server_side_agent_list");
2910
2911 savemod = fc_calloc(ssa_count, sizeof(*savemod));
2912
2913 for (j = 0; j < ssa_count; j++) {
2914 if (!fc_strcasecmp("Autosettlers", modname[j])) {
2915 savemod[j] = aw_name;
2916 } else {
2917 savemod[j] = modname[j];
2918 }
2919 }
2920
2922 "savefile.server_side_agent_list");
2923
2924 free(savemod);
2925 }
2926 }
2927
2928 } /* Version < 3.2.91 */
2929
2930 if (game_version < 3029200) {
2931 /* Before version number bump to 3.2.92, June 2024 */
2932
2933 secfile_insert_bool(loading->file, FALSE, "map.altitude");
2934
2935 /* World Peace has never started in the old savegame. */
2936 game.info.turn
2937 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2940 "game.world_peace_start");
2942 "game.world_peace_start");
2943
2944 /* Last turn change time as a float, not integer multiplied by 100 */
2945 {
2946 float tct = secfile_lookup_int_default(loading->file, 0,
2947 "game.last_turn_change_time") / 100.0;
2948
2949 secfile_replace_float(loading->file, tct, "game.last_turn_change_time");
2950 }
2951
2952 /* Add actions for unit activities */
2953 loading->activities.size
2955 "savefile.activities_size");
2956 if (loading->activities.size) {
2957 loading->activities.order
2958 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
2959 "savefile.activities_vector");
2960 sg_failure_ret(loading->activities.size != 0,
2961 "Failed to load activity order: %s",
2962 secfile_error());
2963 }
2964
2965 loading->action.size = secfile_lookup_int_default(loading->file, 0,
2966 "savefile.action_size");
2967
2968 sg_failure_ret(loading->action.size > 0,
2969 "Failed to load action order: %s",
2970 secfile_error());
2971
2972 if (loading->action.size) {
2973 const char **modname;
2974 int j;
2975
2976 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
2977 "savefile.action_vector");
2978
2979 loading->action.order = fc_calloc(loading->action.size,
2980 sizeof(*loading->action.order));
2981
2982 for (j = 0; j < loading->action.size; j++) {
2984
2985 if (real_action) {
2986 loading->action.order[j] = real_action->id;
2987 } else {
2988 log_sg("Unknown action \'%s\'", modname[j]);
2989 loading->action.order[j] = ACTION_NONE;
2990 }
2991 }
2992
2993 free(modname);
2994 }
2995
2996 player_slots_iterate(pslot) {
2997 int plrno = player_slot_index(pslot);
2998 int nunits;
2999 int unro;
3000
3001 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3002 continue;
3003 }
3004
3006 "player%d.nunits", plrno);
3007
3008 for (unro = 0; unro < nunits; unro++) {
3009 int ei;
3010 int i;
3011 enum unit_activity activity;
3012 enum gen_action act;
3013
3015 "player%d.u%d.activity", plrno, unro);
3016
3017 if (ei >= 0 && ei < loading->activities.size) {
3018 bool found = FALSE;
3019
3020 activity = unit_activity_by_name(loading->activities.order[ei],
3022 act = activity_default_action(activity);
3023
3024 for (i = 0; i < loading->action.size; i++) {
3025 if (act == loading->action.order[i]) {
3026 secfile_insert_int(loading->file, i, "player%d.u%d.action",
3027 plrno, unro);
3028 found = TRUE;
3029 break;
3030 }
3031 }
3032
3033 if (!found) {
3034 secfile_insert_int(loading->file, -1, "player%d.u%d.action",
3035 plrno, unro);
3036 }
3037 }
3038 }
3040
3041 /* Researches */
3042 {
3043 int count = secfile_lookup_int_default(loading->file, 0, "research.count");
3044 int i;
3045
3046 for (i = 0; i < count; i++) {
3047 /* It's ok for old savegames to have these entries. */
3048 secfile_entry_ignore(loading->file, "research.r%d.techs", i);
3049 }
3050 }
3051
3052 } /* Version < 3.2.92 */
3053
3054 if (game_version < 3029300) {
3055 /* Before version number bump to 3.2.93, May 2025 */
3056
3057 {
3058 int action_count;
3059
3061 "savefile.action_size");
3062
3063 if (action_count > 0) {
3064 const char **modname;
3065 const char **savemod;
3066 int j;
3067 const char *cc1_name = "Conquer City Shrink";
3068 const char *cc2_name = "Conquer City Shrink 2";
3069 const char *cc3_name = "Conquer City Shrink 3";
3070 const char *cc4_name = "Conquer City Shrink 4";
3071
3072 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
3073 "savefile.action_vector");
3074
3076
3077 for (j = 0; j < action_count; j++) {
3078 if (!fc_strcasecmp("Conquer City", modname[j])) {
3079 savemod[j] = cc1_name;
3080 } else if (!fc_strcasecmp("Conquer City 2", modname[j])) {
3081 savemod[j] = cc2_name;
3082 } else if (!fc_strcasecmp("Conquer City 3", modname[j])) {
3083 savemod[j] = cc3_name;
3084 } else if (!fc_strcasecmp("Conquer City 4", modname[j])) {
3085 savemod[j] = cc4_name;
3086 } else {
3087 savemod[j] = modname[j];
3088 }
3089 }
3090
3092 "savefile.action_vector");
3093
3094 free(savemod);
3095 }
3096 }
3097
3098 player_slots_iterate(pslot) {
3099 int plrno = player_slot_index(pslot);
3100 int ncities;
3101 int cnro;
3102
3103 if (secfile_section_lookup(loading->file, "player%d", plrno) == nullptr) {
3104 continue;
3105 }
3106
3108 "player%d.dc_total", plrno);
3109
3110 for (cnro = 0; cnro < ncities; cnro++) {
3111 if (!secfile_entry_lookup(loading->file, "player%d.dc%d.original",
3112 plrno, cnro)) {
3113 secfile_insert_int(loading->file, -1, "player%d.dc%d.original",
3114 plrno, cnro);
3115 }
3116 }
3118 } /* Version < 3.2.93 */
3119
3120 if (game_version < 3029400) {
3121 /* Before version number bump to 3.2.94 */
3122
3123 } /* Version < 3.2.94 */
3124
3125#endif /* FREECIV_DEV_SAVE_COMPAT_3_3 */
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:400
#define action_iterate_end
Definition actions.h:218
#define action_get_activity(_pact_)
Definition actions.h:464
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_NONE
Definition actions.h:59
struct @130::my_agent entries[MAX_AGENTS]
const char * default_ai_type_name(void)
Definition aiiface.c:249
#define str
Definition astring.c:76
bool has_capability(const char *cap, const char *capstr)
Definition capability.c:79
char * incite_cost
Definition comments.c:76
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
#define NO_TARGET
Definition fc_types.h: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:743
#define GAME_DEFAULT_SCORETURN
Definition game.h:587
#define GAME_DEFAULT_SAVETURNS
Definition game.h:685
#define GAME_DEFAULT_TEAM_POOLED_RESEARCH
Definition game.h:571
#define GAME_HARDCODED_DEFAULT_SKILL_LEVEL
Definition game.h:703
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
char * lines
Definition packhand.c: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)
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:330
int current_compat_ver(void)
Definition savecompat.c:229
static void compat_load_030000(struct loaddata *loading, enum sgf_version format_class)
static const char num_chars[]
Definition savecompat.c:269
bool sg_success
Definition savecompat.c:35
static const char * killcitizen_enum_str(secfile_data_t data, int bit)
Definition savecompat.c:567
enum barbarian_type barb_type_convert(int old_type)
static char * special_names[]
Definition savecompat.c:37
static struct compatibility compat[]
Definition savecompat.c:115
static void compat_load_020400(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:348
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:239
static const int compat_num
Definition savecompat.c:140
static void compat_load_020600(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:710
static enum direction8 dir_opposite(enum direction8 dir)
void(* load_version_func_t)(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:95
int char2num(char ch)
Definition savecompat.c:275
static void upgrade_server_side_agent(struct loaddata *loading)
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:150
static void unit_order_activity_to_action(struct unit *act_unit)
static char * revolentype_str(enum revolen_type type)
Definition savecompat.c:691
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:251
struct extra_type * special_extra_get(int spe)
Definition savecompat.c:316
static void compat_load_020500(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:584
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:290
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:201
const char * special_rule_name(enum tile_special_type type)
Definition savecompat.c:306
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:141
#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:245
struct packet_game_info info
Definition game.h:89
struct civ_game::@32::@36 server
int north_latitude
Definition map_types.h:80
int south_latitude
Definition map_types.h:81
struct civ_map::@44::@46 server
int huts_absolute
Definition map_types.h:108
const load_version_func_t post_load
Definition savecompat.c:100
const load_version_func_t load
Definition savecompat.c:99
struct name_translation name
Definition specialist.h:31
Definition tile.h:50
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
Definition unit.h:140
int length
Definition unit.h:198
bool has_orders
Definition unit.h:196
enum unit_activity activity
Definition unit.h:159
enum gen_action action
Definition unit.h:160
struct unit::@83 orders
struct extra_type * activity_target
Definition unit.h:167
struct unit_order * list
Definition unit.h:201
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
int team_slot_count(void)
Definition team.c:112
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c: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: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:407
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_PERFORM_ACTION
Definition unit.h:48
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1083
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c: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