Added translator comment about government overthrown message.
[freeciv.git] / server / savecompat.c
blobc9b00f439cf60ff70ddccce4dbe786996ff6dcd1
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "capability.h"
20 #include "log.h"
22 /* common */
23 #include "specialist.h"
25 /* server */
26 #include "aiiface.h"
28 #include "savecompat.h"
30 bool sg_success;
32 static char *special_names[] =
34 "Irrigation", "Mine", "Pollution", "Hut", "Farmland",
35 "Fallout", NULL
39 For each savefile format after 2.3.0, compatibility functions are defined
40 which translate secfile structures from previous version to that version;
41 all necessary compat functions are called in order to
42 translate between the file and current version. See sg_load_compat().
44 The integer version ID should be increased every time the format is changed.
45 If the change is not backwards compatible, please state the changes in the
46 following list and update the compat functions at the end of this file.
48 - what was added / removed
49 - when was it added / removed (date and version)
50 - when can additional capability checks be set to mandatory (version)
51 - which compatibility checks are needed and till when (version)
53 freeciv | what | date | id
54 --------+------------------------------------------------+------------+----
55 current | (mapped to current savegame format) | ----/--/-- | 0
56 | first version (svn17538) | 2010/07/05 | -
57 2.3.0 | 2.3.0 release | 2010/11/?? | 3
58 2.4.0 | 2.4.0 release | 201./../.. | 10
59 | * player ai type | |
60 | * delegation | |
61 | * citizens | |
62 | * save player color | |
63 | * "known" info format change | |
64 2.5.0 | 2.5.0 release | 201./../.. | 20
65 2.6.0 | 2.6.0 release (development) | 201./../.. | 30
66 | | |
69 static void compat_load_020400(struct loaddata *loading);
70 static void compat_load_020500(struct loaddata *loading);
71 static void compat_load_020600(struct loaddata *loading);
73 typedef void (*load_version_func_t) (struct loaddata *loading);
75 struct compatibility {
76 int version;
77 const load_version_func_t load;
80 /* The struct below contains the information about the savegame versions. It
81 * is identified by the version number (first element), which should be
82 * steadily increasing. It is saved as 'savefile.version'. The support
83 * string (first element of 'name') is not saved in the savegame; it is
84 * saved in settings files (so, once assigned, cannot be changed). The
85 * 'pretty' string (second element of 'name') can be changed if necessary
86 * For changes in the development version, edit the definitions above and
87 * add the needed code to load the old version below. Thus, old
88 * savegames can still be loaded while the main definition
89 * represents the current state of the art. */
90 /* While developing freeciv 2.6.0, add the compatibility functions to
91 * - compat_load_020600 to load old savegame. */
92 static struct compatibility compat[] = {
93 /* dummy; equal to the current version (last element) */
94 { 0, NULL },
95 /* version 1 and 2 is not used */
96 /* version 3: first savegame2 format, so no compat functions for translation
97 * from previous format */
98 { 3, NULL },
99 /* version 4 to 9 are reserved for possible changes in 2.3.x */
100 { 10, compat_load_020400 },
101 /* version 11 to 19 are reserved for possible changes in 2.4.x */
102 { 20, compat_load_020500 },
103 /* version 21 to 29 are reserved for possible changes in 2.5.x */
104 { 30, compat_load_020600 },
105 /* Current savefile version is listed above this line; it corresponds to
106 the definitions in this file. */
109 static const int compat_num = ARRAY_SIZE(compat);
110 #define compat_current (compat_num - 1)
112 /****************************************************************************
113 Compatibility functions for loaded game.
115 This function is called at the beginning of loading a savegame. The data in
116 loading->file should be change such, that the current loading functions can
117 be executed without errors.
118 ****************************************************************************/
119 void sg_load_compat(struct loaddata *loading)
121 int i;
123 /* Check status and return if not OK (sg_success != TRUE). */
124 sg_check_ret();
126 loading->version = secfile_lookup_int_default(loading->file, -1,
127 "savefile.version");
128 #ifdef DEBUG
129 sg_failure_ret(0 < loading->version, "Invalid savefile format version (%d).",
130 loading->version);
131 if (loading->version > compat[compat_current].version) {
132 /* Debug build can (TRY TO!) load newer versions but ... */
133 log_error("Savegame version newer than this build found (%d > %d). "
134 "Trying to load the game nevertheless ...", loading->version,
135 compat[compat_current].version);
137 #else
138 sg_failure_ret(0 < loading->version
139 && loading->version <= compat[compat_current].version,
140 "Unknown savefile format version (%d).", loading->version);
141 #endif /* DEBUG */
144 for (i = 0; i < compat_num; i++) {
145 if (loading->version < compat[i].version && compat[i].load != NULL) {
146 log_normal(_("Run compatibility function for version: <%d "
147 "(save file: %d; server: %d)."), compat[i].version,
148 loading->version, compat[compat_current].version);
149 compat[i].load(loading);
154 /****************************************************************************
155 Return current compatibility version
156 ****************************************************************************/
157 int current_compat_ver(void)
159 return compat[compat_current].version;
162 /****************************************************************************
163 This returns an ascii hex value of the given half-byte of the binary
164 integer. See ascii_hex2bin().
165 example: bin2ascii_hex(0xa00, 2) == 'a'
166 ****************************************************************************/
167 char bin2ascii_hex(int value, int halfbyte_wanted)
169 return hex_chars[((value) >> ((halfbyte_wanted) * 4)) & 0xf];
172 /****************************************************************************
173 This returns a binary integer value of the ascii hex char, offset by the
174 given number of half-bytes. See bin2ascii_hex().
175 example: ascii_hex2bin('a', 2) == 0xa00
176 This is only used in loading games, and it requires some error checking so
177 it's done as a function.
178 ****************************************************************************/
179 int ascii_hex2bin(char ch, int halfbyte)
181 const char *pch;
183 if (ch == ' ') {
184 /* Sane value. It is unknow if there are savegames out there which
185 * need this fix. Savegame.c doesn't write such savegames
186 * (anymore) since the inclusion into CVS (2000-08-25). */
187 return 0;
190 pch = strchr(hex_chars, ch);
192 sg_failure_ret_val(NULL != pch && '\0' != ch, 0,
193 "Unknown hex value: '%c' %d", ch, ch);
194 return (pch - hex_chars) << (halfbyte * 4);
197 /****************************************************************************
198 Return the special with the given name, or S_LAST.
199 ****************************************************************************/
200 enum tile_special_type special_by_rule_name(const char *name)
202 int i;
204 for (i = 0; special_names[i] != NULL; i++) {
205 if (!strcmp(name, special_names[i])) {
206 return i;
210 return S_LAST;
213 /****************************************************************************
214 Return the untranslated name of the given special.
215 ****************************************************************************/
216 const char *special_rule_name(enum tile_special_type type)
218 fc_assert(type >= 0 && type < S_LAST);
220 return special_names[type];
223 /* =======================================================================
224 * Compatibility functions for loading a game.
225 * ======================================================================= */
227 /****************************************************************************
228 Translate savegame secfile data from 2.3.x to 2.4.0 format.
229 ****************************************************************************/
230 static void compat_load_020400(struct loaddata *loading)
232 /* Check status and return if not OK (sg_success != TRUE). */
233 sg_check_ret();
235 log_debug("Upgrading data from savegame to version 2.4.0");
237 /* Add the default player AI. */
238 player_slots_iterate(pslot) {
239 int ncities, i, plrno = player_slot_index(pslot);
241 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
242 continue;
245 secfile_insert_str(loading->file, default_ai_type_name(),
246 "player%d.ai_type", player_slot_index(pslot));
248 /* Create dummy citizens informations. We do not know if citizens are
249 * activated due to the fact that this information
250 * (game.info.citizen_nationality) is not available, but adding the
251 * information does no harm. */
252 ncities = secfile_lookup_int_default(loading->file, 0,
253 "player%d.ncities", plrno);
254 if (ncities > 0) {
255 for (i = 0; i < ncities; i++) {
256 int size = secfile_lookup_int_default(loading->file, 0,
257 "player%d.c%d.size", plrno, i);
258 if (size > 0) {
259 secfile_insert_int(loading->file, size,
260 "player%d.c%d.citizen%d", plrno, i, plrno);
265 } player_slots_iterate_end;
267 /* Player colors are assigned at the end of player loading, as this
268 * needs information not available here. */
270 /* Deal with buggy known tiles information from 2.3.0/2.3.1 (and the
271 * workaround in later 2.3.x); see gna bug #19029.
272 * (The structure of this code is odd as it avoids relying on knowledge of
273 * xsize/ysize, which haven't been extracted from the savefile yet.) */
275 if (has_capability("knownv2",
276 secfile_lookup_str(loading->file, "savefile.options"))) {
277 /* This savefile contains known information in a sane format.
278 * Just move any entries to where 2.4.x+ expect to find them. */
279 struct section *map = secfile_section_by_name(loading->file, "map");
280 if (map) {
281 entry_list_iterate(section_entries(map), pentry) {
282 const char *name = entry_name(pentry);
283 if (strncmp(name, "kvb", 3) == 0) {
284 /* Rename the "kvb..." entry to "k..." */
285 char *name2 = fc_strdup(name), *newname = name2 + 2;
286 *newname = 'k';
287 /* Savefile probably contains existing "k" entries, which are bogus
288 * so we trash them */
289 secfile_entry_delete(loading->file, "map.%s", newname);
290 entry_set_name(pentry, newname);
291 FC_FREE(name2);
293 } entry_list_iterate_end;
295 /* Could remove "knownv2" from savefile.options, but it's doing
296 * no harm there. */
297 } else {
298 /* This savefile only contains known information in the broken
299 * format. Try to recover it to a sane format. */
300 /* MAX_NUM_PLAYER_SLOTS in 2.3.x was 128 */
301 /* MAP_MAX_LINEAR_SIZE in 2.3.x was 512 */
302 const int maxslots = 128, maxmapsize = 512;
303 const int lines = maxslots/32;
304 int xsize = 0, y, l, j, x;
305 unsigned int known_row_old[lines * maxmapsize],
306 known_row[lines * maxmapsize];
307 /* Process a map row at a time */
308 for (y = 0; y < maxmapsize; y++) {
309 /* Look for broken info to convert */
310 bool found = FALSE;
311 memset(known_row_old, 0, sizeof(known_row_old));
312 for (l = 0; l < lines; l++) {
313 for (j = 0; j < 8; j++) {
314 const char *s =
315 secfile_lookup_str_default(loading->file, NULL,
316 "map.k%02d_%04d", l * 8 + j, y);
317 if (s) {
318 found = TRUE;
319 if (xsize == 0) {
320 xsize = strlen(s);
322 sg_failure_ret(xsize == strlen(s),
323 "Inconsistent xsize in map.k%02d_%04d",
324 l * 8 + j, y);
325 for (x = 0; x < xsize; x++) {
326 known_row_old[l * xsize + x] |= ascii_hex2bin(s[x], j);
331 if (found) {
332 /* At least one entry found for this row. Let's hope they were
333 * all there. */
334 /* Attempt to munge into sane format */
335 int p;
336 memset(known_row, 0, sizeof(known_row));
337 /* Iterate over possible player slots */
338 for (p = 0; p < maxslots; p++) {
339 l = p / 32;
340 for (x = 0; x < xsize; x++) {
341 /* This test causes bit-shifts of >=32 (undefined behaviour), but
342 * on common platforms, information happens not to be lost, just
343 * oddly arranged. */
344 if (known_row_old[l * xsize + x] & (1u << (p - l * 8))) {
345 known_row[l * xsize + x] |= (1u << (p - l * 32));
349 /* Save sane format back to memory representation of secfile for
350 * real loading code to pick up */
351 for (l = 0; l < lines; l++) {
352 for (j = 0; j < 8; j++) {
353 /* Save info for all slots (not just used ones). It's only
354 * memory, after all. */
355 char row[xsize+1];
356 for (x = 0; x < xsize; x++) {
357 row[x] = bin2ascii_hex(known_row[l * xsize + x], j);
359 row[xsize] = '\0';
360 secfile_replace_str(loading->file, row,
361 "map.k%02d_%04d", l * 8 + j, y);
369 /* Server setting migration. */
371 int set_count;
372 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
373 int i, new_opt = set_count;
374 bool gamestart_valid
375 = secfile_lookup_bool_default(loading->file, FALSE,
376 "settings.gamestart_valid");
377 for (i = 0; i < set_count; i++) {
378 const char *name
379 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
380 if (!name) {
381 continue;
384 /* In 2.3.x and prior, saveturns=0 meant no turn-based saves.
385 * This is now controlled by the "autosaves" setting. */
386 if (!fc_strcasecmp("saveturns", name)) {
387 /* XXX: hardcodes details from GAME_AUTOSAVES_DEFAULT
388 * and settings.c:autosaves_name() (but these defaults reflect
389 * 2.3's behaviour). */
390 const char *const nosave = "GAMEOVER|QUITIDLE|INTERRUPT";
391 const char *const save = "TURN|GAMEOVER|QUITIDLE|INTERRUPT";
392 int nturns;
394 if (secfile_lookup_int(loading->file, &nturns,
395 "settings.set%d.value", i)) {
396 if (nturns == 0) {
397 /* Invent a new "autosaves" setting */
398 secfile_insert_str(loading->file, nosave,
399 "settings.set%d.value", new_opt);
400 /* Pick something valid for saveturns */
401 secfile_replace_int(loading->file, GAME_DEFAULT_SAVETURNS,
402 "settings.set%d.value", i);
403 } else {
404 secfile_insert_str(loading->file, save,
405 "settings.set%d.value", new_opt);
407 } else {
408 log_sg("Setting '%s': %s", name, secfile_error());
410 if (gamestart_valid) {
411 if (secfile_lookup_int(loading->file, &nturns,
412 "settings.set%d.gamestart", i)) {
413 if (nturns == 0) {
414 /* Invent a new "autosaves" setting */
415 secfile_insert_str(loading->file, nosave,
416 "settings.set%d.gamestart", new_opt);
417 /* Pick something valid for saveturns */
418 secfile_replace_int(loading->file, GAME_DEFAULT_SAVETURNS,
419 "settings.set%d.gamestart", i);
420 } else {
421 secfile_insert_str(loading->file, save,
422 "settings.set%d.gamestart", new_opt);
424 } else {
425 log_sg("Setting '%s': %s", name, secfile_error());
428 } else if (!fc_strcasecmp("autosaves", name)) {
429 /* Sanity check. This won't trigger on an option we've just
430 * invented, as the loop won't include it. */
431 log_sg("Unexpected \"autosaves\" setting found in pre-2.4 "
432 "savefile. It may have been overridden.");
439 /****************************************************************************
440 Callback to get name of old killcitizen setting bit.
441 ****************************************************************************/
442 static const char *killcitizen_enum_str(secfile_data_t data, int bit)
444 switch (bit) {
445 case UMT_LAND:
446 return "LAND";
447 case UMT_SEA:
448 return "SEA";
449 case UMT_BOTH:
450 return "BOTH";
453 return NULL;
456 /****************************************************************************
457 Translate savegame secfile data from 2.4.x to 2.5.0 format.
458 ****************************************************************************/
459 static void compat_load_020500(struct loaddata *loading)
461 const char *modname[] = { "Road", "Railroad" };
463 /* Check status and return if not OK (sg_success != TRUE). */
464 sg_check_ret();
466 log_debug("Upgrading data from savegame to version 2.5.0");
468 secfile_insert_int(loading->file, 2, "savefile.roads_size");
469 secfile_insert_int(loading->file, 0, "savefile.trait_size");
471 secfile_insert_str_vec(loading->file, modname, 2,
472 "savefile.roads_vector");
474 /* Server setting migration. */
476 int set_count;
478 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
479 int i;
480 bool gamestart_valid
481 = secfile_lookup_bool_default(loading->file, FALSE,
482 "settings.gamestart_valid");
483 for (i = 0; i < set_count; i++) {
484 const char *name
485 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
486 if (!name) {
487 continue;
489 /* In 2.4.x and prior, "killcitizen" listed move types that
490 * killed citizens after succesfull attack. Now killcitizen
491 * is just boolean and classes affected are defined in ruleset. */
492 if (!fc_strcasecmp("killcitizen", name)) {
493 int value;
495 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
496 killcitizen_enum_str, NULL,
497 "settings.set%d.value", i)) {
498 /* Lowest bit of old killcitizen value indicates if
499 * land units should kill citizens. We take that as
500 * new boolean killcitizen value. */
501 if (value & 0x1) {
502 secfile_replace_bool(loading->file, TRUE,
503 "settings.set%d.value", i);
504 } else {
505 secfile_replace_bool(loading->file, FALSE,
506 "settings.set%d.value", i);
508 } else {
509 log_sg("Setting '%s': %s", name, secfile_error());
511 if (gamestart_valid) {
512 if (secfile_lookup_enum_data(loading->file, &value, TRUE,
513 killcitizen_enum_str, NULL,
514 "settings.set%d.gamestart", i)) {
515 /* Lowest bit of old killcitizen value indicates if
516 * land units should kill citizens. We take that as
517 * new boolean killcitizen value. */
518 if (value & 0x1) {
519 secfile_replace_bool(loading->file, TRUE,
520 "settings.set%d.gamestart", i);
521 } else {
522 secfile_replace_bool(loading->file, FALSE,
523 "settings.set%d.gamestart", i);
525 } else {
526 log_sg("Setting '%s': %s", name, secfile_error());
535 /****************************************************************************
536 Return string representation of revolentype
537 ****************************************************************************/
538 static char *revolentype_str(enum revolen_type type)
540 switch (type) {
541 case REVOLEN_FIXED:
542 return "FIXED";
543 case REVOLEN_RANDOM:
544 return "RANDOM";
545 case REVOLEN_QUICKENING:
546 return "QUICKENING";
547 case REVOLEN_RANDQUICK:
548 return "RANDQUICK";
551 return "";
554 /****************************************************************************
555 Translate savegame secfile data from 2.5.x to 2.6.0 format.
556 ****************************************************************************/
557 static void compat_load_020600(struct loaddata *loading)
559 bool team_pooled_research = GAME_DEFAULT_TEAM_POOLED_RESEARCH;
560 int tsize;
561 int ti;
562 int turn;
564 /* Check status and return if not OK (sg_success != TRUE). */
565 sg_check_ret();
567 log_debug("Upgrading data from savegame to version 2.6.0");
569 /* Terrain mapping table - use current ruleset as we have no way to know
570 * any other old values. */
571 ti = 0;
572 terrain_type_iterate(pterr) {
573 char buf[2];
575 secfile_insert_str(loading->file, terrain_rule_name(pterr), "savefile.terrident%d.name", ti);
576 buf[0] = terrain_identifier(pterr);
577 buf[1] = '\0';
578 secfile_insert_str(loading->file, buf, "savefile.terrident%d.identifier", ti++);
579 } terrain_type_iterate_end;
581 /* Server setting migration. */
583 int set_count;
585 if (secfile_lookup_int(loading->file, &set_count, "settings.set_count")) {
586 char value_buffer[1024] = "";
587 char gamestart_buffer[1024] = "";
588 int i;
589 int dcost = -1;
590 int dstartcost = -1;
591 enum revolen_type rlt = GAME_DEFAULT_REVOLENTYPE;
592 enum revolen_type gsrlt = GAME_DEFAULT_REVOLENTYPE;
593 bool gamestart_valid
594 = secfile_lookup_bool_default(loading->file, FALSE,
595 "settings.gamestart_valid");
596 int new_set_count;
598 for (i = 0; i < set_count; i++) {
599 const char *name
600 = secfile_lookup_str(loading->file, "settings.set%d.name", i);
601 if (!name) {
602 continue;
605 /* In 2.5.x and prior, "spacerace" boolean controlled if
606 * spacerace victory condition was active. */
607 if (!fc_strcasecmp("spacerace", name)) {
608 bool value;
610 if (secfile_lookup_bool(loading->file, &value,
611 "settings.set%d.value", i)) {
612 if (value) {
613 sz_strlcat(value_buffer, "|SPACERACE");
615 } else {
616 log_sg("Setting '%s': %s", name, secfile_error());
618 if (secfile_lookup_bool(loading->file, &value,
619 "settings.set%d.gamestart", i)) {
620 if (value) {
621 sz_strlcat(gamestart_buffer, "|SPACERACE");
623 } else {
624 log_sg("Setting '%s': %s", name, secfile_error());
627 /* We cannot delete old values from the secfile, or rather cannot
628 * change index of the later settings. Renumbering them is not easy as
629 * we don't know type of each setting we would encounter.
630 * So we keep old setting values and only add new "victories" setting. */
631 } else if (!fc_strcasecmp("alliedvictory", name)) {
632 bool value;
634 if (secfile_lookup_bool(loading->file, &value,
635 "settings.set%d.value", i)) {
636 if (value) {
637 sz_strlcat(value_buffer, "|ALLIED");
639 } else {
640 log_sg("Setting '%s': %s", name, secfile_error());
642 if (secfile_lookup_bool(loading->file, &value,
643 "settings.set%d.gamestart", i)) {
644 if (value) {
645 sz_strlcat(gamestart_buffer, "|ALLIED");
647 } else {
648 log_sg("Setting '%s': %s", name, secfile_error());
650 } else if (!fc_strcasecmp("revolen", name)) {
651 int value;
653 if (secfile_lookup_int(loading->file, &value,
654 "settings.set%d.value", i)) {
655 /* 0 meant RANDOM 1-5 */
656 if (value == 0) {
657 rlt = REVOLEN_RANDOM;
658 secfile_replace_int(loading->file, 5,
659 "settings.set%d.value", i);
660 } else {
661 rlt = REVOLEN_FIXED;
663 } else {
664 log_sg("Setting '%s': %s", name, secfile_error());
666 if (secfile_lookup_int(loading->file, &value,
667 "settings.set%d.gamestart", i)) {
668 /* 0 meant RANDOM 1-5 */
669 if (value == 0) {
670 gsrlt = REVOLEN_RANDOM;
671 secfile_replace_int(loading->file, 5,
672 "settings.set%d.gamestart", i);
673 } else {
674 gsrlt = REVOLEN_FIXED;
676 } else {
677 log_sg("Setting '%s': %s", name, secfile_error());
679 } else if (!fc_strcasecmp("happyborders", name)) {
680 bool value;
682 if (secfile_lookup_bool(loading->file, &value,
683 "settings.set%d.value", i)) {
684 secfile_entry_delete(loading->file, "settings.set%d.value", i);
685 if (value) {
686 secfile_insert_str(loading->file, "NATIONAL",
687 "settings.set%d.value", i);
688 } else {
689 secfile_insert_str(loading->file, "DISABLED",
690 "settings.set%d.value", i);
692 } else {
693 log_sg("Setting '%s': %s", name, secfile_error());
695 if (secfile_lookup_bool(loading->file, &value,
696 "settings.set%d.gamestart", i)) {
697 secfile_entry_delete(loading->file, "settings.set%d.gamestart", i);
698 if (value) {
699 secfile_insert_str(loading->file, "NATIONAL",
700 "settings.set%d.gamestart", i);
701 } else {
702 secfile_insert_str(loading->file, "DISABLED",
703 "settings.set%d.gamestart", i);
705 } else {
706 log_sg("Setting '%s': %s", name, secfile_error());
708 } else if (!fc_strcasecmp("team_pooled_research", name)) {
709 sg_warn(secfile_lookup_bool(loading->file,
710 &team_pooled_research,
711 "settings.set%d.value", i),
712 "%s", secfile_error());
713 } else if (!fc_strcasecmp("diplcost", name)) {
714 /* Old 'diplcost' split to 'diplbulbcost' and 'diplgoldcost' */
715 if (secfile_lookup_int(loading->file, &dcost,
716 "settings.set%d.value", i)) {
717 } else {
718 log_sg("Setting '%s': %s", name, secfile_error());
721 if (secfile_lookup_int(loading->file, &dstartcost,
722 "settings.set%d.gamestart", i)) {
723 } else {
724 log_sg("Setting '%s': %s", name, secfile_error());
726 } else if (!fc_strcasecmp("huts", name)) {
727 /* Scale of 'huts' changed. */
728 int hcount;
730 if (secfile_lookup_int(loading->file, &hcount,
731 "settings.set%d.value", i)) {
732 } else {
733 log_sg("Setting '%s': %s", name, secfile_error());
736 /* Store old-style absolute value. */
737 game.map.server.huts_absolute = hcount;
741 new_set_count = set_count + 2; /* 'victories' and 'revolentype' */
743 if (dcost >= 0) {
744 new_set_count += 2;
747 secfile_replace_int(loading->file, new_set_count, "settings.set_count");
749 secfile_insert_str(loading->file, "victories", "settings.set%d.name",
750 set_count);
751 secfile_insert_str(loading->file, value_buffer, "settings.set%d.value",
752 set_count);
753 secfile_insert_str(loading->file, "revolentype", "settings.set%d.name",
754 set_count + 1);
755 secfile_insert_str(loading->file, revolentype_str(rlt), "settings.set%d.value",
756 set_count + 1);
758 if (dcost >= 0) {
759 secfile_insert_str(loading->file, "diplbulbcost", "settings.set%d.name", set_count + 2);
760 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 2);
761 secfile_insert_str(loading->file, "diplgoldcost", "settings.set%d.name", set_count + 3);
762 secfile_insert_int(loading->file, dcost, "settings.set%d.value", set_count + 3);
765 if (gamestart_valid) {
766 secfile_insert_str(loading->file, gamestart_buffer, "settings.set%d.gamestart",
767 set_count);
768 secfile_insert_str(loading->file, revolentype_str(gsrlt), "settings.set%d.gamestart",
769 set_count + 1);
771 if (dcost >= 0) {
772 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 2);
773 secfile_insert_int(loading->file, dstartcost, "settings.set%d.gamestart", set_count + 3);
779 sg_failure_ret(secfile_lookup_int(loading->file, &tsize, "savefile.trait_size"),
780 "Trait size: %s", secfile_error());
782 turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
784 player_slots_iterate(pslot) {
785 int plrno = player_slot_index(pslot);
786 bool got_first_city;
787 int old_barb_type;
788 enum barbarian_type new_barb_type;
789 int i;
790 const char *name;
791 int score;
792 int units_num;
794 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
795 continue;
798 /* Renamed 'capital' to 'got_first_city'. */
799 if (secfile_lookup_bool(loading->file, &got_first_city,
800 "player%d.capital", plrno)) {
801 secfile_insert_bool(loading->file, got_first_city,
802 "player%d.got_first_city", plrno);
805 /* Add 'anonymous' qualifiers for user names */
806 name = secfile_lookup_str_default(loading->file, "", "player%d.username", plrno);
807 secfile_insert_bool(loading->file, (!strcmp(name, ANON_USER_NAME)),
808 "player%d.unassigned_user", plrno);
810 name = secfile_lookup_str_default(loading->file, "", "player%d.ranked_username", plrno);
811 secfile_insert_bool(loading->file, (!strcmp(name, ANON_USER_NAME)),
812 "player%d.unassigned_ranked", plrno);
814 /* Convert numeric barbarian type to textual */
815 old_barb_type = secfile_lookup_int_default(loading->file, 0,
816 "player%d.ai.is_barbarian", plrno);
817 new_barb_type = barb_type_convert(old_barb_type);
818 secfile_insert_str(loading->file, barbarian_type_name(new_barb_type),
819 "player%d.ai.barb_type", plrno);
821 /* Pre-2.6 didn't record when a player was created or died, so we have
822 * to assume they lived from the start of the game until last turn */
823 secfile_insert_int(loading->file, turn, "player%d.turns_alive", plrno);
825 /* As if there never has been a war. */
826 secfile_insert_int(loading->file, -1, "player%d.last_war", plrno);
828 /* Assume people were playing until current reload */
829 secfile_insert_int(loading->file, 0, "player%d.idle_turns", plrno);
831 for (i = 0; i < tsize; i++) {
832 int val;
834 val = secfile_lookup_int_default(loading->file, -1, "player%d.trait.val%d",
835 plrno, i);
836 if (val != -1) {
837 secfile_insert_int(loading->file, val, "player%d.trait%d.val", plrno, i);
840 sg_failure_ret(secfile_lookup_int(loading->file, &val,
841 "player%d.trait.mod%d", plrno, i),
842 "Trait mod: %s", secfile_error());
843 secfile_insert_int(loading->file, val, "player%d.trait%d.mod", plrno, i);
846 score = secfile_lookup_int_default(loading->file, -1,
847 "player%d.units_built", plrno);
848 if (score >= 0) {
849 secfile_insert_int(loading->file, score, "score%d.units_built", plrno);
852 score = secfile_lookup_int_default(loading->file, -1,
853 "player%d.units_killed", plrno);
854 if (score >= 0) {
855 secfile_insert_int(loading->file, score, "score%d.units_killed", plrno);
858 score = secfile_lookup_int_default(loading->file, -1,
859 "player%d.units_lost", plrno);
860 if (score >= 0) {
861 secfile_insert_int(loading->file, score, "score%d.units_lost", plrno);
864 /* Units orders. */
865 units_num = secfile_lookup_int_default(loading->file, 0,
866 "player%d.nunits",
867 plrno);
869 for (i = 0; i < units_num; i++) {
870 int len;
872 if (secfile_lookup_bool_default(loading->file, FALSE,
873 "player%d.u%d.orders_last_move_safe",
874 plrno, i)) {
875 continue;
878 len = secfile_lookup_int_default(loading->file, 0,
879 "player%d.u%d.orders_length",
880 plrno, i);
881 if (len > 0) {
882 char orders_str[len + 1];
883 char *p;
885 sz_strlcpy(orders_str,
886 secfile_lookup_str_default(loading->file, "",
887 "player%d.u%d.orders_list",
888 plrno, i));
889 if ((p = strrchr(orders_str, 'm'))
890 || (p = strrchr(orders_str, 'M'))) {
891 *p = 'x'; /* ORDER_MOVE -> ORDER_ACTION_MOVE */
892 secfile_replace_str(loading->file, orders_str,
893 "player%d.u%d.orders_list", plrno, i);
897 } player_slots_iterate_end;
899 /* Add specialist order - loading time order is ok here, as we will use
900 * that when we in later part of compatibility conversion use the specialist
901 * values */
902 secfile_insert_int(loading->file, specialist_count(),
903 "savefile.specialists_size");
905 const char **modname;
906 int i = 0;
908 modname = fc_calloc(specialist_count(), sizeof(*modname));
910 specialist_type_iterate(sp) {
911 modname[i++] = specialist_rule_name(specialist_by_number(sp));
912 } specialist_type_iterate_end;
914 secfile_insert_str_vec(loading->file, modname, specialist_count(),
915 "savefile.specialists_vector");
917 free(modname);
920 /* Replace all city specialist count fields with correct names */
921 player_slots_iterate(pslot) {
922 int plrno = player_slot_index(pslot);
923 int ncities;
924 int i;
926 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
927 continue;
930 ncities = secfile_lookup_int_default(loading->file, 0, "player%d.ncities", plrno);
932 for (i = 0; i < ncities; i++) {
933 int k = 0;
935 specialist_type_iterate(sp) {
936 struct specialist *psp = specialist_by_number(sp);
937 int count;
939 sg_failure_ret(secfile_lookup_int(loading->file, &count,
940 "player%d.c%d.n%s",
941 plrno, i, specialist_rule_name(psp)),
942 "specialist error: %s", secfile_error());
943 secfile_entry_delete(loading->file, "player%d.c%d.n%s",
944 plrno, i, specialist_rule_name(psp));
945 secfile_insert_int(loading->file, count, "player%d.c%d.nspe%d",
946 plrno, i, k++);
947 } specialist_type_iterate_end;
949 } player_slots_iterate_end;
951 /* Build [research]. */
953 const struct {
954 const char *entry_name;
955 enum entry_type entry_type;
956 } entries[] = {
957 { "goal_name", ENTRY_STR },
958 { "techs", ENTRY_INT },
959 { "futuretech", ENTRY_INT },
960 { "bulbs_before", ENTRY_INT },
961 { "saved_name", ENTRY_STR },
962 { "bulbs", ENTRY_INT },
963 { "now_name", ENTRY_STR },
964 { "got_tech", ENTRY_BOOL },
965 { "done", ENTRY_STR }
968 int researches[MAX(player_slot_count(), team_slot_count())];
969 int count = 0;
970 int i;
972 for (i = 0; i < ARRAY_SIZE(researches); i++) {
973 researches[i] = -1;
976 player_slots_iterate(pslot) {
977 int plrno = player_slot_index(pslot);
978 int ival;
979 bool bval;
980 const char *sval;
981 int j;
983 if (secfile_section_lookup(loading->file, "player%d", plrno) == NULL) {
984 continue;
987 /* Get the research number. */
988 if (team_pooled_research) {
989 i = secfile_lookup_int_default(loading->file, plrno,
990 "player%d.team_no", plrno);
991 } else {
992 i = plrno;
995 sg_failure_ret(i >= 0 && i < ARRAY_SIZE(researches),
996 "Research out of bounds (%d)!", i);
998 /* Find the index in [research] section. */
999 if (researches[i] == -1) {
1000 /* This is the first player for this research. */
1001 secfile_insert_int(loading->file, i, "research.r%d.number", count);
1002 researches[i] = count;
1003 count++;
1005 i = researches[i];
1007 /* Move entries. */
1008 for (j = 0; j < ARRAY_SIZE(entries); j++) {
1009 switch (entries[j].entry_type) {
1010 case ENTRY_BOOL:
1011 if (secfile_lookup_bool(loading->file, &bval,
1012 "player%d.research.%s",
1013 plrno, entries[j].entry_name)) {
1014 secfile_insert_bool(loading->file, bval, "research.r%d.%s",
1015 i, entries[j].entry_name);
1017 break;
1018 case ENTRY_INT:
1019 if (secfile_lookup_int(loading->file, &ival,
1020 "player%d.research.%s",
1021 plrno, entries[j].entry_name)) {
1022 secfile_insert_int(loading->file, ival, "research.r%d.%s",
1023 i, entries[j].entry_name);
1025 break;
1026 case ENTRY_STR:
1027 if ((sval = secfile_lookup_str(loading->file,
1028 "player%d.research.%s",
1029 plrno, entries[j].entry_name))) {
1030 secfile_insert_str(loading->file, sval, "research.r%d.%s",
1031 i, entries[j].entry_name);
1033 break;
1034 case ENTRY_FLOAT:
1035 sg_failure_ret(entries[j].entry_type != ENTRY_FLOAT,
1036 "Research related entry marked as float.");
1037 break;
1038 case ENTRY_FILEREFERENCE:
1039 fc_assert(entries[j].entry_type != ENTRY_FILEREFERENCE);
1040 break;
1043 } player_slots_iterate_end;
1044 secfile_insert_int(loading->file, count, "research.count");
1047 /* Add diplstate type order. */
1048 secfile_insert_int(loading->file, DS_LAST,
1049 "savefile.diplstate_type_size");
1050 if (DS_LAST > 0) {
1051 const char **modname;
1052 int i;
1053 int j;
1055 i = 0;
1056 modname = fc_calloc(DS_LAST, sizeof(*modname));
1058 for (j = 0; j < DS_LAST; j++) {
1059 modname[i++] = diplstate_type_name(j);
1062 secfile_insert_str_vec(loading->file, modname,
1063 DS_LAST,
1064 "savefile.diplstate_type_vector");
1065 free(modname);
1068 /* Fix save games from Freeciv versions with a bug that made it view
1069 * "Never met" as closer than "Peace" or "Alliance". */
1070 player_slots_iterate(pslot) {
1071 int plrno = player_slot_index(pslot);
1073 if (NULL == secfile_section_lookup(loading->file, "player%d", plrno)) {
1074 continue;
1077 player_slots_iterate(pslot2) {
1078 int i = player_slot_index(pslot2);
1079 char buf[32];
1080 int current;
1081 int closest;
1083 if (NULL == secfile_section_lookup(loading->file, "player%d", i)) {
1084 continue;
1087 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
1089 /* Read the current diplomatic state. */
1090 current = secfile_lookup_int_default(loading->file, DS_NO_CONTACT,
1091 "%s.type",
1092 buf);
1094 /* Read the closest diplomatic state. */
1095 closest = secfile_lookup_int_default(loading->file, DS_NO_CONTACT,
1096 "%s.max_state",
1097 buf);
1099 if (closest == DS_NO_CONTACT
1100 && (current == DS_PEACE
1101 || current == DS_ALLIANCE)) {
1102 const char *name1 = secfile_lookup_str_default(loading->file, "",
1103 "player%d.name", plrno);
1104 const char *name2 = secfile_lookup_str_default(loading->file, "",
1105 "player%d.name", i);
1106 /* The current relationship is closer than what the save game
1107 * claims is the closes relationship ever. */
1109 log_sg(_("The save game is wrong about what the closest"
1110 " relationship %s (player %d) and %s (player %d) have had is."
1111 " Fixing it..."),
1112 name1, plrno, name2, i);
1114 secfile_replace_int(loading->file, current, "%s.max_state", buf);
1116 } player_slots_iterate_end;
1117 } player_slots_iterate_end;
1120 /****************************************************************************
1121 Convert old ai level value to ai_level
1122 ****************************************************************************/
1123 enum ai_level ai_level_convert(int old_level)
1125 switch (old_level) {
1126 case 1:
1127 return AI_LEVEL_AWAY;
1128 case 2:
1129 return AI_LEVEL_NOVICE;
1130 case 3:
1131 return AI_LEVEL_EASY;
1132 case 5:
1133 return AI_LEVEL_NORMAL;
1134 case 7:
1135 return AI_LEVEL_HARD;
1136 case 8:
1137 return AI_LEVEL_CHEATING;
1138 case 10:
1139 #ifdef DEBUG
1140 return AI_LEVEL_EXPERIMENTAL;
1141 #else /* DEBUG */
1142 return AI_LEVEL_HARD;
1143 #endif /* DEBUG */
1146 return ai_level_invalid();
1149 /****************************************************************************
1150 Convert old barbarian type value to barbarian_type
1151 ****************************************************************************/
1152 enum barbarian_type barb_type_convert(int old_type)
1154 switch (old_type) {
1155 case 0:
1156 return NOT_A_BARBARIAN;
1157 case 1:
1158 return LAND_BARBARIAN;
1159 case 2:
1160 return SEA_BARBARIAN;
1163 return barbarian_type_invalid();