Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/savegame/savegame3.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
savegame3.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/*
15 This file includes the definition of a new savegame format introduced with
16 3.0. It is defined by the mandatory option '+version3'. The main load
17 function checks if this option is present. If not, the old (pre-3.0)
18 loading routines are used.
19 The format version is also saved in the settings section of the savefile, as an
20 integer (savefile.version). The integer is used to determine the version
21 of the savefile.
22
23 Structure of this file:
24
25 - The main function for saving is savegame3_save().
26
27 - The real work is done by savegame3_load() and savegame3_save_real().
28 This function call all submodules (settings, players, etc.)
29
30 - The remaining part of this file is split into several sections:
31 * helper functions
32 * save / load functions for all submodules (and their subsubmodules)
33
34 - If possible, all functions for load / save submodules should exit in
35 pairs named sg_load_<submodule> and sg_save_<submodule>. If one is not
36 needed please add a comment why.
37
38 - The submodules can be further divided as:
39 sg_load_<submodule>_<subsubmodule>
40
41 - If needed (due to static variables in the *.c files) these functions
42 can be located in the corresponding source files (as done for the settings
43 and the event_cache).
44
45 Creating a savegame:
46
47 (nothing at the moment)
48
49 Loading a savegame:
50
51 - The status of the process is saved within the static variable
52 'sg_success'. This variable is set to TRUE within savegame3_load().
53 If you encounter an error use sg_failure_*() to set it to FALSE and
54 return an error message. Furthermore, sg_check_* should be used at the
55 start of each (submodule) function to return if previous functions failed.
56
57 - While the loading process dependencies between different modules exits.
58 They can be handled within the struct loaddata *loading which is used as
59 first argument for all sg_load_*() function. Please indicate the
60 dependencies within the definition of this struct.
61
62*/
63
64#ifdef HAVE_CONFIG_H
65#include <fc_config.h>
66#endif
67
68#include <ctype.h>
69#include <stdarg.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73
74/* utility */
75#include "bitvector.h"
76#include "fcintl.h"
77#include "idex.h"
78#include "log.h"
79#include "mem.h"
80#include "rand.h"
81#include "registry.h"
82#include "shared.h"
83#include "support.h" /* bool type */
84#include "timing.h"
85
86/* common */
87#include "achievements.h"
88#include "ai.h"
89#include "bitvector.h"
90#include "capability.h"
91#include "citizens.h"
92#include "city.h"
93#include "counters.h"
94#include "game.h"
95#include "government.h"
96#include "map.h"
97#include "mapimg.h"
98#include "movement.h"
99#include "multipliers.h"
100#include "packets.h"
101#include "research.h"
102#include "rgbcolor.h"
103#include "sex.h"
104#include "specialist.h"
105#include "unit.h"
106#include "unitlist.h"
107#include "version.h"
108
109/* server */
110#include "barbarian.h"
111#include "citizenshand.h"
112#include "citytools.h"
113#include "cityturn.h"
114#include "diplhand.h"
115#include "maphand.h"
116#include "meta.h"
117#include "notify.h"
118#include "plrhand.h"
119#include "report.h"
120#include "ruleset.h"
121#include "sanitycheck.h"
122#include "savecompat.h"
123#include "score.h"
124#include "settings.h"
125#include "spacerace.h"
126#include "srv_main.h"
127#include "stdinhand.h"
128#include "techtools.h"
129#include "unittools.h"
130
131/* server/advisors */
132#include "advdata.h"
133#include "advbuilding.h"
134#include "infracache.h"
135
136/* server/generator */
137#include "mapgen.h"
138#include "mapgen_utils.h"
139
140/* server/scripting */
141#include "script_server.h"
142
143/* ai */
144#include "aitraits.h"
145#include "difficulty.h"
146
147#include "savegame3.h"
148
149extern bool sg_success;
150
151#define ACTIVITY_OLD_POLLUTION_SG3 (ACTIVITY_LAST + 1)
152#define ACTIVITY_OLD_FALLOUT_SG3 (ACTIVITY_OLD_POLLUTION_SG3 + 1)
153#define ACTIVITY_LAST_SAVEGAME3 (ACTIVITY_OLD_FALLOUT_SG3 + 1)
154
155#ifdef FREECIV_TESTMATIC
156#define SAVE_DUMMY_TURN_CHANGE_TIME 1
157#endif
158
159/*
160 * This loops over the entire map to save data. It collects all the data of
161 * a line using GET_XY_CHAR and then executes the macro SECFILE_INSERT_LINE.
162 *
163 * Parameters:
164 * ptile: current tile within the line (used by GET_XY_CHAR)
165 * GET_XY_CHAR: macro returning the map character for each position
166 * secfile: a secfile struct
167 * secpath, ...: path as used for sprintf() with arguments; the last item
168 * will be the y coordinate
169 * Example:
170 * SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), file, "map.t%04d");
171 */
172#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath, ...) \
173{ \
174 char _line[wld.map.xsize + 1]; \
175 int _nat_x, _nat_y; \
176 \
177 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
178 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
179 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
180 fc_assert_action(ptile != NULL, continue); \
181 _line[_nat_x] = (GET_XY_CHAR); \
182 sg_failure_ret(fc_isprint(_line[_nat_x] & 0x7f), \
183 "Trying to write invalid map data at position " \
184 "(%d, %d) for path %s: '%c' (%d)", _nat_x, _nat_y, \
185 secpath, _line[_nat_x], _line[_nat_x]); \
186 } \
187 _line[wld.map.xsize] = '\0'; \
188 secfile_insert_str(secfile, _line, secpath, ## __VA_ARGS__, _nat_y); \
189 } \
190}
191
192/*
193 * This loops over the entire map to load data. It inputs a line of data
194 * using the macro SECFILE_LOOKUP_LINE and then loops using the macro
195 * SET_XY_CHAR to load each char into the map at (map_x, map_y). Internal
196 * variables ch, map_x, map_y, nat_x, and nat_y are allocated within the
197 * macro but definable by the caller.
198 *
199 * Parameters:
200 * ch: a variable to hold a char (data for a single position,
201 * used by SET_XY_CHAR)
202 * ptile: current tile within the line (used by SET_XY_CHAR)
203 * SET_XY_CHAR: macro to load the map character at each (map_x, map_y)
204 * secfile: a secfile struct
205 * secpath, ...: path as used for sprintf() with arguments; the last item
206 * will be the y coordinate
207 * Example:
208 * LOAD_MAP_CHAR(ch, ptile,
209 * map_get_player_tile(ptile, plr)->terrain
210 * = char2terrain(ch), file, "player%d.map_t%04d", plrno);
211 *
212 * Note: some (but not all) of the code this is replacing used to skip over
213 * lines that did not exist. This allowed for backward-compatibility.
214 * We could add another parameter that specified whether it was OK to
215 * skip the data, but there's not really much advantage to exiting
216 * early in this case. Instead, we let any map data type to be empty,
217 * and just print an informative warning message about it.
218 */
219#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath, ...) \
220{ \
221 int _nat_x, _nat_y; \
222 bool _printed_warning = FALSE; \
223 for (_nat_y = 0; _nat_y < wld.map.ysize; _nat_y++) { \
224 const char *_line = secfile_lookup_str(secfile, secpath, \
225 ## __VA_ARGS__, _nat_y); \
226 if (NULL == _line) { \
227 char buf[64]; \
228 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
229 log_verbose("Line not found='%s'", buf); \
230 _printed_warning = TRUE; \
231 continue; \
232 } else if (strlen(_line) != wld.map.xsize) { \
233 char buf[64]; \
234 fc_snprintf(buf, sizeof(buf), secpath, ## __VA_ARGS__, _nat_y); \
235 log_verbose("Line too short (expected %d got " SIZE_T_PRINTF \
236 ")='%s'", wld.map.xsize, strlen(_line), buf); \
237 _printed_warning = TRUE; \
238 continue; \
239 } \
240 for (_nat_x = 0; _nat_x < wld.map.xsize; _nat_x++) { \
241 const char ch = _line[_nat_x]; \
242 struct tile *ptile = native_pos_to_tile(&(wld.map), _nat_x, _nat_y); \
243 (SET_XY_CHAR); \
244 } \
245 } \
246 if (_printed_warning) { \
247 /* TRANS: Minor error message. */ \
248 log_sg(_("Saved game contains incomplete map data. This can" \
249 " happen with old saved games, or it may indicate an" \
250 " invalid saved game file. Proceed at your own risk.")); \
251 } \
252}
253
254/* Iterate on the extras half-bytes */
255#define halfbyte_iterate_extras(e, num_extras_types) \
256{ \
257 int e; \
258 for (e = 0; 4 * e < (num_extras_types); e++) {
259
260#define halfbyte_iterate_extras_end \
261 } \
262}
263
264 struct savedata {
265 struct section_file *file;
266 char secfile_options[512];
267
268 /* set by the caller */
269 const char *save_reason;
270 bool scenario;
271
272 /* Set in sg_save_game(); needed in sg_save_map_*(); ... */
273 bool save_players;
274};
275
276#define TOKEN_SIZE 10
277
278 static const char savefile_options_default[] =
279 " +version3";
280/* The following savefile option are added if needed:
281 * - nothing at current version
282 * See also calls to sg_save_savefile_options(). */
283
284static void savegame3_save_real(struct section_file *file,
285 const char *save_reason,
286 bool scenario);
287static struct loaddata *loaddata_new(struct section_file *file);
288static void loaddata_destroy(struct loaddata *loading);
289
290static struct savedata *savedata_new(struct section_file *file,
291 const char *save_reason,
292 bool scenario);
293static void savedata_destroy(struct savedata *saving);
294
295static enum unit_orders char2order(char order);
296static char order2char(enum unit_orders order);
297static enum direction8 char2dir(char dir);
298static char dir2char(enum direction8 dir);
299static char activity2char(int activity);
300static enum unit_activity char2activity(char activity);
301static char *quote_block(const void *const data, int length);
302static int unquote_block(const char *const quoted_, void *dest,
303 int dest_length);
304static void worklist_load(struct section_file *file, int wlist_max_length,
305 struct worklist *pwl, const char *path, ...);
306static void worklist_save(struct section_file *file,
307 const struct worklist *pwl,
308 int max_length, const char *path, ...);
309static void unit_ordering_calc(void);
310static void unit_ordering_apply(void);
311static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx);
312static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx);
313static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
314 const int *idx);
315static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
316 const int *idx);
317static struct terrain *char2terrain(char ch);
318static char terrain2char(const struct terrain *pterrain);
319static Tech_type_id technology_load(struct section_file *file,
320 const char *path, int plrno);
321static void technology_save(struct section_file *file,
322 const char *path, int plrno, Tech_type_id tech);
323
324static void sg_load_savefile(struct loaddata *loading);
325static void sg_save_savefile(struct savedata *saving);
326static void sg_save_savefile_options(struct savedata *saving,
327 const char *option);
328
329static void sg_load_game(struct loaddata *loading);
330static void sg_save_game(struct savedata *saving);
331
332static void sg_load_ruledata(struct loaddata *loading);
333static void sg_save_ruledata(struct savedata *saving);
334
335static void sg_load_random(struct loaddata *loading);
336static void sg_save_random(struct savedata *saving);
337
338static void sg_load_script(struct loaddata *loading);
339static void sg_save_script(struct savedata *saving);
340
341static void sg_load_scenario(struct loaddata *loading);
342static void sg_save_scenario(struct savedata *saving);
343
344static void sg_load_settings(struct loaddata *loading);
345static void sg_save_settings(struct savedata *saving);
346
347static void sg_load_counters (struct loaddata * loading);
348static void sg_save_counters (struct savedata * saving);
349
350static void sg_load_map(struct loaddata *loading);
351static void sg_save_map(struct savedata *saving);
352static void sg_load_map_tiles(struct loaddata *loading);
353static void sg_save_map_tiles(struct savedata *saving);
354static void sg_load_map_tiles_extras(struct loaddata *loading);
355static void sg_save_map_tiles_extras(struct savedata *saving);
356
357static void sg_load_map_startpos(struct loaddata *loading);
358static void sg_save_map_startpos(struct savedata *saving);
359static void sg_load_map_owner(struct loaddata *loading);
360static void sg_save_map_owner(struct savedata *saving);
361static void sg_load_map_worked(struct loaddata *loading);
362static void sg_save_map_worked(struct savedata *saving);
363static void sg_load_map_known(struct loaddata *loading);
364static void sg_save_map_known(struct savedata *saving);
365
366static void sg_load_players_basic(struct loaddata *loading);
367static void sg_load_players(struct loaddata *loading);
368static void sg_load_player_main(struct loaddata *loading,
369 struct player *plr);
370static void sg_load_player_cities(struct loaddata *loading,
371 struct player *plr);
372static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
373 struct city *pcity, const char *citystr,
374 int wlist_max_length, int routes_max);
375static void sg_load_player_city_citizens(struct loaddata *loading,
376 struct player *plr,
377 struct city *pcity,
378 const char *citystr);
379static void sg_load_player_units(struct loaddata *loading,
380 struct player *plr);
381static bool sg_load_player_unit(struct loaddata *loading,
382 struct player *plr, struct unit *punit,
383 int orders_max_length,
384 const char *unitstr);
385static void sg_load_player_units_transport(struct loaddata *loading,
386 struct player *plr);
387static void sg_load_player_attributes(struct loaddata *loading,
388 struct player *plr);
389static void sg_load_player_vision(struct loaddata *loading,
390 struct player *plr);
391static bool sg_load_player_vision_city(struct loaddata *loading,
392 struct player *plr,
393 struct vision_site *pdcity,
394 const char *citystr);
395static void sg_save_players(struct savedata *saving);
396static void sg_save_player_main(struct savedata *saving,
397 struct player *plr);
398static void sg_save_player_cities(struct savedata *saving,
399 struct player *plr);
400static void sg_save_player_units(struct savedata *saving,
401 struct player *plr);
402static void sg_save_player_attributes(struct savedata *saving,
403 struct player *plr);
404static void sg_save_player_vision(struct savedata *saving,
405 struct player *plr);
406
407static void sg_load_researches(struct loaddata *loading);
408static void sg_save_researches(struct savedata *saving);
409
410static void sg_load_event_cache(struct loaddata *loading);
411static void sg_save_event_cache(struct savedata *saving);
412
413static void sg_load_treaties(struct loaddata *loading);
414static void sg_save_treaties(struct savedata *saving);
415
416static void sg_load_history(struct loaddata *loading);
417static void sg_save_history(struct savedata *saving);
418
419static void sg_load_mapimg(struct loaddata *loading);
420static void sg_save_mapimg(struct savedata *saving);
421
422static void sg_load_sanitycheck(struct loaddata *loading);
423static void sg_save_sanitycheck(struct savedata *saving);
424
425
426/************************************************************************/
429 void savegame3_save(struct section_file *sfile, const char *save_reason,
430 bool scenario)
431{
432 fc_assert_ret(sfile != NULL);
433
434#ifdef DEBUG_TIMERS
435 struct timer *savetimer = timer_new(TIMER_CPU, TIMER_DEBUG, "save");
436 timer_start(savetimer);
437#endif
438
439 log_verbose("saving game in new format ...");
440 savegame3_save_real(sfile, save_reason, scenario);
441
442#ifdef DEBUG_TIMERS
443 timer_stop(savetimer);
444 log_debug("Creating secfile in %.3f seconds.", timer_read_seconds(savetimer));
445 timer_destroy(savetimer);
446#endif /* DEBUG_TIMERS */
447}
448
449/* =======================================================================
450 * Basic load / save functions.
451 * ======================================================================= */
452
453/************************************************************************/
456 void savegame3_load(struct section_file *file)
457{
458 struct loaddata *loading;
459 bool was_send_city_suppressed, was_send_tile_suppressed;
460
461 /* initialise loading */
462 was_send_city_suppressed = send_city_suppression(TRUE);
463 was_send_tile_suppressed = send_tile_suppression(TRUE);
464 loading = loaddata_new(file);
465 sg_success = TRUE;
466
467 /* Load the savegame data. */
468 /* [compat] */
469 sg_load_compat(loading, SAVEGAME_3);
470 /* [scenario] */
471 sg_load_scenario(loading);
472 /* [savefile] */
473 sg_load_savefile(loading);
474 /* [game] */
475 sg_load_game(loading);
476 /* [random] */
477 sg_load_random(loading);
478 /* [settings] */
479 sg_load_settings(loading);
480 /* [ruledata] */
481 sg_load_ruledata(loading);
482 /* [players] (basic data) */
483 sg_load_players_basic(loading);
484 /* [map]; needs width and height loaded by [settings] */
485 sg_load_map(loading);
486 /* [research] */
487 sg_load_researches(loading);
488 /* [player<i>] */
489 sg_load_players(loading);
490 /* [counters] */
491 sg_load_counters(loading);
492 /* [event_cache] */
493 sg_load_event_cache(loading);
494 /* [treaties] */
495 sg_load_treaties(loading);
496 /* [history] */
497 sg_load_history(loading);
498 /* [mapimg] */
499 sg_load_mapimg(loading);
500 /* [script] -- must come last as may reference game objects */
501 sg_load_script(loading);
502 /* [post_load_compat]; needs the game loaded by [savefile] */
503 sg_load_post_load_compat(loading, SAVEGAME_3);
504
505 /* Sanity checks for the loaded game. */
506 sg_load_sanitycheck(loading);
507
508 /* deinitialise loading */
509 loaddata_destroy(loading);
510 send_tile_suppression(was_send_tile_suppressed);
511 send_city_suppression(was_send_city_suppressed);
512
513 if (!sg_success) {
514 log_error("Failure loading savegame!");
515 /* Try to get the server back to a vaguely sane state */
516 server_game_free();
517 server_game_init(FALSE);
518 load_rulesets(NULL, NULL, FALSE, NULL, TRUE, FALSE, TRUE);
519 }
520}
521
522/************************************************************************/
525 static void savegame3_save_real(struct section_file *file,
526 const char *save_reason,
527 bool scenario)
528{
529 struct savedata *saving;
530
531 /* initialise loading */
532 saving = savedata_new(file, save_reason, scenario);
533 sg_success = TRUE;
534
535 /* [scenario] */
536 /* This should be first section so scanning through all scenarios just for
537 * names and descriptions would go faster. */
538 sg_save_scenario(saving);
539 /* [savefile] */
540 sg_save_savefile(saving);
541 /* [counters] */
542 sg_save_counters(saving);
543 /* [game] */
544 sg_save_game(saving);
545 /* [random] */
546 sg_save_random(saving);
547 /* [script] */
548 sg_save_script(saving);
549 /* [settings] */
550 sg_save_settings(saving);
551 /* [ruledata] */
552 sg_save_ruledata(saving);
553 /* [map] */
554 sg_save_map(saving);
555 /* [player<i>] */
556 sg_save_players(saving);
557 /* [research] */
558 sg_save_researches(saving);
559 /* [event_cache] */
560 sg_save_event_cache(saving);
561 /* [treaty<i>] */
562 sg_save_treaties(saving);
563 /* [history] */
564 sg_save_history(saving);
565 /* [mapimg] */
566 sg_save_mapimg(saving);
567
568 /* Sanity checks for the saved game. */
569 sg_save_sanitycheck(saving);
570
571 /* deinitialise saving */
572 savedata_destroy(saving);
573
574 if (!sg_success) {
575 log_error("Failure saving savegame!");
576 }
577}
578
579/************************************************************************/
582 static struct loaddata *loaddata_new(struct section_file *file)
583{
584 struct loaddata *loading = calloc(1, sizeof(*loading));
585 loading->file = file;
586 loading->secfile_options = NULL;
587
588 loading->improvement.order = NULL;
589 loading->improvement.size = -1;
590 loading->technology.order = NULL;
591 loading->technology.size = -1;
592 loading->activities.order = NULL;
593 loading->activities.size = -1;
594 loading->trait.order = NULL;
595 loading->trait.size = -1;
596 loading->extra.order = NULL;
597 loading->extra.size = -1;
598 loading->multiplier.order = NULL;
599 loading->multiplier.size = -1;
600 loading->specialist.order = NULL;
601 loading->specialist.size = -1;
602 loading->action.order = NULL;
603 loading->action.size = -1;
604 loading->act_dec.order = NULL;
605 loading->act_dec.size = -1;
606 loading->ssa.order = NULL;
607 loading->ssa.size = -1;
608 loading->coptions.order = NULL;
609 loading->coptions.size = -1;
610
611 loading->server_state = S_S_INITIAL;
612 loading->rstate = fc_rand_state();
613 loading->worked_tiles = NULL;
614
615 return loading;
616}
617
618/************************************************************************/
621 static void loaddata_destroy(struct loaddata *loading)
622{
623 if (loading->improvement.order != NULL) {
624 free(loading->improvement.order);
625 }
626
627 if (loading->technology.order != NULL) {
628 free(loading->technology.order);
629 }
630
631 if (loading->activities.order != NULL) {
632 free(loading->activities.order);
633 }
634
635 if (loading->trait.order != NULL) {
636 free(loading->trait.order);
637 }
638
639 if (loading->extra.order != NULL) {
640 free(loading->extra.order);
641 }
642
643 if (loading->multiplier.order != NULL) {
644 free(loading->multiplier.order);
645 }
646
647 if (loading->specialist.order != NULL) {
648 free(loading->specialist.order);
649 }
650
651 if (loading->action.order != NULL) {
652 free(loading->action.order);
653 }
654
655 if (loading->act_dec.order != NULL) {
656 free(loading->act_dec.order);
657 }
658
659 if (loading->ssa.order != NULL) {
660 free(loading->ssa.order);
661 }
662
663 if (loading->coptions.order != NULL) {
664 free(loading->coptions.order);
665 }
666
667 if (loading->worked_tiles != NULL) {
668 free(loading->worked_tiles);
669 }
670
671 free(loading);
672}
673
674/************************************************************************/
677 static struct savedata *savedata_new(struct section_file *file,
678 const char *save_reason,
679 bool scenario)
680{
681 struct savedata *saving = calloc(1, sizeof(*saving));
682 saving->file = file;
683 saving->secfile_options[0] = '\0';
684
685 saving->save_reason = save_reason;
686 saving->scenario = scenario;
687
688 saving->save_players = FALSE;
689
690 return saving;
691}
692
693/************************************************************************/
696 static void savedata_destroy(struct savedata *saving)
697{
698 free(saving);
699}
700
701/* =======================================================================
702 * Helper functions.
703 * ======================================================================= */
704
705/************************************************************************/
708 static enum unit_orders char2order(char order)
709{
710 switch (order) {
711 case 'm':
712 case 'M':
713 return ORDER_MOVE;
714 case 'w':
715 case 'W':
716 return ORDER_FULL_MP;
717 case 'a':
718 case 'A':
719 return ORDER_ACTIVITY;
720 case 'x':
721 case 'X':
722 return ORDER_ACTION_MOVE;
723 case 'p':
724 case 'P':
725 return ORDER_PERFORM_ACTION;
726 }
727
728 /* This can happen if the savegame is invalid. */
729 return ORDER_LAST;
730}
731
732/************************************************************************/
735 static char order2char(enum unit_orders order)
736{
737 switch (order) {
738 case ORDER_MOVE:
739 return 'm';
740 case ORDER_FULL_MP:
741 return 'w';
742 case ORDER_ACTIVITY:
743 return 'a';
744 case ORDER_ACTION_MOVE:
745 return 'x';
746 case ORDER_PERFORM_ACTION:
747 return 'p';
748 case ORDER_LAST:
749 break;
750 }
751
752 fc_assert(FALSE);
753 return '?';
754}
755
756/************************************************************************/
759 static enum direction8 char2dir(char dir)
760{
761 /* Numberpad values for the directions. */
762 switch (dir) {
763 case '1':
764 return DIR8_SOUTHWEST;
765 case '2':
766 return DIR8_SOUTH;
767 case '3':
768 return DIR8_SOUTHEAST;
769 case '4':
770 return DIR8_WEST;
771 case '6':
772 return DIR8_EAST;
773 case '7':
774 return DIR8_NORTHWEST;
775 case '8':
776 return DIR8_NORTH;
777 case '9':
778 return DIR8_NORTHEAST;
779 }
780
781 /* This can happen if the savegame is invalid. */
782 return direction8_invalid();
783}
784
785/************************************************************************/
788 static char dir2char(enum direction8 dir)
789{
790 /* Numberpad values for the directions. */
791 switch (dir) {
792 case DIR8_NORTH:
793 return '8';
794 case DIR8_SOUTH:
795 return '2';
796 case DIR8_EAST:
797 return '6';
798 case DIR8_WEST:
799 return '4';
800 case DIR8_NORTHEAST:
801 return '9';
802 case DIR8_NORTHWEST:
803 return '7';
804 case DIR8_SOUTHEAST:
805 return '3';
806 case DIR8_SOUTHWEST:
807 return '1';
808 }
809
810 fc_assert(FALSE);
811
812 return '?';
813}
814
815/************************************************************************/
821 static char activity2char(int activity)
822{
823 switch (activity) {
824 case ACTIVITY_IDLE:
825 return 'w';
826 case ACTIVITY_CLEAN:
827 return 'C';
828 case ACTIVITY_OLD_POLLUTION_SG3:
829 return 'p';
830 case ACTIVITY_MINE:
831 return 'm';
832 case ACTIVITY_PLANT:
833 return 'M';
834 case ACTIVITY_IRRIGATE:
835 return 'i';
836 case ACTIVITY_CULTIVATE:
837 return 'I';
838 case ACTIVITY_FORTIFIED:
839 return 'f';
840 case ACTIVITY_SENTRY:
841 return 's';
842 case ACTIVITY_PILLAGE:
843 return 'e';
844 case ACTIVITY_GOTO:
845 return 'g';
846 case ACTIVITY_EXPLORE:
847 return 'x';
848 case ACTIVITY_TRANSFORM:
849 return 'o';
850 case ACTIVITY_FORTIFYING:
851 return 'y';
852 case ACTIVITY_OLD_FALLOUT_SG3:
853 return 'u';
854 case ACTIVITY_BASE:
855 return 'b';
856 case ACTIVITY_GEN_ROAD:
857 return 'R';
858 case ACTIVITY_CONVERT:
859 return 'c';
860 case ACTIVITY_LAST:
861 break;
862 }
863
864 fc_assert(FALSE);
865
866 return '?';
867}
868
869/************************************************************************/
872 static enum unit_activity char2activity(char activity)
873{
874 enum unit_activity a;
875
876 for (a = 0; a < ACTIVITY_LAST_SAVEGAME3; a++) {
877 /* Skip ACTIVITY_LAST. The SAVEGAME3 specific values are after it. */
878 if (a != ACTIVITY_LAST) {
879 char achar = activity2char(a);
880
881 if (activity == achar) {
882 return a;
883 }
884 }
885 }
886
887 /* This can happen if the savegame is invalid. */
888 return ACTIVITY_LAST;
889}
890
891/************************************************************************/
895 static char *quote_block(const void *const data, int length)
896{
897 char *buffer = fc_malloc(length * 3 + 10);
898 size_t offset;
899 int i;
900
901 sprintf(buffer, "%d:", length);
902 offset = strlen(buffer);
903
904 for (i = 0; i < length; i++) {
905 sprintf(buffer + offset, "%02x ", ((unsigned char *) data)[i]);
906 offset += 3;
907 }
908 return buffer;
909}
910
911/************************************************************************/
916 static int unquote_block(const char *const quoted_, void *dest,
917 int dest_length)
918{
919 int i, length, parsed, tmp;
920 char *endptr;
921 const char *quoted = quoted_;
922
923 parsed = sscanf(quoted, "%d", &length);
924
925 if (parsed != 1) {
926 log_error(_("Syntax error in attribute block."));
927 return 0;
928 }
929
930 if (length > dest_length) {
931 return 0;
932 }
933
934 quoted = strchr(quoted, ':');
935
936 if (quoted == NULL) {
937 log_error(_("Syntax error in attribute block."));
938 return 0;
939 }
940
941 quoted++;
942
943 for (i = 0; i < length; i++) {
944 tmp = strtol(quoted, &endptr, 16);
945
946 if ((endptr - quoted) != 2
947 || *endptr != ' '
948 || (tmp & 0xff) != tmp) {
949 log_error(_("Syntax error in attribute block."));
950 return 0;
951 }
952
953 ((unsigned char *) dest)[i] = tmp;
954 quoted += 3;
955 }
956
957 return length;
958}
959
960/************************************************************************/
964 static void worklist_load(struct section_file *file, int wlist_max_length,
965 struct worklist *pwl, const char *path, ...)
966{
967 int i;
968 const char *kind;
969 const char *name;
970 char path_str[1024];
971 va_list ap;
972
973 /* The first part of the registry path is taken from the varargs to the
974 * function. */
975 va_start(ap, path);
976 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
977 va_end(ap);
978
979 worklist_init(pwl);
980 pwl->length = secfile_lookup_int_default(file, 0,
981 "%s.wl_length", path_str);
982
983 for (i = 0; i < pwl->length; i++) {
984 kind = secfile_lookup_str(file, "%s.wl_kind%d", path_str, i);
985
986 /* We lookup the production value by name. An invalid entry isn't a
987 * fatal error; we just truncate the worklist. */
988 name = secfile_lookup_str_default(file, "-", "%s.wl_value%d",
989 path_str, i);
990 pwl->entries[i] = universal_by_rule_name(kind, name);
991 if (pwl->entries[i].kind == universals_n_invalid()) {
992 log_sg("%s.wl_value%d: unknown \"%s\" \"%s\".", path_str, i, kind,
993 name);
994 pwl->length = i;
995 break;
996 }
997 }
998
999 /* Padding entries */
1000 for (; i < wlist_max_length; i++) {
1001 (void) secfile_entry_lookup(file, "%s.wl_kind%d", path_str, i);
1002 (void) secfile_entry_lookup(file, "%s.wl_value%d", path_str, i);
1003 }
1004}
1005
1006/************************************************************************/
1010 static void worklist_save(struct section_file *file,
1011 const struct worklist *pwl,
1012 int max_length, const char *path, ...)
1013{
1014 char path_str[1024];
1015 int i;
1016 va_list ap;
1017
1018 /* The first part of the registry path is taken from the varargs to the
1019 * function. */
1020 va_start(ap, path);
1021 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
1022 va_end(ap);
1023
1024 secfile_insert_int(file, pwl->length, "%s.wl_length", path_str);
1025
1026 for (i = 0; i < pwl->length; i++) {
1027 const struct universal *entry = pwl->entries + i;
1028 secfile_insert_str(file, universal_type_rule_name(entry),
1029 "%s.wl_kind%d", path_str, i);
1030 secfile_insert_str(file, universal_rule_name(entry),
1031 "%s.wl_value%d", path_str, i);
1032 }
1033
1034 fc_assert_ret(max_length <= MAX_LEN_WORKLIST);
1035
1036 /* We want to keep savegame in tabular format, so each line has to be
1037 * of equal length. Fill table up to maximum worklist size. */
1038 for (i = pwl->length ; i < max_length; i++) {
1039 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
1040 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
1041 }
1042}
1043
1044/************************************************************************/
1048 static void unit_ordering_calc(void)
1049{
1050 int j;
1051
1052 players_iterate(pplayer) {
1053 /* to avoid junk values for unsupported units: */
1054 unit_list_iterate(pplayer->units, punit) {
1055 punit->server.ord_city = 0;
1056 } unit_list_iterate_end;
1057 city_list_iterate(pplayer->cities, pcity) {
1058 j = 0;
1059 unit_list_iterate(pcity->units_supported, punit) {
1060 punit->server.ord_city = j++;
1061 } unit_list_iterate_end;
1062 } city_list_iterate_end;
1063 } players_iterate_end;
1064
1065 whole_map_iterate(&(wld.map), ptile) {
1066 j = 0;
1067 unit_list_iterate(ptile->units, punit) {
1068 punit->server.ord_map = j++;
1069 } unit_list_iterate_end;
1070 } whole_map_iterate_end;
1071}
1072
1073/************************************************************************/
1077 static void unit_ordering_apply(void)
1078{
1079 players_iterate(pplayer) {
1080 city_list_iterate(pplayer->cities, pcity) {
1081 unit_list_sort_ord_city(pcity->units_supported);
1082 }
1083 city_list_iterate_end;
1084 } players_iterate_end;
1085
1086 whole_map_iterate(&(wld.map), ptile) {
1087 unit_list_sort_ord_map(ptile->units);
1088 } whole_map_iterate_end;
1089}
1090
1091/************************************************************************/
1098 static void sg_extras_set_dbv(struct dbv *extras, char ch,
1099 struct extra_type **idx)
1100{
1101 int i, bin;
1102 const char *pch = strchr(hex_chars, ch);
1103
1104 if (!pch || ch == '\0') {
1105 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1106 bin = 0;
1107 } else {
1108 bin = pch - hex_chars;
1109 }
1110
1111 for (i = 0; i < 4; i++) {
1112 struct extra_type *pextra = idx[i];
1113
1114 if (pextra == NULL) {
1115 continue;
1116 }
1117 if ((bin & (1 << i))
1118 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1119 dbv_set(extras, extra_index(pextra));
1120 }
1121 }
1122}
1123
1124/************************************************************************/
1131 static void sg_extras_set_bv(bv_extras *extras, char ch,
1132 struct extra_type **idx)
1133{
1134 int i, bin;
1135 const char *pch = strchr(hex_chars, ch);
1136
1137 if (!pch || ch == '\0') {
1138 log_sg("Unknown hex value: '%c' (%d)", ch, ch);
1139 bin = 0;
1140 } else {
1141 bin = pch - hex_chars;
1142 }
1143
1144 for (i = 0; i < 4; i++) {
1145 struct extra_type *pextra = idx[i];
1146
1147 if (pextra == NULL) {
1148 continue;
1149 }
1150 if ((bin & (1 << i))
1151 && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) {
1152 BV_SET(*extras, extra_index(pextra));
1153 }
1154 }
1155}
1156
1157/************************************************************************/
1163 static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource,
1164 const int *idx)
1165{
1166 int i, bin = 0;
1167 int max = dbv_bits(extras);
1168
1169 for (i = 0; i < 4; i++) {
1170 int extra = idx[i];
1171
1172 if (extra < 0) {
1173 break;
1174 }
1175
1176 if (extra < max
1177 && (dbv_isset(extras, extra)
1178 /* An invalid resource, a resource that can't exist at the tile's
1179 * current terrain, isn't in the bit extra vector. Save it so it
1180 * can return if the tile's terrain changes to something it can
1181 * exist on. */
1182 || extra_by_number(extra) == presource)) {
1183 bin |= (1 << i);
1184 }
1185 }
1186
1187 return hex_chars[bin];
1188}
1189
1190/************************************************************************/
1196 static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource,
1197 const int *idx)
1198{
1199 int i, bin = 0;
1200
1201 for (i = 0; i < 4; i++) {
1202 int extra = idx[i];
1203
1204 if (extra < 0) {
1205 break;
1206 }
1207
1208 if (BV_ISSET(extras, extra)
1209 /* An invalid resource, a resource that can't exist at the tile's
1210 * current terrain, isn't in the bit extra vector. Save it so it
1211 * can return if the tile's terrain changes to something it can
1212 * exist on. */
1213 || extra_by_number(extra) == presource) {
1214 bin |= (1 << i);
1215 }
1216 }
1217
1218 return hex_chars[bin];
1219}
1220
1221/************************************************************************/
1225 static struct terrain *char2terrain(char ch)
1226{
1227 /* terrain_by_identifier plus fatal error */
1228 if (ch == TERRAIN_UNKNOWN_IDENTIFIER) {
1229 return T_UNKNOWN;
1230 }
1231 terrain_type_iterate(pterrain) {
1232 if (pterrain->identifier_load == ch) {
1233 return pterrain;
1234 }
1235 } terrain_type_iterate_end;
1236
1237 log_fatal("Unknown terrain identifier '%c' in savegame.", ch);
1238
1239 exit(EXIT_FAILURE);
1240
1241 RETURN_VALUE_AFTER_EXIT(NULL);
1242}
1243
1244/************************************************************************/
1248 static char terrain2char(const struct terrain *pterrain)
1249{
1250 if (pterrain == T_UNKNOWN) {
1251 return TERRAIN_UNKNOWN_IDENTIFIER;
1252 } else {
1253 return pterrain->identifier;
1254 }
1255}
1256
1257/************************************************************************/
1261 static Tech_type_id technology_load(struct section_file *file,
1262 const char *path, int plrno)
1263{
1264 char path_with_name[128];
1265 const char *name;
1266 struct advance *padvance;
1267
1268 fc_snprintf(path_with_name, sizeof(path_with_name),
1269 "%s_name", path);
1270
1271 name = secfile_lookup_str(file, path_with_name, plrno);
1272
1273 if (!name || name[0] == '\0') {
1274 /* used by researching_saved */
1275 return A_UNKNOWN;
1276 }
1277 if (fc_strcasecmp(name, "A_FUTURE") == 0) {
1278 return A_FUTURE;
1279 }
1280 if (fc_strcasecmp(name, "A_NONE") == 0) {
1281 return A_NONE;
1282 }
1283 if (fc_strcasecmp(name, "A_UNSET") == 0) {
1284 return A_UNSET;
1285 }
1286
1287 padvance = advance_by_rule_name(name);
1288 sg_failure_ret_val(NULL != padvance, A_NONE,
1289 "%s: unknown technology \"%s\".", path_with_name, name);
1290
1291 return advance_number(padvance);
1292}
1293
1294/************************************************************************/
1297 static void technology_save(struct section_file *file,
1298 const char *path, int plrno, Tech_type_id tech)
1299{
1300 char path_with_name[128];
1301 const char *name;
1302
1303 fc_snprintf(path_with_name, sizeof(path_with_name),
1304 "%s_name", path);
1305
1306 switch (tech) {
1307 case A_UNKNOWN: /* used by researching_saved */
1308 name = "";
1309 break;
1310 case A_NONE:
1311 name = "A_NONE";
1312 break;
1313 case A_UNSET:
1314 name = "A_UNSET";
1315 break;
1316 case A_FUTURE:
1317 name = "A_FUTURE";
1318 break;
1319 default:
1320 name = advance_rule_name(advance_by_number(tech));
1321 break;
1322 }
1323
1324 secfile_insert_str(file, name, path_with_name, plrno);
1325}
1326
1327/* =======================================================================
1328 * Load / save savefile data.
1329 * ======================================================================= */
1330
1331/************************************************************************/
1334 static void sg_load_savefile(struct loaddata *loading)
1335{
1336 int i;
1337 const char *terr_name;
1338 bool ruleset_datafile;
1339 bool current_ruleset_rejected;
1340 const char *str;
1341
1342 /* Check status and return if not OK (sg_success FALSE). */
1343 sg_check_ret();
1344
1345 /* Load savefile options. */
1346 loading->secfile_options
1347 = secfile_lookup_str(loading->file, "savefile.options");
1348
1349 /* We don't need these entries, but read them anyway to avoid
1350 * warnings about unread secfile entries. */
1351 (void) secfile_entry_by_path(loading->file, "savefile.reason");
1352 (void) secfile_entry_by_path(loading->file, "savefile.revision");
1353
1354 str = secfile_lookup_str(loading->file, "savefile.orig_version");
1355 sz_strlcpy(game.server.orig_game_version, str);
1356
1357 if (game.scenario.datafile[0] != '\0') {
1358 ruleset_datafile = FALSE;
1359 } else {
1360 ruleset_datafile = TRUE;
1361 }
1362
1363 current_ruleset_rejected = FALSE;
1364 if (game.scenario.is_scenario && !game.scenario.ruleset_locked) {
1365 const char *req_caps;
1366
1367 if (!load_rulesets(NULL, NULL, FALSE, NULL, TRUE, FALSE,
1368 ruleset_datafile)) {
1369 /* Failed to load correct ruleset */
1370 sg_failure_ret(FALSE, _("Failed to load ruleset '%s'."),
1371 game.server.rulesetdir);
1372 }
1373
1374 req_caps = secfile_lookup_str_default(loading->file, "",
1375 "scenario.ruleset_caps");
1376 strncpy(game.scenario.req_caps, req_caps,
1377 sizeof(game.scenario.req_caps) - 1);
1378 game.scenario.req_caps[sizeof(game.scenario.req_caps) - 1] = '\0';
1379
1380 if (!has_capabilities(req_caps, game.ruleset_capabilities)) {
1381 /* Current ruleset lacks required capabilities. */
1382 log_normal(_("Scenario requires ruleset capabilities: %s"), req_caps);
1383 log_normal(_("Ruleset has capabilities: %s"),
1384 game.ruleset_capabilities);
1385 /* TRANS: ... ruleset dir ... scenario name ... */
1386 log_error(_("Current ruleset %s not compatible with the scenario %s."
1387 " Trying to switch to the ruleset specified by the"
1388 " scenario."),
1389 game.server.rulesetdir, game.scenario.name);
1390
1391 current_ruleset_rejected = TRUE;
1392 }
1393 }
1394
1395 if (!game.scenario.is_scenario || game.scenario.ruleset_locked
1396 || current_ruleset_rejected) {
1397 const char *ruleset, *alt_dir;
1398
1399 ruleset = secfile_lookup_str_default(loading->file,
1400 GAME_DEFAULT_RULESETDIR,
1401 "savefile.rulesetdir");
1402
1403 /* Load ruleset. */
1404 sz_strlcpy(game.server.rulesetdir, ruleset);
1405 if (!strcmp("default", game.server.rulesetdir)) {
1406 /* Here 'default' really means current default.
1407 * Saving happens with real ruleset name, so savegames containing this
1408 * are special scenarios. */
1409 sz_strlcpy(game.server.rulesetdir, GAME_DEFAULT_RULESETDIR);
1410 log_verbose("Savegame specified ruleset '%s'. Really loading '%s'.",
1411 ruleset, game.server.rulesetdir);
1412 }
1413
1414 alt_dir = secfile_lookup_str_default(loading->file, NULL,
1415 "savefile.ruleset_alt_dir");
1416
1417 if (!load_rulesets(NULL, alt_dir, FALSE, NULL, TRUE, FALSE, ruleset_datafile)) {
1418 if (alt_dir) {
1419 sg_failure_ret(FALSE,
1420 _("Failed to load either of rulesets '%s' or '%s' "
1421 "needed for savegame."),
1422 ruleset, alt_dir);
1423 } else {
1424 sg_failure_ret(FALSE,
1425 _("Failed to load ruleset '%s' needed for savegame."),
1426 ruleset);
1427 }
1428 }
1429
1430 if (current_ruleset_rejected) {
1431 /* TRANS: ruleset dir */
1432 log_normal(_("Successfully loaded the scenario's ruleset %s."), ruleset);
1433 }
1434 }
1435
1436 /* Remove all aifill players. Correct number of them get created later
1437 * with correct skill level etc. */
1438 (void) aifill(0);
1439
1440 /* Time to load scenario specific luadata */
1441 if (game.scenario.datafile[0] != '\0') {
1442 if (!fc_strcasecmp("none", game.scenario.datafile)) {
1443 game.server.luadata = NULL;
1444 } else {
1445 const struct strvec *pathes[] = { get_scenario_dirs(), NULL };
1446 const struct strvec **path;
1447 const char *found = NULL;
1448 char testfile[MAX_LEN_PATH];
1449 struct section_file *secfile;
1450
1451 for (path = pathes; found == NULL && *path != NULL; path++) {
1452 fc_snprintf(testfile, sizeof(testfile), "%s.luadata", game.scenario.datafile);
1453
1454 found = fileinfoname(*path, testfile);
1455 }
1456
1457 if (found == NULL) {
1458 log_error(_("Can't find scenario luadata file %s.luadata."), game.scenario.datafile);
1459 sg_success = FALSE;
1460 return;
1461 }
1462
1463 secfile = secfile_load(found, FALSE);
1464 if (secfile == NULL) {
1465 log_error(_("Failed to load scenario luadata file %s.luadata"),
1466 game.scenario.datafile);
1467 sg_success = FALSE;
1468 return;
1469 }
1470
1471 game.server.luadata = secfile;
1472 }
1473 }
1474
1475 game.server.dbid = secfile_lookup_int_default(loading->file, -1,
1476 "savefile.dbid");
1477
1478 /* This is in the savegame only if the game has been started before savegame3.c time,
1479 * and in that case it's TRUE. If it's missing, it's to be considered FALSE. */
1480 game.server.last_updated_year = secfile_lookup_bool_default(loading->file, FALSE,
1481 "savefile.last_updated_as_year");
1482
1483 /* Load improvements. */
1484 loading->improvement.size
1485 = secfile_lookup_int_default(loading->file, 0,
1486 "savefile.improvement_size");
1487 if (loading->improvement.size) {
1488 loading->improvement.order
1489 = secfile_lookup_str_vec(loading->file, &loading->improvement.size,
1490 "savefile.improvement_vector");
1491 sg_failure_ret(loading->improvement.size != 0,
1492 "Failed to load improvement order: %s",
1493 secfile_error());
1494 }
1495
1496 /* Load technologies. */
1497 loading->technology.size
1498 = secfile_lookup_int_default(loading->file, 0,
1499 "savefile.technology_size");
1500 if (loading->technology.size) {
1501 loading->technology.order
1502 = secfile_lookup_str_vec(loading->file, &loading->technology.size,
1503 "savefile.technology_vector");
1504 sg_failure_ret(loading->technology.size != 0,
1505 "Failed to load technology order: %s",
1506 secfile_error());
1507 }
1508
1509 /* Load Activities. */
1510 loading->activities.size
1511 = secfile_lookup_int_default(loading->file, 0,
1512 "savefile.activities_size");
1513 if (loading->activities.size) {
1514 loading->activities.order
1515 = secfile_lookup_str_vec(loading->file, &loading->activities.size,
1516 "savefile.activities_vector");
1517 sg_failure_ret(loading->activities.size != 0,
1518 "Failed to load activity order: %s",
1519 secfile_error());
1520 }
1521
1522 /* Load traits. */
1523 loading->trait.size
1524 = secfile_lookup_int_default(loading->file, 0,
1525 "savefile.trait_size");
1526 if (loading->trait.size) {
1527 loading->trait.order
1528 = secfile_lookup_str_vec(loading->file, &loading->trait.size,
1529 "savefile.trait_vector");
1530 sg_failure_ret(loading->trait.size != 0,
1531 "Failed to load trait order: %s",
1532 secfile_error());
1533 }
1534
1535 /* Load extras. */
1536 loading->extra.size
1537 = secfile_lookup_int_default(loading->file, 0,
1538 "savefile.extras_size");
1539 if (loading->extra.size) {
1540 const char **modname;
1541 size_t nmod;
1542 int j;
1543
1544 modname = secfile_lookup_str_vec(loading->file, &loading->extra.size,
1545 "savefile.extras_vector");
1546 sg_failure_ret(loading->extra.size != 0,
1547 "Failed to load extras order: %s",
1548 secfile_error());
1549 sg_failure_ret(!(game.control.num_extra_types < loading->extra.size),
1550 "Number of extras defined by the ruleset (= %d) are "
1551 "lower than the number in the savefile (= %d).",
1552 game.control.num_extra_types, (int)loading->extra.size);
1553 /* make sure that the size of the array is divisible by 4 */
1554 nmod = 4 * ((loading->extra.size + 3) / 4);
1555 loading->extra.order = fc_calloc(nmod, sizeof(*loading->extra.order));
1556 for (j = 0; j < loading->extra.size; j++) {
1557 loading->extra.order[j] = extra_type_by_rule_name(modname[j]);
1558 }
1559 free(modname);
1560 for (; j < nmod; j++) {
1561 loading->extra.order[j] = NULL;
1562 }
1563 }
1564
1565 /* Load multipliers. */
1566 loading->multiplier.size
1567 = secfile_lookup_int_default(loading->file, 0,
1568 "savefile.multipliers_size");
1569 if (loading->multiplier.size) {
1570 const char **modname;
1571 int j;
1572
1573 modname = secfile_lookup_str_vec(loading->file, &loading->multiplier.size,
1574 "savefile.multipliers_vector");
1575 sg_failure_ret(loading->multiplier.size != 0,
1576 "Failed to load multipliers order: %s",
1577 secfile_error());
1578 /* It's OK for the set of multipliers in the savefile to differ
1579 * from those in the ruleset. */
1580 loading->multiplier.order = fc_calloc(loading->multiplier.size,
1581 sizeof(*loading->multiplier.order));
1582 for (j = 0; j < loading->multiplier.size; j++) {
1583 loading->multiplier.order[j] = multiplier_by_rule_name(modname[j]);
1584 if (!loading->multiplier.order[j]) {
1585 log_verbose("Multiplier \"%s\" in savegame but not in ruleset, "
1586 "discarding", modname[j]);
1587 }
1588 }
1589 free(modname);
1590 }
1591
1592 /* Load specialists. */
1593 loading->specialist.size
1594 = secfile_lookup_int_default(loading->file, 0,
1595 "savefile.specialists_size");
1596 if (loading->specialist.size) {
1597 const char **modname;
1598 size_t nmod;
1599 int j;
1600
1601 modname = secfile_lookup_str_vec(loading->file, &loading->specialist.size,
1602 "savefile.specialists_vector");
1603 sg_failure_ret(loading->specialist.size != 0,
1604 "Failed to load specialists order: %s",
1605 secfile_error());
1606 sg_failure_ret(!(game.control.num_specialist_types < loading->specialist.size),
1607 "Number of specialists defined by the ruleset (= %d) are "
1608 "lower than the number in the savefile (= %d).",
1609 game.control.num_specialist_types, (int)loading->specialist.size);
1610 /* make sure that the size of the array is divisible by 4 */
1611 /* That's not really needed with specialists at the moment, but done this way
1612 * for consistency with other types, and to be prepared for the time it needs
1613 * to be this way. */
1614 nmod = 4 * ((loading->specialist.size + 3) / 4);
1615 loading->specialist.order = fc_calloc(nmod, sizeof(*loading->specialist.order));
1616 for (j = 0; j < loading->specialist.size; j++) {
1617 loading->specialist.order[j] = specialist_by_rule_name(modname[j]);
1618 }
1619 free(modname);
1620 for (; j < nmod; j++) {
1621 loading->specialist.order[j] = NULL;
1622 }
1623 }
1624
1625 /* Load action order. */
1626 loading->action.size = secfile_lookup_int_default(loading->file, 0,
1627 "savefile.action_size");
1628
1629 sg_failure_ret(loading->action.size > 0,
1630 "Failed to load action order: %s",
1631 secfile_error());
1632
1633 if (loading->action.size) {
1634 const char **modname;
1635 int j;
1636
1637 modname = secfile_lookup_str_vec(loading->file, &loading->action.size,
1638 "savefile.action_vector");
1639
1640 loading->action.order = fc_calloc(loading->action.size,
1641 sizeof(*loading->action.order));
1642
1643 for (j = 0; j < loading->action.size; j++) {
1644 struct action *real_action = action_by_rule_name(modname[j]);
1645
1646 if (real_action) {
1647 loading->action.order[j] = real_action->id;
1648 } else {
1649 log_sg("Unknown action \'%s\'", modname[j]);
1650 loading->action.order[j] = ACTION_NONE;
1651 }
1652 }
1653
1654 free(modname);
1655 }
1656
1657 /* Load action decision order. */
1658 loading->act_dec.size
1659 = secfile_lookup_int_default(loading->file, 0,
1660 "savefile.action_decision_size");
1661
1662 sg_failure_ret(loading->act_dec.size > 0,
1663 "Failed to load action decision order: %s",
1664 secfile_error());
1665
1666 if (loading->act_dec.size) {
1667 const char **modname;
1668 int j;
1669
1670 modname = secfile_lookup_str_vec(loading->file, &loading->act_dec.size,
1671 "savefile.action_decision_vector");
1672
1673 loading->act_dec.order = fc_calloc(loading->act_dec.size,
1674 sizeof(*loading->act_dec.order));
1675
1676 for (j = 0; j < loading->act_dec.size; j++) {
1677 loading->act_dec.order[j] = action_decision_by_name(modname[j],
1678 fc_strcasecmp);
1679 }
1680
1681 free(modname);
1682 }
1683
1684 /* Load server side agent order. */
1685 loading->ssa.size
1686 = secfile_lookup_int_default(loading->file, 0,
1687 "savefile.server_side_agent_size");
1688
1689 sg_failure_ret(loading->ssa.size > 0,
1690 "Failed to load server side agent order: %s",
1691 secfile_error());
1692
1693 if (loading->ssa.size) {
1694 const char **modname;
1695 int j;
1696
1697 modname = secfile_lookup_str_vec(loading->file, &loading->ssa.size,
1698 "savefile.server_side_agent_list");
1699
1700 loading->ssa.order = fc_calloc(loading->ssa.size,
1701 sizeof(*loading->ssa.order));
1702
1703 for (j = 0; j < loading->ssa.size; j++) {
1704 loading->ssa.order[j] = server_side_agent_by_name(modname[j],
1705 fc_strcasecmp);
1706 }
1707
1708 free(modname);
1709 }
1710
1711 /* Load city options order. */
1712 loading->coptions.size
1713 = secfile_lookup_int_default(loading->file, 0,
1714 "savefile.city_options_size");
1715
1716 sg_failure_ret(loading->coptions.size > 0,
1717 "Failed to load city options order: %s",
1718 secfile_error());
1719
1720 if (loading->coptions.size) {
1721 const char **modname;
1722 int j;
1723
1724 modname = secfile_lookup_str_vec(loading->file, &loading->coptions.size,
1725 "savefile.city_options_vector");
1726
1727 loading->coptions.order = fc_calloc(loading->coptions.size,
1728 sizeof(*loading->coptions.order));
1729
1730 for (j = 0; j < loading->coptions.size; j++) {
1731 loading->coptions.order[j] = city_options_by_name(modname[j],
1732 fc_strcasecmp);
1733 }
1734
1735 free(modname);
1736 }
1737
1738 /* Terrain identifiers */
1739 terrain_type_iterate(pterr) {
1740 pterr->identifier_load = '\0';
1741 } terrain_type_iterate_end;
1742
1743 i = 0;
1744 while ((terr_name = secfile_lookup_str_default(loading->file, NULL,
1745 "savefile.terrident%d.name", i)) != NULL) {
1746 struct terrain *pterr = terrain_by_rule_name(terr_name);
1747
1748 if (pterr != NULL) {
1749 const char *iptr = secfile_lookup_str_default(loading->file, NULL,
1750 "savefile.terrident%d.identifier", i);
1751
1752 pterr->identifier_load = *iptr;
1753 } else {
1754 log_error("Identifier for unknown terrain type %s.", terr_name);
1755 }
1756 i++;
1757 }
1758
1759 terrain_type_iterate(pterr) {
1760 terrain_type_iterate(pterr2) {
1761 if (pterr != pterr2 && pterr->identifier_load != '\0') {
1762 sg_failure_ret((pterr->identifier_load != pterr2->identifier_load),
1763 "%s and %s share a saved identifier",
1764 terrain_rule_name(pterr), terrain_rule_name(pterr2));
1765 }
1766 } terrain_type_iterate_end;
1767 } terrain_type_iterate_end;
1768}
1769
1770/************************************************************************/
1773 static void sg_save_savefile(struct savedata *saving)
1774{
1775 int i;
1776
1777 /* Check status and return if not OK (sg_success FALSE). */
1778 sg_check_ret();
1779
1780 /* Save savefile options. */
1781 sg_save_savefile_options(saving, savefile_options_default);
1782
1783 secfile_insert_int(saving->file, current_compat_ver(), "savefile.version");
1784
1785 /* Save reason of the savefile generation. */
1786 secfile_insert_str(saving->file, saving->save_reason, "savefile.reason");
1787
1788 /* Save as accurate freeciv revision information as possible */
1789 secfile_insert_str(saving->file, freeciv_datafile_version(), "savefile.revision");
1790
1791 /* Freeciv version used in the very first launch of this game -
1792 * or even saving in pregame. */
1793 secfile_insert_str(saving->file, game.server.orig_game_version,
1794 "savefile.orig_version");
1795
1796 /* Save rulesetdir at this point as this ruleset is required by this
1797 * savefile. */
1798 secfile_insert_str(saving->file, game.server.rulesetdir, "savefile.rulesetdir");
1799
1800 if (game.control.version[0] != '\0') {
1801 /* Current ruleset has version information, save it.
1802 * This is never loaded, but exist in savegame file only for debugging purposes. */
1803 secfile_insert_str(saving->file, game.control.version, "savefile.rulesetversion");
1804 }
1805
1806 if (game.control.alt_dir[0] != '\0') {
1807 secfile_insert_str(saving->file, game.control.alt_dir, "savefile.ruleset_alt_dir");
1808 }
1809
1810 if (game.server.last_updated_year) {
1811 secfile_insert_bool(saving->file, TRUE, "savefile.last_updated_as_year");
1812 }
1813
1814 secfile_insert_int(saving->file, game.server.dbid, "savefile.dbid");
1815
1816 /* Save improvement order in savegame, so we are not dependent on ruleset
1817 * order. If the game isn't started improvements aren't loaded so we can
1818 * not save the order. */
1819 secfile_insert_int(saving->file, improvement_count(),
1820 "savefile.improvement_size");
1821 if (improvement_count() > 0) {
1822 const char *buf[improvement_count()];
1823
1824 improvement_iterate(pimprove) {
1825 buf[improvement_index(pimprove)] = improvement_rule_name(pimprove);
1826 } improvement_iterate_end;
1827
1828 secfile_insert_str_vec(saving->file, buf, improvement_count(),
1829 "savefile.improvement_vector");
1830 }
1831
1832 /* Save technology order in savegame, so we are not dependent on ruleset
1833 * order. If the game isn't started advances aren't loaded so we can not
1834 * save the order. */
1835 secfile_insert_int(saving->file, game.control.num_tech_types,
1836 "savefile.technology_size");
1837 if (game.control.num_tech_types > 0) {
1838 const char *buf[game.control.num_tech_types];
1839
1840 buf[A_NONE] = "A_NONE";
1841 advance_iterate(a) {
1842 buf[advance_index(a)] = advance_rule_name(a);
1843 } advance_iterate_end;
1844 secfile_insert_str_vec(saving->file, buf, game.control.num_tech_types,
1845 "savefile.technology_vector");
1846 }
1847
1848 /* Save activities order in the savegame. */
1849 secfile_insert_int(saving->file, ACTIVITY_LAST,
1850 "savefile.activities_size");
1851 if (ACTIVITY_LAST > 0) {
1852 const char **modname;
1853 int j;
1854
1855 i = 0;
1856
1857 modname = fc_calloc(ACTIVITY_LAST, sizeof(*modname));
1858
1859 for (j = 0; j < ACTIVITY_LAST; j++) {
1860 modname[i++] = unit_activity_name(j);
1861 }
1862
1863 secfile_insert_str_vec(saving->file, modname,
1864 ACTIVITY_LAST,
1865 "savefile.activities_vector");
1866 free(modname);
1867 }
1868
1869 /* Save specialists order in the savegame. */
1870 secfile_insert_int(saving->file, specialist_count(),
1871 "savefile.specialists_size");
1872 {
1873 const char **modname;
1874
1875 i = 0;
1876 modname = fc_calloc(specialist_count(), sizeof(*modname));
1877
1878 specialist_type_iterate(sp) {
1879 modname[i++] = specialist_rule_name(specialist_by_number(sp));
1880 } specialist_type_iterate_end;
1881
1882 secfile_insert_str_vec(saving->file, modname, specialist_count(),
1883 "savefile.specialists_vector");
1884
1885 free(modname);
1886 }
1887
1888 /* Save trait order in savegame. */
1889 secfile_insert_int(saving->file, TRAIT_COUNT,
1890 "savefile.trait_size");
1891 {
1892 const char **modname;
1893 enum trait tr;
1894 int j;
1895
1896 modname = fc_calloc(TRAIT_COUNT, sizeof(*modname));
1897
1898 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
1899 modname[j] = trait_name(tr);
1900 }
1901
1902 secfile_insert_str_vec(saving->file, modname, TRAIT_COUNT,
1903 "savefile.trait_vector");
1904 free(modname);
1905 }
1906
1907 /* Save extras order in the savegame. */
1908 secfile_insert_int(saving->file, game.control.num_extra_types,
1909 "savefile.extras_size");
1910 if (game.control.num_extra_types > 0) {
1911 const char **modname;
1912
1913 i = 0;
1914 modname = fc_calloc(game.control.num_extra_types, sizeof(*modname));
1915
1916 extra_type_iterate(pextra) {
1917 modname[i++] = extra_rule_name(pextra);
1918 } extra_type_iterate_end;
1919
1920 secfile_insert_str_vec(saving->file, modname,
1921 game.control.num_extra_types,
1922 "savefile.extras_vector");
1923 free(modname);
1924 }
1925
1926 /* Save multipliers order in the savegame. */
1927 secfile_insert_int(saving->file, multiplier_count(),
1928 "savefile.multipliers_size");
1929 if (multiplier_count() > 0) {
1930 const char **modname;
1931
1932 modname = fc_calloc(multiplier_count(), sizeof(*modname));
1933
1934 multipliers_iterate(pmul) {
1935 modname[multiplier_index(pmul)] = multiplier_rule_name(pmul);
1936 } multipliers_iterate_end;
1937
1938 secfile_insert_str_vec(saving->file, modname,
1939 multiplier_count(),
1940 "savefile.multipliers_vector");
1941 free(modname);
1942 }
1943
1944 /* Save city_option order in the savegame. */
1945 secfile_insert_int(saving->file, CITYO_LAST,
1946 "savefile.city_options_size");
1947 if (CITYO_LAST > 0) {
1948 const char **modname;
1949 int j;
1950
1951 i = 0;
1952 modname = fc_calloc(CITYO_LAST, sizeof(*modname));
1953
1954 for (j = 0; j < CITYO_LAST; j++) {
1955 modname[i++] = city_options_name(j);
1956 }
1957
1958 secfile_insert_str_vec(saving->file, modname,
1959 CITYO_LAST,
1960 "savefile.city_options_vector");
1961 free(modname);
1962 }
1963
1964 /* Save action order in the savegame. */
1965 secfile_insert_int(saving->file, NUM_ACTIONS,
1966 "savefile.action_size");
1967 if (NUM_ACTIONS > 0) {
1968 const char **modname;
1969 int j;
1970
1971 i = 0;
1972 modname = fc_calloc(NUM_ACTIONS, sizeof(*modname));
1973
1974 for (j = 0; j < NUM_ACTIONS; j++) {
1975 modname[i++] = action_id_rule_name(j);
1976 }
1977
1978 secfile_insert_str_vec(saving->file, modname,
1979 NUM_ACTIONS,
1980 "savefile.action_vector");
1981 free(modname);
1982 }
1983
1984 /* Save action decision order in the savegame. */
1985 secfile_insert_int(saving->file, ACT_DEC_COUNT,
1986 "savefile.action_decision_size");
1987 if (ACT_DEC_COUNT > 0) {
1988 const char **modname;
1989 int j;
1990
1991 i = 0;
1992 modname = fc_calloc(ACT_DEC_COUNT, sizeof(*modname));
1993
1994 for (j = 0; j < ACT_DEC_COUNT; j++) {
1995 modname[i++] = action_decision_name(j);
1996 }
1997
1998 secfile_insert_str_vec(saving->file, modname,
1999 ACT_DEC_COUNT,
2000 "savefile.action_decision_vector");
2001 free(modname);
2002 }
2003
2004 /* Save server side agent order in the savegame. */
2005 secfile_insert_int(saving->file, SSA_COUNT,
2006 "savefile.server_side_agent_size");
2007 if (SSA_COUNT > 0) {
2008 const char **modname;
2009 int j;
2010
2011 i = 0;
2012 modname = fc_calloc(SSA_COUNT, sizeof(*modname));
2013
2014 for (j = 0; j < SSA_COUNT; j++) {
2015 modname[i++] = server_side_agent_name(j);
2016 }
2017
2018 secfile_insert_str_vec(saving->file, modname,
2019 SSA_COUNT,
2020 "savefile.server_side_agent_list");
2021 free(modname);
2022 }
2023
2024 /* Save terrain character mapping in the savegame. */
2025 i = 0;
2026 terrain_type_iterate(pterr) {
2027 char buf[2];
2028
2029 secfile_insert_str(saving->file, terrain_rule_name(pterr), "savefile.terrident%d.name", i);
2030 buf[0] = terrain_identifier(pterr);
2031 buf[1] = '\0';
2032 secfile_insert_str(saving->file, buf, "savefile.terrident%d.identifier", i++);
2033 } terrain_type_iterate_end;
2034}
2035
2036/************************************************************************/
2039 static void sg_save_savefile_options(struct savedata *saving,
2040 const char *option)
2041{
2042 /* Check status and return if not OK (sg_success FALSE). */
2043 sg_check_ret();
2044
2045 if (option == NULL) {
2046 /* no additional option */
2047 return;
2048 }
2049
2050 sz_strlcat(saving->secfile_options, option);
2051 secfile_replace_str(saving->file, saving->secfile_options,
2052 "savefile.options");
2053}
2054
2055/* =======================================================================
2056 * Load / save game status.
2057 * ======================================================================= */
2058
2059/************************************************************************/
2062 static void sg_load_ruledata(struct loaddata *loading)
2063{
2064 int i;
2065 const char *name;
2066
2067 /* Check status and return if not OK (sg_success FALSE). */
2068 sg_check_ret();
2069
2070 for (i = 0;
2071 (name = secfile_lookup_str_default(loading->file, NULL,
2072 "ruledata.government%d.name", i));
2073 i++) {
2074 struct government *gov = government_by_rule_name(name);
2075
2076 if (gov != NULL) {
2077 gov->changed_to_times = secfile_lookup_int_default(loading->file, 0,
2078 "ruledata.government%d.changes", i);
2079 }
2080 }
2081}
2082
2083/************************************************************************/
2086 static void sg_load_game(struct loaddata *loading)
2087{
2088 const char *str;
2089 int i;
2090
2091 /* Check status and return if not OK (sg_success FALSE). */
2092 sg_check_ret();
2093
2094 /* Load server state. */
2095 str = secfile_lookup_str_default(loading->file, "S_S_INITIAL",
2096 "game.server_state");
2097 loading->server_state = server_states_by_name(str, strcmp);
2098 if (!server_states_is_valid(loading->server_state)) {
2099 /* Don't take any risk! */
2100 loading->server_state = S_S_INITIAL;
2101 }
2102
2103 game.server.additional_phase_seconds
2104 = secfile_lookup_int_default(loading->file, 0, "game.phase_seconds");
2105
2106 str = secfile_lookup_str_default(loading->file,
2107 default_meta_patches_string(),
2108 "game.meta_patches");
2109 set_meta_patches_string(str);
2110
2111 if (0 == strcmp(DEFAULT_META_SERVER_ADDR, srvarg.metaserver_addr)) {
2112 /* Do not overwrite this if the user requested a specific metaserver
2113 * from the command line (option --Metaserver). */
2114 sz_strlcpy(srvarg.metaserver_addr,
2115 secfile_lookup_str_default(loading->file,
2116 DEFAULT_META_SERVER_ADDR,
2117 "game.meta_server"));
2118 }
2119
2120 if ('\0' == srvarg.serverid[0]) {
2121 /* Do not overwrite this if the user requested a specific metaserver
2122 * from the command line (option --serverid). */
2123 sz_strlcpy(srvarg.serverid,
2124 secfile_lookup_str_default(loading->file, "",
2125 "game.serverid"));
2126 }
2127 sz_strlcpy(server.game_identifier,
2128 secfile_lookup_str_default(loading->file, "", "game.id"));
2129 /* We are not checking game_identifier legality just yet.
2130 * That's done when we are sure that rand seed has been initialized,
2131 * so that we can generate new game_identifier, if needed.
2132 * See sq_load_sanitycheck(). */
2133
2134 str = secfile_lookup_str_default(loading->file, NULL,
2135 "game.phase_mode");
2136 if (str != NULL) {
2137 game.info.phase_mode = phase_mode_type_by_name(str, fc_strcasecmp);
2138 if (!phase_mode_type_is_valid(game.info.phase_mode)) {
2139 log_error("Illegal phase mode \"%s\"", str);
2140 game.info.phase_mode = GAME_DEFAULT_PHASE_MODE;
2141 }
2142 } else {
2143 log_error("Phase mode missing");
2144 }
2145
2146 str = secfile_lookup_str_default(loading->file, NULL,
2147 "game.phase_mode_stored");
2148 if (str != NULL) {
2149 game.server.phase_mode_stored = phase_mode_type_by_name(str, fc_strcasecmp);
2150 if (!phase_mode_type_is_valid(game.server.phase_mode_stored)) {
2151 log_error("Illegal stored phase mode \"%s\"", str);
2152 game.server.phase_mode_stored = GAME_DEFAULT_PHASE_MODE;
2153 }
2154 } else {
2155 log_error("Stored phase mode missing");
2156 }
2157 game.info.phase
2158 = secfile_lookup_int_default(loading->file, 0,
2159 "game.phase");
2160 game.server.scoreturn
2161 = secfile_lookup_int_default(loading->file,
2162 game.info.turn + GAME_DEFAULT_SCORETURN,
2163 "game.scoreturn");
2164
2165 game.server.timeoutint
2166 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINT,
2167 "game.timeoutint");
2168 game.server.timeoutintinc
2169 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINTINC,
2170 "game.timeoutintinc");
2171 game.server.timeoutinc
2172 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINC,
2173 "game.timeoutinc");
2174 game.server.timeoutincmult
2175 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTINCMULT,
2176 "game.timeoutincmult");
2177 game.server.timeoutcounter
2178 = secfile_lookup_int_default(loading->file, GAME_DEFAULT_TIMEOUTCOUNTER,
2179 "game.timeoutcounter");
2180
2181 game.info.turn
2182 = secfile_lookup_int_default(loading->file, 0, "game.turn");
2183 sg_failure_ret(secfile_lookup_int(loading->file, &game.info.year,
2184 "game.year"), "%s", secfile_error());
2185 game.info.year_0_hack
2186 = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
2187
2188 game.info.globalwarming
2189 = secfile_lookup_int_default(loading->file, 0, "game.globalwarming");
2190 game.info.heating
2191 = secfile_lookup_int_default(loading->file, 0, "game.heating");
2192 game.info.warminglevel
2193 = secfile_lookup_int_default(loading->file, 0, "game.warminglevel");
2194
2195 game.info.nuclearwinter
2196 = secfile_lookup_int_default(loading->file, 0, "game.nuclearwinter");
2197 game.info.cooling
2198 = secfile_lookup_int_default(loading->file, 0, "game.cooling");
2199 game.info.coolinglevel
2200 = secfile_lookup_int_default(loading->file, 0, "game.coolinglevel");
2201
2202 /* Savegame may store random_seed for documentation purposes only,
2203 * we don't need it. Just silence "unused entry" warning. */
2204 (void) secfile_entry_lookup(loading->file, "game.random_seed");
2205
2206 /* Global advances. */
2207 str = secfile_lookup_str_default(loading->file, NULL,
2208 "game.global_advances");
2209 if (str != NULL) {
2210 sg_failure_ret(strlen(str) == loading->technology.size,
2211 "Invalid length of 'game.global_advances' ("
2212 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
2213 strlen(str), loading->technology.size);
2214 for (i = 0; i < loading->technology.size; i++) {
2215 sg_failure_ret(str[i] == '1' || str[i] == '0',
2216 "Undefined value '%c' within 'game.global_advances'.",
2217 str[i]);
2218 if (str[i] == '1') {
2219 struct advance *padvance =
2220 advance_by_rule_name(loading->technology.order[i]);
2221
2222 if (padvance != NULL) {
2223 game.info.global_advances[advance_number(padvance)] = TRUE;
2224 }
2225 }
2226 }
2227 }
2228
2229 game.info.is_new_game
2230 = !secfile_lookup_bool_default(loading->file, TRUE, "game.save_players");
2231
2232 game.server.turn_change_time
2233 = secfile_lookup_int_default(loading->file, 0, "game.last_turn_change_time") / 100;
2234}
2235
2236/************************************************************************/
2239 static void sg_save_ruledata(struct savedata *saving)
2240{
2241 int set_count = 0;
2242
2243 governments_iterate(pgov) {
2244 char path[256];
2245
2246 fc_snprintf(path, sizeof(path),
2247 "ruledata.government%d", set_count++);
2248
2249 secfile_insert_str(saving->file, government_rule_name(pgov),
2250 "%s.name", path);
2251 secfile_insert_int(saving->file, pgov->changed_to_times,
2252 "%s.changes", path);
2253 } governments_iterate_end;
2254}
2255
2256/************************************************************************/
2259 static void sg_save_game(struct savedata *saving)
2260{
2261 enum server_states srv_state;
2262 char global_advances[game.control.num_tech_types + 1];
2263 int i;
2264
2265 /* Check status and return if not OK (sg_success FALSE). */
2266 sg_check_ret();
2267
2268 /* Game state: once the game is no longer a new game (ie, has been
2269 * started the first time), it should always be considered a running
2270 * game for savegame purposes. */
2271 if (saving->scenario && !game.scenario.players) {
2272 srv_state = S_S_INITIAL;
2273 } else {
2274 srv_state = game.info.is_new_game ? server_state() : S_S_RUNNING;
2275 }
2276 secfile_insert_str(saving->file, server_states_name(srv_state),
2277 "game.server_state");
2278
2279 if (game.server.phase_timer != NULL) {
2280 secfile_insert_int(saving->file,
2281 timer_read_seconds(game.server.phase_timer)
2282 + game.server.additional_phase_seconds,
2283 "game.phase_seconds");
2284 }
2285
2286 secfile_insert_str(saving->file, get_meta_patches_string(),
2287 "game.meta_patches");
2288 secfile_insert_str(saving->file, meta_addr_port(), "game.meta_server");
2289
2290 secfile_insert_str(saving->file, server.game_identifier, "game.id");
2291 secfile_insert_str(saving->file, srvarg.serverid, "game.serverid");
2292
2293 secfile_insert_str(saving->file,
2294 phase_mode_type_name(game.info.phase_mode),
2295 "game.phase_mode");
2296 secfile_insert_str(saving->file,
2297 phase_mode_type_name(game.server.phase_mode_stored),
2298 "game.phase_mode_stored");
2299 secfile_insert_int(saving->file, game.info.phase,
2300 "game.phase");
2301 secfile_insert_int(saving->file, game.server.scoreturn,
2302 "game.scoreturn");
2303
2304 secfile_insert_int(saving->file, game.server.timeoutint,
2305 "game.timeoutint");
2306 secfile_insert_int(saving->file, game.server.timeoutintinc,
2307 "game.timeoutintinc");
2308 secfile_insert_int(saving->file, game.server.timeoutinc,
2309 "game.timeoutinc");
2310 secfile_insert_int(saving->file, game.server.timeoutincmult,
2311 "game.timeoutincmult");
2312 secfile_insert_int(saving->file, game.server.timeoutcounter,
2313 "game.timeoutcounter");
2314
2315 secfile_insert_int(saving->file, game.info.turn, "game.turn");
2316 secfile_insert_int(saving->file, game.info.year, "game.year");
2317 secfile_insert_bool(saving->file, game.info.year_0_hack,
2318 "game.year_0_hack");
2319
2320 secfile_insert_int(saving->file, game.info.globalwarming,
2321 "game.globalwarming");
2322 secfile_insert_int(saving->file, game.info.heating,
2323 "game.heating");
2324 secfile_insert_int(saving->file, game.info.warminglevel,
2325 "game.warminglevel");
2326
2327 secfile_insert_int(saving->file, game.info.nuclearwinter,
2328 "game.nuclearwinter");
2329 secfile_insert_int(saving->file, game.info.cooling,
2330 "game.cooling");
2331 secfile_insert_int(saving->file, game.info.coolinglevel,
2332 "game.coolinglevel");
2333 /* For debugging purposes only.
2334 * Do not save it if it's 0 (not known);
2335 * this confuses people reading this 'document' less than
2336 * saving 0. */
2337 if (game.server.seed != 0) {
2338 secfile_insert_int(saving->file, game.server.seed,
2339 "game.random_seed");
2340 }
2341
2342 /* Global advances. */
2343 for (i = 0; i < game.control.num_tech_types; i++) {
2344 global_advances[i] = game.info.global_advances[i] ? '1' : '0';
2345 }
2346 global_advances[i] = '\0';
2347 secfile_insert_str(saving->file, global_advances, "game.global_advances");
2348
2349 if (!game_was_started()) {
2350 saving->save_players = FALSE;
2351 } else {
2352 if (saving->scenario) {
2353 saving->save_players = game.scenario.players;
2354 } else {
2355 saving->save_players = TRUE;
2356 }
2357#ifndef SAVE_DUMMY_TURN_CHANGE_TIME
2358 secfile_insert_int(saving->file, game.server.turn_change_time * 100,
2359 "game.last_turn_change_time");
2360#else /* SAVE_DUMMY_TURN_CHANGE_TIME */
2361 secfile_insert_int(saving->file, game.info.turn * 10,
2362 "game.last_turn_change_time");
2363#endif /* SAVE_DUMMY_TURN_CHANGE_TIME */
2364 }
2365 secfile_insert_bool(saving->file, saving->save_players,
2366 "game.save_players");
2367
2368 if (srv_state != S_S_INITIAL) {
2369 const char *ainames[ai_type_get_count()];
2370
2371 i = 0;
2372 ai_type_iterate(ait) {
2373 ainames[i] = ait->name;
2374 i++;
2375 } ai_type_iterate_end;
2376
2377 secfile_insert_str_vec(saving->file, ainames, i,
2378 "game.ai_types");
2379 }
2380}
2381
2382/* =======================================================================
2383 * Load / save random status.
2384 * ======================================================================= */
2385
2386/************************************************************************/
2389 static void sg_load_random(struct loaddata *loading)
2390{
2391 /* Check status and return if not OK (sg_success FALSE). */
2392 sg_check_ret();
2393
2394 if (secfile_lookup_bool_default(loading->file, FALSE, "random.saved")) {
2395 const char *str;
2396 int i;
2397
2398 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.j,
2399 "random.index_J"), "%s", secfile_error());
2400 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.k,
2401 "random.index_K"), "%s", secfile_error());
2402 sg_failure_ret(secfile_lookup_int(loading->file, &loading->rstate.x,
2403 "random.index_X"), "%s", secfile_error());
2404
2405 for (i = 0; i < 8; i++) {
2406 str = secfile_lookup_str(loading->file, "random.table%d",i);
2407 sg_failure_ret(NULL != str, "%s", secfile_error());
2408 sscanf(str, "%8x %8x %8x %8x %8x %8x %8x", &loading->rstate.v[7*i],
2409 &loading->rstate.v[7*i+1], &loading->rstate.v[7*i+2],
2410 &loading->rstate.v[7*i+3], &loading->rstate.v[7*i+4],
2411 &loading->rstate.v[7*i+5], &loading->rstate.v[7*i+6]);
2412 }
2413 loading->rstate.is_init = TRUE;
2414 fc_rand_set_state(loading->rstate);
2415 } else {
2416 /* No random values - mark the setting. */
2417 (void) secfile_entry_by_path(loading->file, "random.saved");
2418
2419 /* We're loading a game without a seed (which is okay, if it's a scenario).
2420 * We need to generate the game seed now because it will be needed later
2421 * during the load. */
2422 init_game_seed();
2423 loading->rstate = fc_rand_state();
2424 }
2425}
2426
2427/************************************************************************/
2430 static void sg_save_random(struct savedata *saving)
2431{
2432 /* Check status and return if not OK (sg_success FALSE). */
2433 sg_check_ret();
2434
2435 if (fc_rand_is_init() && (!saving->scenario || game.scenario.save_random)) {
2436 int i;
2437 RANDOM_STATE rstate = fc_rand_state();
2438
2439 secfile_insert_bool(saving->file, TRUE, "random.saved");
2440 fc_assert(rstate.is_init);
2441
2442 secfile_insert_int(saving->file, rstate.j, "random.index_J");
2443 secfile_insert_int(saving->file, rstate.k, "random.index_K");
2444 secfile_insert_int(saving->file, rstate.x, "random.index_X");
2445
2446 for (i = 0; i < 8; i++) {
2447 char vec[100];
2448
2449 fc_snprintf(vec, sizeof(vec),
2450 "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7 * i],
2451 rstate.v[7 * i + 1], rstate.v[7 * i + 2],
2452 rstate.v[7 * i + 3], rstate.v[7 * i + 4],
2453 rstate.v[7 * i + 5], rstate.v[7 * i + 6]);
2454 secfile_insert_str(saving->file, vec, "random.table%d", i);
2455 }
2456 } else {
2457 secfile_insert_bool(saving->file, FALSE, "random.saved");
2458 }
2459}
2460
2461/* =======================================================================
2462 * Load / save lua script data.
2463 * ======================================================================= */
2464
2465/************************************************************************/
2468 static void sg_load_script(struct loaddata *loading)
2469{
2470 /* Check status and return if not OK (sg_success FALSE). */
2471 sg_check_ret();
2472
2473 script_server_state_load(loading->file);
2474}
2475
2476/************************************************************************/
2479 static void sg_save_script(struct savedata *saving)
2480{
2481 /* Check status and return if not OK (sg_success FALSE). */
2482 sg_check_ret();
2483
2484 script_server_state_save(saving->file);
2485}
2486
2487/* =======================================================================
2488 * Load / save scenario data.
2489 * ======================================================================= */
2490
2491/************************************************************************/
2494 static void sg_load_scenario(struct loaddata *loading)
2495{
2496 const char *buf;
2497 int game_version;
2498
2499 /* Check status and return if not OK (sg_success FALSE). */
2500 sg_check_ret();
2501
2502 /* Load version. */
2503 game_version
2504 = secfile_lookup_int_default(loading->file, 0, "scenario.game_version");
2505 /* We require at least version 2.90.99 - and at that time we saved version
2506 * numbers as 10000*MAJOR+100*MINOR+PATCH */
2507 sg_failure_ret(29099 <= game_version, "Saved game is too old, at least "
2508 "version 2.90.99 required.");
2509
2510 loading->full_version = game_version;
2511
2512 game.scenario.datafile[0] = '\0';
2513
2514 sg_failure_ret(secfile_lookup_bool(loading->file, &game.scenario.is_scenario,
2515 "scenario.is_scenario"), "%s", secfile_error());
2516 if (!game.scenario.is_scenario) {
2517 return;
2518 }
2519
2520 buf = secfile_lookup_str_default(loading->file, "", "scenario.name");
2521 if (buf[0] != '\0') {
2522 sz_strlcpy(game.scenario.name, buf);
2523 }
2524
2525 buf = secfile_lookup_str_default(loading->file, "",
2526 "scenario.authors");
2527 if (buf[0] != '\0') {
2528 sz_strlcpy(game.scenario.authors, buf);
2529 } else {
2530 game.scenario.authors[0] = '\0';
2531 }
2532
2533 buf = secfile_lookup_str_default(loading->file, "",
2534 "scenario.description");
2535 if (buf[0] != '\0') {
2536 sz_strlcpy(game.scenario_desc.description, buf);
2537 } else {
2538 game.scenario_desc.description[0] = '\0';
2539 }
2540 game.scenario.save_random
2541 = secfile_lookup_bool_default(loading->file, FALSE, "scenario.save_random");
2542 game.scenario.players
2543 = secfile_lookup_bool_default(loading->file, TRUE, "scenario.players");
2544 game.scenario.startpos_nations
2545 = secfile_lookup_bool_default(loading->file, FALSE,
2546 "scenario.startpos_nations");
2547 game.scenario.prevent_new_cities
2548 = secfile_lookup_bool_default(loading->file, FALSE,
2549 "scenario.prevent_new_cities");
2550 game.scenario.lake_flooding
2551 = secfile_lookup_bool_default(loading->file, TRUE,
2552 "scenario.lake_flooding");
2553 game.scenario.handmade
2554 = secfile_lookup_bool_default(loading->file, FALSE,
2555 "scenario.handmade");
2556 game.scenario.allow_ai_type_fallback
2557 = secfile_lookup_bool_default(loading->file, FALSE,
2558 "scenario.allow_ai_type_fallback");
2559
2560 game.scenario.ruleset_locked
2561 = secfile_lookup_bool_default(loading->file, TRUE,
2562 "scenario.ruleset_locked");
2563
2564 buf = secfile_lookup_str_default(loading->file, "",
2565 "scenario.datafile");
2566 if (buf[0] != '\0') {
2567 sz_strlcpy(game.scenario.datafile, buf);
2568 }
2569
2570 sg_failure_ret(loading->server_state == S_S_INITIAL
2571 || (loading->server_state == S_S_RUNNING
2572 && game.scenario.players),
2573 "Invalid scenario definition (server state '%s' and "
2574 "players are %s).",
2575 server_states_name(loading->server_state),
2576 game.scenario.players ? "saved" : "not saved");
2577}
2578
2579/************************************************************************/
2582 static void sg_save_scenario(struct savedata *saving)
2583{
2584 struct entry *mod_entry;
2585 int game_version;
2586
2587 /* Check status and return if not OK (sg_success FALSE). */
2588 sg_check_ret();
2589
2590 game_version = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000 + PATCH_VERSION * 100;
2591#ifdef EMERGENCY_VERSION
2592 game_version += EMERGENCY_VERSION;
2593#endif /* EMERGENCY_VERSION */
2594 secfile_insert_int(saving->file, game_version, "scenario.game_version");
2595
2596 if (!saving->scenario || !game.scenario.is_scenario) {
2597 secfile_insert_bool(saving->file, FALSE, "scenario.is_scenario");
2598 return;
2599 }
2600
2601 secfile_insert_bool(saving->file, TRUE, "scenario.is_scenario");
2602
2603 /* Name is mandatory to the level that is saved even if empty. */
2604 mod_entry = secfile_insert_str(saving->file, game.scenario.name, "scenario.name");
2605 entry_str_set_gt_marking(mod_entry, TRUE);
2606
2607 /* Authors list is saved only if it exist */
2608 if (game.scenario.authors[0] != '\0') {
2609 mod_entry = secfile_insert_str(saving->file, game.scenario.authors,
2610 "scenario.authors");
2611 entry_str_set_gt_marking(mod_entry, TRUE);
2612 }
2613
2614 /* Description is saved only if it exist */
2615 if (game.scenario_desc.description[0] != '\0') {
2616 mod_entry = secfile_insert_str(saving->file, game.scenario_desc.description,
2617 "scenario.description");
2618 entry_str_set_gt_marking(mod_entry, TRUE);
2619 }
2620
2621 secfile_insert_bool(saving->file, game.scenario.save_random, "scenario.save_random");
2622 secfile_insert_bool(saving->file, game.scenario.players, "scenario.players");
2623 secfile_insert_bool(saving->file, game.scenario.startpos_nations,
2624 "scenario.startpos_nations");
2625 if (game.scenario.prevent_new_cities) {
2626 secfile_insert_bool(saving->file, game.scenario.prevent_new_cities,
2627 "scenario.prevent_new_cities");
2628 }
2629 secfile_insert_bool(saving->file, game.scenario.lake_flooding,
2630 "scenario.lake_flooding");
2631 if (game.scenario.handmade) {
2632 secfile_insert_bool(saving->file, game.scenario.handmade,
2633 "scenario.handmade");
2634 }
2635 if (game.scenario.allow_ai_type_fallback) {
2636 secfile_insert_bool(saving->file, game.scenario.allow_ai_type_fallback,
2637 "scenario.allow_ai_type_fallback");
2638 }
2639
2640 if (game.scenario.datafile[0] != '\0') {
2641 secfile_insert_str(saving->file, game.scenario.datafile,
2642 "scenario.datafile");
2643 }
2644 secfile_insert_bool(saving->file, game.scenario.ruleset_locked,
2645 "scenario.ruleset_locked");
2646 if (!game.scenario.ruleset_locked && game.scenario.req_caps[0] != '\0') {
2647 secfile_insert_str(saving->file, game.scenario.req_caps,
2648 "scenario.ruleset_caps");
2649 }
2650}
2651
2652/* =======================================================================
2653 * Load / save game settings.
2654 * ======================================================================= */
2655
2656/************************************************************************/
2659 static void sg_load_settings(struct loaddata *loading)
2660{
2661 /* Check status and return if not OK (sg_success FALSE). */
2662 sg_check_ret();
2663
2664 settings_game_load(loading->file, "settings");
2665
2666 /* Save current status of fogofwar. */
2667 game.server.fogofwar_old = game.info.fogofwar;
2668
2669 /* Add all compatibility settings here. */
2670}
2671
2672/************************************************************************/
2675 static void sg_save_settings(struct savedata *saving)
2676{
2677 enum map_generator real_generator = wld.map.server.generator;
2678
2679 /* Check status and return if not OK (sg_success FALSE). */
2680 sg_check_ret();
2681
2682 if (saving->scenario) {
2683 wld.map.server.generator = MAPGEN_SCENARIO; /* We want a scenario. */
2684 }
2685
2686 settings_game_save(saving->file, "settings");
2687 /* Restore real map generator. */
2688 wld.map.server.generator = real_generator;
2689
2690 /* Add all compatibility settings here. */
2691}
2692
2693
2694/************************************************************************/
2697 static void sg_load_counters(struct loaddata *loading)
2698{
2699 struct city *pcity;
2700 int i, j;
2701 size_t length, length2;
2702 int *city_count;
2703 length = secfile_lookup_int_default(loading->file, 0,
2704 "savefile.city_counters_order_size");
2705
2706 if (0==length) {
2707
2708 return;
2709 }
2710
2711 loading->counter.order = secfile_lookup_str_vec(loading->file, &loading->counter.size, "savefile.city_counters_order_vector");
2712
2713 sg_failure_ret(loading->counter.order != 0,
2714 "Failed to load counter's ruleset order: %s",
2715 secfile_error());
2716 sg_failure_ret(loading->counter.size = length,
2717 "Counter vector in savegame have bad size: %s",
2718 secfile_error());
2719
2720 int corder[length];
2721
2722 for (i = 0; i < length; i++) {
2723
2724 struct counter *ctg = counter_by_rule_name(loading->counter.order[i]);
2725 corder[i] = counter_index(ctg);
2726 }
2727
2728 i = 0;
2729 while (NULL != (city_count =
2730 secfile_lookup_int_vec(loading->file, &length2,
2731 "counters.c%d", i))) {
2732
2733 sg_failure_ret((length2 -1 == (size_t) length), ( "Bad city counters vector size. Should be " SIZE_T_PRINTF ". Is " SIZE_T_PRINTF "." ), length, length2 - 1);
2734
2735 pcity = game_city_by_number(city_count[0]);
2736
2737 sg_failure_ret(NULL != pcity, "City with id %d not found. Is savegame malformed? Abort loading.", city_count[0]);
2738
2739 for (j = 0; j < length; j++) {
2740
2741 pcity->counter_values[corder[j]] = city_count[j+1];
2742 }
2743 i++;
2744 }
2745}
2746
2747/************************************************************************/
2750 static void sg_save_counters(struct savedata *saving)
2751{
2752 /* Check status and return if not OK (sg_success FALSE). */
2753 sg_check_ret();
2754
2755 const char **countnames;;
2756 int *countvalues;
2757 int i, j, count;
2758
2759 count = counters_get_city_counters_count();
2760
2761 secfile_insert_int(saving->file, count,
2762 "savefile.city_counters_order_size");
2763
2764 if (0 == count) {
2765
2766 return;
2767 }
2768
2769 countnames = fc_calloc(count, sizeof(*countnames));
2770 for (j = 0; j < count; j++) {
2771 countnames[j] = counter_rule_name(counter_by_index(j, CTGT_CITY));
2772 }
2773
2774 secfile_insert_str_vec(saving->file, countnames, count,
2775 "savefile.city_counters_order_vector");
2776
2777 free(countnames);
2778
2779 // Saving city's counters
2780
2781 j = 0;
2782 countvalues = fc_calloc(count+1, sizeof(*countvalues));
2783
2784 players_iterate(_pplayer) {
2785
2786 city_list_iterate(_pplayer->cities, pcity) {
2787
2788 countvalues[0] = pcity->id;
2789 for (i = 0; i < count; ++i) {
2790
2791 countvalues[i+1] = pcity->counter_values[i];
2792 }
2793
2794 secfile_insert_int_vec(saving->file, countvalues, count + 1, "counters.c%d", j);
2795 ++j;
2796 } city_list_iterate_end;
2797 } players_iterate_end;
2798
2799 free(countvalues);
2800}
2801
2802/* =======================================================================
2803 * Load / save the main map.
2804 * ======================================================================= */
2805
2806/************************************************************************/
2809 static void sg_load_map(struct loaddata *loading)
2810{
2811 /* Check status and return if not OK (sg_success FALSE). */
2812 sg_check_ret();
2813
2814 /* This defaults to TRUE even if map has not been generated.
2815 * We rely on that
2816 * 1) scenario maps have it explicitly right.
2817 * 2) when map is actually generated, it re-initialize this to FALSE. */
2818 wld.map.server.have_huts
2819 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_huts");
2820 game.scenario.have_resources
2821 = secfile_lookup_bool_default(loading->file, TRUE, "map.have_resources");
2822
2823 wld.map.server.have_resources = game.scenario.have_resources;
2824
2825 /* Savegame may store random_seed for documentation purposes only,
2826 * we don't need it. Just silence "unused entry" warning. */
2827 (void) secfile_entry_lookup(loading->file, "map.random_seed");
2828
2829 if (S_S_INITIAL == loading->server_state
2830 && MAPGEN_SCENARIO == wld.map.server.generator) {
2831 /* Generator MAPGEN_SCENARIO is used;
2832 * this map was done with the map editor. */
2833
2834 /* Load tiles. */
2835 sg_load_map_tiles(loading);
2836 sg_load_map_startpos(loading);
2837 sg_load_map_tiles_extras(loading);
2838
2839 /* Nothing more needed for a scenario. */
2840 return;
2841 }
2842
2843 if (S_S_INITIAL == loading->server_state) {
2844 /* Nothing more to do if it is not a scenario but in initial state. */
2845 return;
2846 }
2847
2848 sg_load_map_tiles(loading);
2849 sg_load_map_startpos(loading);
2850 sg_load_map_tiles_extras(loading);
2851 sg_load_map_known(loading);
2852 sg_load_map_owner(loading);
2853 sg_load_map_worked(loading);
2854}
2855
2856/************************************************************************/
2859 static void sg_save_map(struct savedata *saving)
2860{
2861 /* Check status and return if not OK (sg_success FALSE). */
2862 sg_check_ret();
2863
2864 if (map_is_empty()) {
2865 /* No map. */
2866 return;
2867 }
2868
2869 if (saving->scenario) {
2870 secfile_insert_bool(saving->file, wld.map.server.have_huts,
2871 "map.have_huts");
2872 secfile_insert_bool(saving->file, game.scenario.have_resources,
2873 "map.have_resources");
2874 } else {
2875 secfile_insert_bool(saving->file, TRUE, "map.have_huts");
2876 secfile_insert_bool(saving->file, TRUE, "map.have_resources");
2877 }
2878
2879 /* For debugging purposes only.
2880 * Do not save it if it's 0 (not known);
2881 * this confuses people reading this 'document' less than
2882 * saving 0. */
2883 if (wld.map.server.seed) {
2884 secfile_insert_int(saving->file, wld.map.server.seed,
2885 "map.random_seed");
2886 }
2887
2888 sg_save_map_tiles(saving);
2889 sg_save_map_startpos(saving);
2890 sg_save_map_tiles_extras(saving);
2891 sg_save_map_owner(saving);
2892 sg_save_map_worked(saving);
2893 sg_save_map_known(saving);
2894}
2895
2896/************************************************************************/
2899 static void sg_load_map_tiles(struct loaddata *loading)
2900{
2901 /* Check status and return if not OK (sg_success FALSE). */
2902 sg_check_ret();
2903
2904 /* Initialize the map for the current topology. 'map.xsize' and
2905 * 'map.ysize' must be set. */
2906 map_init_topology();
2907
2908 /* Allocate map. */
2909 main_map_allocate();
2910
2911 /* get the terrain type */
2912 LOAD_MAP_CHAR(ch, ptile, ptile->terrain = char2terrain(ch), loading->file,
2913 "map.t%04d");
2914 assign_continent_numbers();
2915
2916 /* Check for special tile sprites. */
2917 whole_map_iterate(&(wld.map), ptile) {
2918 const char *spec_sprite;
2919 const char *label;
2920 int nat_x, nat_y;
2921
2922 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
2923 spec_sprite = secfile_lookup_str(loading->file, "map.spec_sprite_%d_%d",
2924 nat_x, nat_y);
2925 label = secfile_lookup_str_default(loading->file, NULL, "map.label_%d_%d",
2926 nat_x, nat_y);
2927 if (NULL != ptile->spec_sprite) {
2928 ptile->spec_sprite = fc_strdup(spec_sprite);
2929 }
2930 if (label != NULL) {
2931 tile_set_label(ptile, label);
2932 }
2933 } whole_map_iterate_end;
2934}
2935
2936/************************************************************************/
2939 static void sg_save_map_tiles(struct savedata *saving)
2940{
2941 /* Check status and return if not OK (sg_success FALSE). */
2942 sg_check_ret();
2943
2944 /* Save the terrain type. */
2945 SAVE_MAP_CHAR(ptile, terrain2char(ptile->terrain), saving->file,
2946 "map.t%04d");
2947
2948 /* Save special tile sprites. */
2949 whole_map_iterate(&(wld.map), ptile) {
2950 int nat_x, nat_y;
2951
2952 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
2953 if (ptile->spec_sprite) {
2954 secfile_insert_str(saving->file, ptile->spec_sprite,
2955 "map.spec_sprite_%d_%d", nat_x, nat_y);
2956 }
2957 if (ptile->label != NULL) {
2958 secfile_insert_str(saving->file, ptile->label,
2959 "map.label_%d_%d", nat_x, nat_y);
2960 }
2961 } whole_map_iterate_end;
2962}
2963
2964/************************************************************************/
2967 static void sg_load_map_tiles_extras(struct loaddata *loading)
2968{
2969 /* Check status and return if not OK (sg_success FALSE). */
2970 sg_check_ret();
2971
2972 /* Load extras. */
2973 halfbyte_iterate_extras(j, loading->extra.size) {
2974 LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch,
2975 loading->extra.order + 4 * j),
2976 loading->file, "map.e%02d_%04d", j);
2977 } halfbyte_iterate_extras_end;
2978
2979 if (S_S_INITIAL != loading->server_state
2980 || MAPGEN_SCENARIO != wld.map.server.generator
2981 || game.scenario.have_resources) {
2982 whole_map_iterate(&(wld.map), ptile) {
2983 extra_type_by_cause_iterate(EC_RESOURCE, pres) {
2984 if (tile_has_extra(ptile, pres)) {
2985 tile_set_resource(ptile, pres);
2986
2987 if (!terrain_has_resource(ptile->terrain, ptile->resource)) {
2988 BV_CLR(ptile->extras, extra_index(pres));
2989 }
2990 }
2991 } extra_type_by_cause_iterate_end;
2992 } whole_map_iterate_end;
2993 }
2994}
2995
2996/************************************************************************/
2999 static void sg_save_map_tiles_extras(struct savedata *saving)
3000{
3001 /* Check status and return if not OK (sg_success FALSE). */
3002 sg_check_ret();
3003
3004 /* Save extras. */
3005 halfbyte_iterate_extras(j, game.control.num_extra_types) {
3006 int mod[4];
3007 int l;
3008
3009 for (l = 0; l < 4; l++) {
3010 if (4 * j + 1 > game.control.num_extra_types) {
3011 mod[l] = -1;
3012 } else {
3013 mod[l] = 4 * j + l;
3014 }
3015 }
3016 SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod),
3017 saving->file, "map.e%02d_%04d", j);
3018 } halfbyte_iterate_extras_end;
3019}
3020
3021/************************************************************************/
3025 static void sg_load_map_startpos(struct loaddata *loading)
3026{
3027 struct nation_type *pnation;
3028 struct startpos *psp;
3029 struct tile *ptile;
3030 const char SEPARATOR = '#';
3031 const char *nation_names;
3032 int nat_x, nat_y;
3033 bool exclude;
3034 int i, startpos_count;
3035
3036 /* Check status and return if not OK (sg_success FALSE). */
3037 sg_check_ret();
3038
3039 startpos_count
3040 = secfile_lookup_int_default(loading->file, 0, "map.startpos_count");
3041
3042 if (0 == startpos_count) {
3043 /* Nothing to do. */
3044 return;
3045 }
3046
3047 for (i = 0; i < startpos_count; i++) {
3048 if (!secfile_lookup_int(loading->file, &nat_x, "map.startpos%d.x", i)
3049 || !secfile_lookup_int(loading->file, &nat_y,
3050 "map.startpos%d.y", i)) {
3051 log_sg("Warning: Undefined coordinates for startpos %d", i);
3052 continue;
3053 }
3054
3055 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
3056 if (NULL == ptile) {
3057 log_error("Start position native coordinates (%d, %d) do not exist "
3058 "in this map. Skipping...", nat_x, nat_y);
3059 continue;
3060 }
3061
3062 exclude = secfile_lookup_bool_default(loading->file, FALSE,
3063 "map.startpos%d.exclude", i);
3064
3065 psp = map_startpos_new(ptile);
3066
3067 nation_names = secfile_lookup_str(loading->file,
3068 "map.startpos%d.nations", i);
3069 if (NULL != nation_names && '\0' != nation_names[0]) {
3070 const size_t size = strlen(nation_names) + 1;
3071 char buf[size], *start, *end;
3072
3073 memcpy(buf, nation_names, size);
3074 for (start = buf - 1; NULL != start; start = end) {
3075 start++;
3076 if ((end = strchr(start, SEPARATOR))) {
3077 *end = '\0';
3078 }
3079
3080 pnation = nation_by_rule_name(start);
3081 if (NO_NATION_SELECTED != pnation) {
3082 if (exclude) {
3083 startpos_disallow(psp, pnation);
3084 } else {
3085 startpos_allow(psp, pnation);
3086 }
3087 } else {
3088 log_verbose("Missing nation \"%s\".", start);
3089 }
3090 }
3091 }
3092 }
3093
3094 if (0 < map_startpos_count()
3095 && loading->server_state == S_S_INITIAL
3096 && map_startpos_count() < game.server.max_players) {
3097 log_verbose("Number of starts (%d) are lower than rules.max_players "
3098 "(%d), lowering rules.max_players.",
3099 map_startpos_count(), game.server.max_players);
3100 game.server.max_players = map_startpos_count();
3101 }
3102
3103 /* Re-initialize nation availability in light of start positions.
3104 * This has to be after loading [scenario] and [map].startpos and
3105 * before we seek nations for players. */
3106 update_nations_with_startpos();
3107}
3108
3109/************************************************************************/
3112 static void sg_save_map_startpos(struct savedata *saving)
3113{
3114 struct tile *ptile;
3115 const char SEPARATOR = '#';
3116 int i = 0;
3117
3118 /* Check status and return if not OK (sg_success FALSE). */
3119 sg_check_ret();
3120
3121 if (!game.server.save_options.save_starts) {
3122 return;
3123 }
3124
3125 secfile_insert_int(saving->file, map_startpos_count(),
3126 "map.startpos_count");
3127
3128 map_startpos_iterate(psp) {
3129 int nat_x, nat_y;
3130
3131 ptile = startpos_tile(psp);
3132
3133 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
3134 secfile_insert_int(saving->file, nat_x, "map.startpos%d.x", i);
3135 secfile_insert_int(saving->file, nat_y, "map.startpos%d.y", i);
3136
3137 secfile_insert_bool(saving->file, startpos_is_excluding(psp),
3138 "map.startpos%d.exclude", i);
3139 if (startpos_allows_all(psp)) {
3140 secfile_insert_str(saving->file, "", "map.startpos%d.nations", i);
3141 } else {
3142 const struct nation_hash *nations = startpos_raw_nations(psp);
3143 char nation_names[MAX_LEN_NAME * nation_hash_size(nations)];
3144
3145 nation_names[0] = '\0';
3146 nation_hash_iterate(nations, pnation) {
3147 if ('\0' == nation_names[0]) {
3148 fc_strlcpy(nation_names, nation_rule_name(pnation),
3149 sizeof(nation_names));
3150 } else {
3151 cat_snprintf(nation_names, sizeof(nation_names),
3152 "%c%s", SEPARATOR, nation_rule_name(pnation));
3153 }
3154 } nation_hash_iterate_end;
3155 secfile_insert_str(saving->file, nation_names,
3156 "map.startpos%d.nations", i);
3157 }
3158 i++;
3159 } map_startpos_iterate_end;
3160
3161 fc_assert(map_startpos_count() == i);
3162}
3163
3164/************************************************************************/
3167 static void sg_load_map_owner(struct loaddata *loading)
3168{
3169 int x, y;
3170 struct tile *claimer = NULL;
3171 struct extra_type *placing = NULL;
3172
3173 /* Check status and return if not OK (sg_success FALSE). */
3174 sg_check_ret();
3175
3176 if (game.info.is_new_game) {
3177 /* No owner/source information for a new game / scenario. */
3178 return;
3179 }
3180
3181 /* Owner, ownership source, and infra turns are stored as plain numbers */
3182 for (y = 0; y < wld.map.ysize; y++) {
3183 const char *buffer1 = secfile_lookup_str(loading->file,
3184 "map.owner%04d", y);
3185 const char *buffer2 = secfile_lookup_str(loading->file,
3186 "map.source%04d", y);
3187 const char *buffer3 = secfile_lookup_str(loading->file,
3188 "map.eowner%04d", y);
3189 const char *buffer_placing = secfile_lookup_str_default(loading->file,
3190 NULL,
3191 "map.placing%04d", y);
3192 const char *buffer_turns = secfile_lookup_str_default(loading->file,
3193 NULL,
3194 "map.infra_turns%04d", y);
3195 const char *ptr1 = buffer1;
3196 const char *ptr2 = buffer2;
3197 const char *ptr3 = buffer3;
3198 const char *ptr_placing = buffer_placing;
3199 const char *ptr_turns = buffer_turns;
3200
3201 sg_failure_ret(buffer1 != NULL, "%s", secfile_error());
3202 sg_failure_ret(buffer2 != NULL, "%s", secfile_error());
3203 sg_failure_ret(buffer3 != NULL, "%s", secfile_error());
3204
3205 for (x = 0; x < wld.map.xsize; x++) {
3206 char token1[TOKEN_SIZE];
3207 char token2[TOKEN_SIZE];
3208 char token3[TOKEN_SIZE];
3209 char token_placing[TOKEN_SIZE];
3210 char token_turns[TOKEN_SIZE];
3211 struct player *owner = NULL;
3212 struct player *eowner = NULL;
3213 int turns;
3214 int number;
3215 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3216
3217 scanin(&ptr1, ",", token1, sizeof(token1));
3218 sg_failure_ret(token1[0] != '\0',
3219 "Map size not correct (map.owner%d).", y);
3220 if (strcmp(token1, "-") == 0) {
3221 owner = NULL;
3222 } else {
3223 sg_failure_ret(str_to_int(token1, &number),
3224 "Got map owner %s in (%d, %d).", token1, x, y);
3225 owner = player_by_number(number);
3226 }
3227
3228 scanin(&ptr2, ",", token2, sizeof(token2));
3229 sg_failure_ret(token2[0] != '\0',
3230 "Map size not correct (map.source%d).", y);
3231 if (strcmp(token2, "-") == 0) {
3232 claimer = NULL;
3233 } else {
3234 sg_failure_ret(str_to_int(token2, &number),
3235 "Got map source %s in (%d, %d).", token2, x, y);
3236 claimer = index_to_tile(&(wld.map), number);
3237 }
3238
3239 scanin(&ptr3, ",", token3, sizeof(token3));
3240 sg_failure_ret(token3[0] != '\0',
3241 "Map size not correct (map.eowner%d).", y);
3242 if (strcmp(token3, "-") == 0) {
3243 eowner = NULL;
3244 } else {
3245 sg_failure_ret(str_to_int(token3, &number),
3246 "Got base owner %s in (%d, %d).", token3, x, y);
3247 eowner = player_by_number(number);
3248 }
3249
3250 if (ptr_placing != NULL) {
3251 scanin(&ptr_placing, ",", token_placing, sizeof(token_placing));
3252 sg_failure_ret(token_placing[0] != '\0',
3253 "Map size not correct (map.placing%d).", y);
3254 if (strcmp(token_placing, "-") == 0) {
3255 placing = NULL;
3256 } else {
3257 sg_failure_ret(str_to_int(token_placing, &number),
3258 "Got placing extra %s in (%d, %d).", token_placing, x, y);
3259 placing = extra_by_number(number);
3260 }
3261 } else {
3262 placing = NULL;
3263 }
3264
3265 if (ptr_turns != NULL) {
3266 scanin(&ptr_turns, ",", token_turns, sizeof(token_turns));
3267 sg_failure_ret(token_turns[0] != '\0',
3268 "Map size not correct (map.infra_turns%d).", y);
3269 sg_failure_ret(str_to_int(token_turns, &number),
3270 "Got infra_turns %s in (%d, %d).", token_turns, x, y);
3271 turns = number;
3272 } else {
3273 turns = 1;
3274 }
3275
3276 map_claim_ownership(ptile, owner, claimer, FALSE);
3277 tile_claim_bases(ptile, eowner);
3278 ptile->placing = placing;
3279 ptile->infra_turns = turns;
3280 log_debug("extras_owner(%d, %d) = %s", TILE_XY(ptile), player_name(eowner));
3281 }
3282 }
3283}
3284
3285/************************************************************************/
3288 static void sg_save_map_owner(struct savedata *saving)
3289{
3290 int x, y;
3291
3292 /* Check status and return if not OK (sg_success FALSE). */
3293 sg_check_ret();
3294
3295 if (saving->scenario && !saving->save_players) {
3296 /* Nothing to do for a scenario without saved players. */
3297 return;
3298 }
3299
3300 /* Store owner and ownership source as plain numbers. */
3301 for (y = 0; y < wld.map.ysize; y++) {
3302 char line[wld.map.xsize * TOKEN_SIZE];
3303
3304 line[0] = '\0';
3305 for (x = 0; x < wld.map.xsize; x++) {
3306 char token[TOKEN_SIZE];
3307 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3308
3309 if (!saving->save_players || tile_owner(ptile) == NULL) {
3310 strcpy(token, "-");
3311 } else {
3312 fc_snprintf(token, sizeof(token), "%d",
3313 player_number(tile_owner(ptile)));
3314 }
3315 strcat(line, token);
3316 if (x + 1 < wld.map.xsize) {
3317 strcat(line, ",");
3318 }
3319 }
3320 secfile_insert_str(saving->file, line, "map.owner%04d", y);
3321 }
3322
3323 for (y = 0; y < wld.map.ysize; y++) {
3324 char line[wld.map.xsize * TOKEN_SIZE];
3325
3326 line[0] = '\0';
3327 for (x = 0; x < wld.map.xsize; x++) {
3328 char token[TOKEN_SIZE];
3329 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3330
3331 if (ptile->claimer == NULL) {
3332 strcpy(token, "-");
3333 } else {
3334 fc_snprintf(token, sizeof(token), "%d", tile_index(ptile->claimer));
3335 }
3336 strcat(line, token);
3337 if (x + 1 < wld.map.xsize) {
3338 strcat(line, ",");
3339 }
3340 }
3341 secfile_insert_str(saving->file, line, "map.source%04d", y);
3342 }
3343
3344 for (y = 0; y < wld.map.ysize; y++) {
3345 char line[wld.map.xsize * TOKEN_SIZE];
3346
3347 line[0] = '\0';
3348 for (x = 0; x < wld.map.xsize; x++) {
3349 char token[TOKEN_SIZE];
3350 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3351
3352 if (!saving->save_players || extra_owner(ptile) == NULL) {
3353 strcpy(token, "-");
3354 } else {
3355 fc_snprintf(token, sizeof(token), "%d",
3356 player_number(extra_owner(ptile)));
3357 }
3358 strcat(line, token);
3359 if (x + 1 < wld.map.xsize) {
3360 strcat(line, ",");
3361 }
3362 }
3363 secfile_insert_str(saving->file, line, "map.eowner%04d", y);
3364 }
3365
3366 for (y = 0; y < wld.map.ysize; y++) {
3367 char line[wld.map.xsize * TOKEN_SIZE];
3368
3369 line[0] = '\0';
3370 for (x = 0; x < wld.map.xsize; x++) {
3371 char token[TOKEN_SIZE];
3372 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3373
3374 if (ptile->placing == NULL) {
3375 strcpy(token, "-");
3376 } else {
3377 fc_snprintf(token, sizeof(token), "%d",
3378 extra_number(ptile->placing));
3379 }
3380 strcat(line, token);
3381 if (x + 1 < wld.map.xsize) {
3382 strcat(line, ",");
3383 }
3384 }
3385 secfile_insert_str(saving->file, line, "map.placing%04d", y);
3386 }
3387
3388 for (y = 0; y < wld.map.ysize; y++) {
3389 char line[wld.map.xsize * TOKEN_SIZE];
3390
3391 line[0] = '\0';
3392 for (x = 0; x < wld.map.xsize; x++) {
3393 char token[TOKEN_SIZE];
3394 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3395
3396 if (ptile->placing != NULL) {
3397 fc_snprintf(token, sizeof(token), "%d",
3398 ptile->infra_turns);
3399 } else {
3400 fc_snprintf(token, sizeof(token), "0");
3401 }
3402 strcat(line, token);
3403 if (x + 1 < wld.map.xsize) {
3404 strcat(line, ",");
3405 }
3406 }
3407 secfile_insert_str(saving->file, line, "map.infra_turns%04d", y);
3408 }
3409}
3410
3411/************************************************************************/
3414 static void sg_load_map_worked(struct loaddata *loading)
3415{
3416 int x, y;
3417
3418 /* Check status and return if not OK (sg_success FALSE). */
3419 sg_check_ret();
3420
3421 sg_failure_ret(loading->worked_tiles == NULL,
3422 "City worked map not loaded!");
3423
3424 loading->worked_tiles = fc_malloc(MAP_INDEX_SIZE *
3425 sizeof(*loading->worked_tiles));
3426
3427 for (y = 0; y < wld.map.ysize; y++) {
3428 const char *buffer = secfile_lookup_str(loading->file, "map.worked%04d",
3429 y);
3430 const char *ptr = buffer;
3431
3432 sg_failure_ret(NULL != buffer,
3433 "Savegame corrupt - map line %d not found.", y);
3434 for (x = 0; x < wld.map.xsize; x++) {
3435 char token[TOKEN_SIZE];
3436 int number;
3437 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3438
3439 scanin(&ptr, ",", token, sizeof(token));
3440 sg_failure_ret('\0' != token[0],
3441 "Savegame corrupt - map size not correct.");
3442 if (strcmp(token, "-") == 0) {
3443 number = -1;
3444 } else {
3445 sg_failure_ret(str_to_int(token, &number) && 0 < number,
3446 "Savegame corrupt - got tile worked by city "
3447 "id=%s in (%d, %d).", token, x, y);
3448 }
3449
3450 loading->worked_tiles[ptile->index] = number;
3451 }
3452 }
3453}
3454
3455/************************************************************************/
3458 static void sg_save_map_worked(struct savedata *saving)
3459{
3460 int x, y;
3461
3462 /* Check status and return if not OK (sg_success FALSE). */
3463 sg_check_ret();
3464
3465 if (saving->scenario && !saving->save_players) {
3466 /* Nothing to do for a scenario without saved players. */
3467 return;
3468 }
3469
3470 /* additionally save the tiles worked by the cities */
3471 for (y = 0; y < wld.map.ysize; y++) {
3472 char line[wld.map.xsize * TOKEN_SIZE];
3473
3474 line[0] = '\0';
3475 for (x = 0; x < wld.map.xsize; x++) {
3476 char token[TOKEN_SIZE];
3477 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
3478 struct city *pcity = tile_worked(ptile);
3479
3480 if (pcity == NULL) {
3481 strcpy(token, "-");
3482 } else {
3483 fc_snprintf(token, sizeof(token), "%d", pcity->id);
3484 }
3485 strcat(line, token);
3486 if (x < wld.map.xsize) {
3487 strcat(line, ",");
3488 }
3489 }
3490 secfile_insert_str(saving->file, line, "map.worked%04d", y);
3491 }
3492}
3493
3494/************************************************************************/
3497 static void sg_load_map_known(struct loaddata *loading)
3498{
3499 /* Check status and return if not OK (sg_success FALSE). */
3500 sg_check_ret();
3501
3502 players_iterate(pplayer) {
3503 /* Allocate player private map here; it is needed in different modules
3504 * besides this one ((i.e. sg_load_player_*()). */
3505 player_map_init(pplayer);
3506 } players_iterate_end;
3507
3508 if (secfile_lookup_bool_default(loading->file, TRUE,
3509 "game.save_known")) {
3510 int lines = player_slot_max_used_number()/32 + 1, j, p, l, i;
3511 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3512
3513 for (l = 0; l < lines; l++) {
3514 for (j = 0; j < 8; j++) {
3515 for (i = 0; i < 4; i++) {
3516 /* Only bother trying to load the map for this halfbyte if at least
3517 * one of the corresponding player slots is in use. */
3518 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3519 LOAD_MAP_CHAR(ch, ptile,
3520 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3521 |= ascii_hex2bin(ch, j),
3522 loading->file, "map.k%02d_%04d", l * 8 + j);
3523 break;
3524 }
3525 }
3526 }
3527 }
3528
3529 players_iterate(pplayer) {
3530 dbv_clr_all(&pplayer->tile_known);
3531 } players_iterate_end;
3532
3533 /* HACK: we read the known data from hex into 32-bit integers, and
3534 * now we convert it to the known tile data of each player. */
3535 whole_map_iterate(&(wld.map), ptile) {
3536 players_iterate(pplayer) {
3537 p = player_index(pplayer);
3538 l = player_index(pplayer) / 32;
3539
3540 if (known[l * MAP_INDEX_SIZE + tile_index(ptile)] & (1u << (p % 32))) {
3541 map_set_known(ptile, pplayer);
3542 }
3543 } players_iterate_end;
3544 } whole_map_iterate_end;
3545
3546 FC_FREE(known);
3547 }
3548}
3549
3550/************************************************************************/
3553 static void sg_save_map_known(struct savedata *saving)
3554{
3555 /* Check status and return if not OK (sg_success FALSE). */
3556 sg_check_ret();
3557
3558 if (!saving->save_players) {
3559 secfile_insert_bool(saving->file, FALSE, "game.save_known");
3560 return;
3561 } else {
3562 int lines = player_slot_max_used_number()/32 + 1;
3563
3564 secfile_insert_bool(saving->file, game.server.save_options.save_known,
3565 "game.save_known");
3566 if (game.server.save_options.save_known) {
3567 int j, p, l, i;
3568 unsigned int *known = fc_calloc(lines * MAP_INDEX_SIZE, sizeof(*known));
3569
3570 /* HACK: we convert the data into a 32-bit integer, and then save it as
3571 * hex. */
3572
3573 whole_map_iterate(&(wld.map), ptile) {
3574 players_iterate(pplayer) {
3575 if (map_is_known(ptile, pplayer)) {
3576 p = player_index(pplayer);
3577 l = p / 32;
3578 known[l * MAP_INDEX_SIZE + tile_index(ptile)]
3579 |= (1u << (p % 32)); /* "p % 32" = "p - l * 32" */
3580 }
3581 } players_iterate_end;
3582 } whole_map_iterate_end;
3583
3584 for (l = 0; l < lines; l++) {
3585 for (j = 0; j < 8; j++) {
3586 for (i = 0; i < 4; i++) {
3587 /* Only bother saving the map for this halfbyte if at least one
3588 * of the corresponding player slots is in use */
3589 if (player_slot_is_used(player_slot_by_number(l*32 + j*4 + i))) {
3590 /* put 4-bit segments of the 32-bit "known" field */
3591 SAVE_MAP_CHAR(ptile, bin2ascii_hex(known[l * MAP_INDEX_SIZE
3592 + tile_index(ptile)], j),
3593 saving->file, "map.k%02d_%04d", l * 8 + j);
3594 break;
3595 }
3596 }
3597 }
3598 }
3599
3600 FC_FREE(known);
3601 }
3602 }
3603}
3604
3605/* =======================================================================
3606 * Load / save player data.
3607 *
3608 * This is splitted into two parts as some data can only be loaded if the
3609 * number of players is known and the corresponding player slots are
3610 * defined.
3611 * ======================================================================= */
3612
3613/************************************************************************/
3616 static void sg_load_players_basic(struct loaddata *loading)
3617{
3618 int i, k, nplayers;
3619 const char *str;
3620 bool shuffle_loaded = TRUE;
3621
3622 /* Check status and return if not OK (sg_success FALSE). */
3623 sg_check_ret();
3624
3625 if (S_S_INITIAL == loading->server_state
3626 || game.info.is_new_game) {
3627 /* Nothing more to do. */
3628 return;
3629 }
3630
3631 /* Load destroyed wonders: */
3632 str = secfile_lookup_str(loading->file,
3633 "players.destroyed_wonders");
3634 sg_failure_ret(str != NULL, "%s", secfile_error());
3635 sg_failure_ret(strlen(str) == loading->improvement.size,
3636 "Invalid length for 'players.destroyed_wonders' ("
3637 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
3638 strlen(str), loading->improvement.size);
3639 for (k = 0; k < loading->improvement.size; k++) {
3640 sg_failure_ret(str[k] == '1' || str[k] == '0',
3641 "Undefined value '%c' within "
3642 "'players.destroyed_wonders'.", str[k]);
3643
3644 if (str[k] == '1') {
3645 struct impr_type *pimprove =
3646 improvement_by_rule_name(loading->improvement.order[k]);
3647 if (pimprove) {
3648 game.info.great_wonder_owners[improvement_index(pimprove)]
3649 = WONDER_DESTROYED;
3650 }
3651 }
3652 }
3653
3654 server.identity_number
3655 = secfile_lookup_int_default(loading->file, server.identity_number,
3656 "players.identity_number_used");
3657
3658 /* First remove all defined players. */
3659 players_iterate(pplayer) {
3660 server_remove_player(pplayer);
3661 } players_iterate_end;
3662
3663 /* Now, load the players from the savefile. */
3664 player_slots_iterate(pslot) {
3665 struct player *pplayer;
3666 struct rgbcolor *prgbcolor = NULL;
3667 int pslot_id = player_slot_index(pslot);
3668
3669 if (NULL == secfile_section_lookup(loading->file, "player%d",
3670 pslot_id)) {
3671 continue;
3672 }
3673
3674 /* Get player AI type. */
3675 str = secfile_lookup_str(loading->file, "player%d.ai_type",
3676 player_slot_index(pslot));
3677 sg_failure_ret(str != NULL, "%s", secfile_error());
3678
3679 /* Get player color */
3680 if (!rgbcolor_load(loading->file, &prgbcolor, "player%d.color",
3681 pslot_id)) {
3682 if (game_was_started()) {
3683 log_sg("Game has started, yet player %d has no color defined.",
3684 pslot_id);
3685 /* This will be fixed up later */
3686 } else {
3687 log_verbose("No color defined for player %d.", pslot_id);
3688 /* Colors will be assigned on game start, or at end of savefile
3689 * loading if game has already started */
3690 }
3691 }
3692
3693 /* Create player. */
3694 pplayer = server_create_player(player_slot_index(pslot), str,
3695 prgbcolor,
3696 !game.scenario.is_scenario
3697 || game.scenario.allow_ai_type_fallback);
3698 sg_failure_ret(pplayer != NULL, "Invalid AI type: '%s'!", str);
3699
3700 server_player_init(pplayer, FALSE, FALSE);
3701
3702 /* Free the color definition. */
3703 rgbcolor_destroy(prgbcolor);
3704
3705 /* Multipliers (policies) */
3706
3707 /* First initialise player values with ruleset defaults; this will
3708 * cover any in the ruleset not known when the savefile was created. */
3709 multipliers_iterate(pmul) {
3710 pplayer->multipliers[multiplier_index(pmul)].value
3711 = pplayer->multipliers[multiplier_index(pmul)].target = pmul->def;
3712 } multipliers_iterate_end;
3713
3714 /* Now override with any values from the savefile. */
3715 for (k = 0; k < loading->multiplier.size; k++) {
3716 const struct multiplier *pmul = loading->multiplier.order[k];
3717
3718 if (pmul) {
3719 Multiplier_type_id idx = multiplier_index(pmul);
3720 int val =
3721 secfile_lookup_int_default(loading->file, pmul->def,
3722 "player%d.multiplier%d.val",
3723 player_slot_index(pslot), k);
3724 int rval = (((CLIP(pmul->start, val, pmul->stop)
3725 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3726
3727 if (rval != val) {
3728 log_verbose("Player %d had illegal value for multiplier \"%s\": "
3729 "was %d, clamped to %d", pslot_id,
3730 multiplier_rule_name(pmul), val, rval);
3731 }
3732 pplayer->multipliers[idx].value = rval;
3733
3734 val =
3735 secfile_lookup_int_default(loading->file,
3736 pplayer->multipliers[idx].value,
3737 "player%d.multiplier%d.target",
3738 player_slot_index(pslot), k);
3739 rval = (((CLIP(pmul->start, val, pmul->stop)
3740 - pmul->start) / pmul->step) * pmul->step) + pmul->start;
3741
3742 if (rval != val) {
3743 log_verbose("Player %d had illegal value for multiplier_target "
3744 " \"%s\": was %d, clamped to %d", pslot_id,
3745 multiplier_rule_name(pmul), val, rval);
3746 }
3747 pplayer->multipliers[idx].target = rval;
3748
3749 pplayer->multipliers[idx].changed
3750 = secfile_lookup_int_default(loading->file, 0,
3751 "player%d.multiplier%d.changed",
3752 player_slot_index(pslot), k);
3753 } /* else silently discard multiplier not in current ruleset */
3754 }
3755
3756 /* Must be loaded before tile owner is set. */
3757 pplayer->server.border_vision =
3758 secfile_lookup_bool_default(loading->file, FALSE,
3759 "player%d.border_vision",
3760 player_slot_index(pslot));
3761
3762 pplayer->autoselect_weight = secfile_lookup_int_default(loading->file, 0,
3763 "player%d.autoselect_weight",
3764 pslot_id);
3765 } player_slots_iterate_end;
3766
3767 /* check number of players */
3768 nplayers = secfile_lookup_int_default(loading->file, 0, "players.nplayers");
3769 sg_failure_ret(player_count() == nplayers, "The value of players.nplayers "
3770 "(%d) from the loaded game does not match the number of "
3771 "players present (%d).", nplayers, player_count());
3772
3773 /* Load team informations. */
3774 players_iterate(pplayer) {
3775 int team;
3776 struct team_slot *tslot = NULL;
3777
3778 sg_failure_ret(secfile_lookup_int(loading->file, &team,
3779 "player%d.team_no",
3780 player_number(pplayer))
3781 && (tslot = team_slot_by_number(team)),
3782 "Invalid team definition for player %s (nb %d).",
3783 player_name(pplayer), player_number(pplayer));
3784 /* Should never fail when slot given is not NULL */
3785 team_add_player(pplayer, team_new(tslot));
3786 } players_iterate_end;
3787
3788 /* Loading the shuffle list is quite complex. At the time of saving the
3789 * shuffle data is saved as
3790 * shuffled_player_<number> = player_slot_id
3791 * where number is an increasing number and player_slot_id is a number
3792 * between 0 and the maximum number of player slots. Now we have to create
3793 * a list
3794 * shuffler_players[number] = player_slot_id
3795 * where all player slot IDs are used exactly one time. The code below
3796 * handles this ... */
3797 if (secfile_lookup_int_default(loading->file, -1,
3798 "players.shuffled_player_%d", 0) >= 0) {
3799 int slots = player_slot_count();
3800 int plrcount = player_count();
3801 int shuffled_players[slots];
3802 bool shuffled_player_set[slots];
3803
3804 for (i = 0; i < slots; i++) {
3805 /* Array to save used numbers. */
3806 shuffled_player_set[i] = FALSE;
3807 /* List of all player IDs (needed for set_shuffled_players()). It is
3808 * initialised with the value -1 to indicate that no value is set. */
3809 shuffled_players[i] = -1;
3810 }
3811
3812 /* Load shuffled player list. */
3813 for (i = 0; i < plrcount; i++) {
3814 int shuffle
3815 = secfile_lookup_int_default(loading->file, -1,
3816 "players.shuffled_player_%d", i);
3817
3818 if (shuffle == -1) {
3819 log_sg("Missing player shuffle information (index %d) "
3820 "- reshuffle player list!", i);
3821 shuffle_loaded = FALSE;
3822 break;
3823 } else if (shuffled_player_set[shuffle]) {
3824 log_sg("Player shuffle %d used two times "
3825 "- reshuffle player list!", shuffle);
3826 shuffle_loaded = FALSE;
3827 break;
3828 }
3829 /* Set this ID as used. */
3830 shuffled_player_set[shuffle] = TRUE;
3831
3832 /* Save the player ID in the shuffle list. */
3833 shuffled_players[i] = shuffle;
3834 }
3835
3836 if (shuffle_loaded) {
3837 /* Insert missing numbers. */
3838 int shuffle_index = plrcount;
3839
3840 for (i = 0; i < slots; i++) {
3841 if (!shuffled_player_set[i]) {
3842 shuffled_players[shuffle_index++] = i;
3843 }
3844
3845 /* shuffle_index must not grow higher than size of shuffled_players. */
3846 sg_failure_ret(shuffle_index <= slots,
3847 "Invalid player shuffle data!");
3848 }
3849
3850#ifdef FREECIV_DEBUG
3851 log_debug("[load shuffle] player_count() = %d", player_count());
3852 player_slots_iterate(pslot) {
3853 int plrid = player_slot_index(pslot);
3854
3855 log_debug("[load shuffle] id: %3d => slot: %3d | slot %3d: %s",
3856 plrid, shuffled_players[plrid], plrid,
3857 shuffled_player_set[plrid] ? "is used" : "-");
3858 } player_slots_iterate_end;
3859#endif /* FREECIV_DEBUG */
3860
3861 /* Set shuffle list from savegame. */
3862 set_shuffled_players(shuffled_players);
3863 }
3864 }
3865
3866 if (!shuffle_loaded) {
3867 /* No shuffled players included or error loading them, so shuffle them
3868 * (this may include scenarios). */
3869 shuffle_players();
3870 }
3871}
3872
3873/************************************************************************/
3876 static void sg_load_players(struct loaddata *loading)
3877{
3878 /* Check status and return if not OK (sg_success FALSE). */
3879 sg_check_ret();
3880
3881 if (game.info.is_new_game) {
3882 /* Nothing to do. */
3883 return;
3884 }
3885
3886 players_iterate(pplayer) {
3887 sg_load_player_main(loading, pplayer);
3888 sg_load_player_cities(loading, pplayer);
3889 sg_load_player_units(loading, pplayer);
3890 sg_load_player_attributes(loading, pplayer);
3891
3892 /* Check the success of the functions above. */
3893 sg_check_ret();
3894
3895 /* print out some informations */
3896 if (is_ai(pplayer)) {
3897 log_normal(_("%s has been added as %s level AI-controlled player "
3898 "(%s)."), player_name(pplayer),
3899 ai_level_translated_name(pplayer->ai_common.skill_level),
3900 ai_name(pplayer->ai));
3901 } else {
3902 log_normal(_("%s has been added as human player."),
3903 player_name(pplayer));
3904 }
3905 } players_iterate_end;
3906
3907 /* Also load the transport status of the units here. It must be a special
3908 * case as all units must be known (unit on an allied transporter). */
3909 players_iterate(pplayer) {
3910 /* Load unit transport status. */
3911 sg_load_player_units_transport(loading, pplayer);
3912 } players_iterate_end;
3913
3914 /* Savegame may contain nation assignments that are incompatible with the
3915 * current nationset. Ensure they are compatible, one way or another. */
3916 fit_nationset_to_players();
3917
3918 /* Some players may have invalid nations in the ruleset. Once all players
3919 * are loaded, pick one of the remaining nations for them. */
3920 players_iterate(pplayer) {
3921 if (pplayer->nation == NO_NATION_SELECTED) {
3922 player_set_nation(pplayer, pick_a_nation(NULL, FALSE, TRUE,
3923 NOT_A_BARBARIAN));
3924 /* TRANS: Minor error message: <Leader> ... <Poles>. */
3925 log_sg(_("%s had invalid nation; changing to %s."),
3926 player_name(pplayer), nation_plural_for_player(pplayer));
3927
3928 ai_traits_init(pplayer);
3929 }
3930 } players_iterate_end;
3931
3932 /* Sanity check alliances, prevent allied-with-ally-of-enemy. */
3933 players_iterate_alive(plr) {
3934 players_iterate_alive(aplayer) {
3935 if (pplayers_allied(plr, aplayer)) {
3936 enum dipl_reason can_ally = pplayer_can_make_treaty(plr, aplayer,
3937 DS_ALLIANCE);
3938
3939 if (can_ally == DIPL_ALLIANCE_PROBLEM_US
3940 || can_ally == DIPL_ALLIANCE_PROBLEM_THEM) {
3941 log_sg("Illegal alliance structure detected: "
3942 "%s alliance to %s reduced to peace treaty.",
3943 nation_rule_name(nation_of_player(plr)),
3944 nation_rule_name(nation_of_player(aplayer)));
3945 player_diplstate_get(plr, aplayer)->type = DS_PEACE;
3946 player_diplstate_get(aplayer, plr)->type = DS_PEACE;
3947 }
3948 }
3949 } players_iterate_alive_end;
3950 } players_iterate_alive_end;
3951
3952 /* Update cached city illness. This can depend on trade routes,
3953 * so can't be calculated until all players have been loaded. */
3954 if (game.info.illness_on) {
3955 cities_iterate(pcity) {
3956 pcity->server.illness
3957 = city_illness_calc(pcity, NULL, NULL,
3958 &(pcity->illness_trade), NULL);
3959 } cities_iterate_end;
3960 }
3961
3962 /* Update all city information. This must come after all cities are
3963 * loaded (in player_load) but before player (dumb) cities are loaded
3964 * in player_load_vision(). */
3965 players_iterate(plr) {
3966 city_list_iterate(plr->cities, pcity) {
3967 city_refresh(pcity);
3968 sanity_check_city(pcity);
3969 CALL_PLR_AI_FUNC(city_got, plr, plr, pcity);
3970 } city_list_iterate_end;
3971 } players_iterate_end;
3972
3973 /* Since the cities must be placed on the map to put them on the
3974 player map we do this afterwards */
3975 players_iterate(pplayer) {
3976 sg_load_player_vision(loading, pplayer);
3977 /* Check the success of the function above. */
3978 sg_check_ret();
3979 } players_iterate_end;
3980
3981 /* Check shared vision and tiles. */
3982 players_iterate(pplayer) {
3983 BV_CLR_ALL(pplayer->gives_shared_vision);
3984 BV_CLR_ALL(pplayer->gives_shared_tiles);
3985 BV_CLR_ALL(pplayer->server.really_gives_vision);
3986 } players_iterate_end;
3987
3988 /* Set up shared vision... */
3989 players_iterate(pplayer) {
3990 int plr1 = player_index(pplayer);
3991
3992 players_iterate(pplayer2) {
3993 int plr2 = player_index(pplayer2);
3994
3995 if (secfile_lookup_bool_default(loading->file, FALSE,
3996 "player%d.diplstate%d.gives_shared_vision", plr1, plr2)) {
3997 give_shared_vision(pplayer, pplayer2);
3998 }
3999 if (secfile_lookup_bool_default(loading->file, FALSE,
4000 "player%d.diplstate%d.gives_shared_tiles", plr1, plr2)) {
4001 BV_SET(pplayer->gives_shared_tiles, player_index(pplayer2));
4002 }
4003 } players_iterate_end;
4004 } players_iterate_end;
4005
4006 /* ...and check it */
4007 players_iterate(pplayer1) {
4008 players_iterate(pplayer2) {
4009 /* TODO: Is there a good reason player is not marked as
4010 * giving shared vision to themselves -> really_gives_vision()
4011 * returning FALSE when pplayer1 == pplayer2 */
4012 if (pplayer1 != pplayer2
4013 && players_on_same_team(pplayer1, pplayer2)) {
4014 if (!really_gives_vision(pplayer1, pplayer2)) {
4015 sg_regr(3000900,
4016 _("%s did not give shared vision to team member %s."),
4017 player_name(pplayer1), player_name(pplayer2));
4018 give_shared_vision(pplayer1, pplayer2);
4019 }
4020 if (!really_gives_vision(pplayer2, pplayer1)) {
4021 sg_regr(3000900,
4022 _("%s did not give shared vision to team member %s."),
4023 player_name(pplayer2), player_name(pplayer1));
4024 give_shared_vision(pplayer2, pplayer1);
4025 }
4026 }
4027 } players_iterate_end;
4028 } players_iterate_end;
4029
4030 initialize_globals();
4031 unit_ordering_apply();
4032
4033 /* All vision is ready; this calls city_thaw_workers_queue(). */
4034 map_calculate_borders();
4035
4036 /* Make sure everything is consistent. */
4037 players_iterate(pplayer) {
4038 unit_list_iterate(pplayer->units, punit) {
4039 if (!can_unit_continue_current_activity(&(wld.map), punit)) {
4040 struct tile *ptile = unit_tile(punit);
4041
4042 log_sg("%s doing illegal activity in savegame!",
4043 unit_rule_name(punit));
4044 log_sg("Activity: %s, Target: %s, Tile: (%d, %d), Terrain: %s",
4045 unit_activity_name(punit->activity),
4046 punit->activity_target ? extra_rule_name(
4047 punit->activity_target)
4048 : "missing",
4049 TILE_XY(ptile), terrain_rule_name(tile_terrain(ptile)));
4050 punit->activity = ACTIVITY_IDLE;
4051 }
4052 } unit_list_iterate_end;
4053 } players_iterate_end;
4054
4055 cities_iterate(pcity) {
4056 city_refresh(pcity);
4057 city_thaw_workers(pcity); /* may auto_arrange_workers() */
4058 } cities_iterate_end;
4059
4060 /* Player colors are always needed once game has started. Pre-2.4 savegames
4061 * lack them. This cannot be in compatibility conversion layer as we need
4062 * all the player data available to be able to assign best colors. */
4063 if (game_was_started()) {
4064 assign_player_colors();
4065 }
4066}
4067
4068/************************************************************************/
4071 static void sg_save_players(struct savedata *saving)
4072{
4073 /* Check status and return if not OK (sg_success FALSE). */
4074 sg_check_ret();
4075
4076 if ((saving->scenario && !saving->save_players)
4077 || !game_was_started()) {
4078 /* Nothing to do for a scenario without saved players or a game in
4079 * INITIAL state. */
4080 return;
4081 }
4082
4083 secfile_insert_int(saving->file, player_count(), "players.nplayers");
4084
4085 /* Save destroyed wonders as bitvector. Note that improvement order
4086 * is saved in 'savefile.improvement.order'. */
4087 {
4088 char destroyed[B_LAST+1];
4089
4090 improvement_iterate(pimprove) {
4091 if (is_great_wonder(pimprove)
4092 && great_wonder_is_destroyed(pimprove)) {
4093 destroyed[improvement_index(pimprove)] = '1';
4094 } else {
4095 destroyed[improvement_index(pimprove)] = '0';
4096 }
4097 } improvement_iterate_end;
4098 destroyed[improvement_count()] = '\0';
4099 secfile_insert_str(saving->file, destroyed,
4100 "players.destroyed_wonders");
4101 }
4102
4103 secfile_insert_int(saving->file, server.identity_number,
4104 "players.identity_number_used");
4105
4106 /* Save player order. */
4107 {
4108 int i = 0;
4109 shuffled_players_iterate(pplayer) {
4110 secfile_insert_int(saving->file, player_number(pplayer),
4111 "players.shuffled_player_%d", i);
4112 i++;
4113 } shuffled_players_iterate_end;
4114 }
4115
4116 /* Sort units. */
4117 unit_ordering_calc();
4118
4119 /* Save players. */
4120 players_iterate(pplayer) {
4121 sg_save_player_main(saving, pplayer);
4122 sg_save_player_cities(saving, pplayer);
4123 sg_save_player_units(saving, pplayer);
4124 sg_save_player_attributes(saving, pplayer);
4125 sg_save_player_vision(saving, pplayer);
4126 } players_iterate_end;
4127}
4128
4129/************************************************************************/
4132 static void sg_load_player_main(struct loaddata *loading,
4133 struct player *plr)
4134{
4135 const char **slist;
4136 int i, plrno = player_number(plr);
4137 const char *str;
4138 struct government *gov;
4139 const char *level;
4140 const char *barb_str;
4141 size_t nval;
4142 const char *kind;
4143
4144 /* Check status and return if not OK (sg_success FALSE). */
4145 sg_check_ret();
4146
4147 /* Basic player data. */
4148 str = secfile_lookup_str(loading->file, "player%d.name", plrno);
4149 sg_failure_ret(str != NULL, "%s", secfile_error());
4150 server_player_set_name(plr, str);
4151 sz_strlcpy(plr->username,
4152 secfile_lookup_str_default(loading->file, "",
4153 "player%d.username", plrno));
4154 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->unassigned_user,
4155 "player%d.unassigned_user", plrno),
4156 "%s", secfile_error());
4157 sz_strlcpy(plr->server.orig_username,
4158 secfile_lookup_str_default(loading->file, "",
4159 "player%d.orig_username", plrno));
4160 sz_strlcpy(plr->ranked_username,
4161 secfile_lookup_str_default(loading->file, "",
4162 "player%d.ranked_username",
4163 plrno));
4164 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->unassigned_ranked,
4165 "player%d.unassigned_ranked", plrno),
4166 "%s", secfile_error());
4167 str = secfile_lookup_str_default(loading->file, "",
4168 "player%d.delegation_username",
4169 plrno);
4170 /* Defaults to no delegation. */
4171 if (strlen(str)) {
4172 player_delegation_set(plr, str);
4173 }
4174
4175 /* Player flags */
4176 BV_CLR_ALL(plr->flags);
4177 slist = secfile_lookup_str_vec(loading->file, &nval, "player%d.flags", plrno);
4178 for (i = 0; i < nval; i++) {
4179 const char *sval = slist[i];
4180 enum plr_flag_id fid = plr_flag_id_by_name(sval, fc_strcasecmp);
4181
4182 sg_failure_ret(plr_flag_id_is_valid(fid), "Invalid player flag \"%s\".", sval);
4183
4184 BV_SET(plr->flags, fid);
4185 }
4186 free(slist);
4187
4188 /* Nation */
4189 str = secfile_lookup_str(loading->file, "player%d.nation", plrno);
4190 player_set_nation(plr, nation_by_rule_name(str));
4191 if (plr->nation != NULL) {
4192 ai_traits_init(plr);
4193 }
4194
4195 /* Government */
4196 str = secfile_lookup_str(loading->file, "player%d.government_name",
4197 plrno);
4198 gov = government_by_rule_name(str);
4199 sg_failure_ret(gov != NULL, "Player%d: unsupported government \"%s\".",
4200 plrno, str);
4201 plr->government = gov;
4202
4203 /* Target government */
4204 str = secfile_lookup_str(loading->file,
4205 "player%d.target_government_name", plrno);
4206 if (str != NULL) {
4207 plr->target_government = government_by_rule_name(str);
4208 } else {
4209 plr->target_government = NULL;
4210 }
4211 plr->revolution_finishes
4212 = secfile_lookup_int_default(loading->file, -1,
4213 "player%d.revolution_finishes", plrno);
4214
4215 /* Load diplomatic data (diplstate + embassy + vision).
4216 * Shared vision is loaded in sg_load_players(). */
4217 BV_CLR_ALL(plr->real_embassy);
4218 players_iterate(pplayer) {
4219 char buf[32];
4220 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4221 i = player_index(pplayer);
4222
4223 /* Load diplomatic status */
4224 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4225
4226 ds->type =
4227 secfile_lookup_enum_default(loading->file, DS_WAR,
4228 diplstate_type, "%s.current", buf);
4229 ds->max_state =
4230 secfile_lookup_enum_default(loading->file, DS_WAR,
4231 diplstate_type, "%s.closest", buf);
4232
4233 /* FIXME: If either party is barbarian, we cannot enforce below check */
4234#if 0
4235 if (ds->type == DS_WAR && ds->first_contact_turn <= 0) {
4236 sg_regr(3020000,
4237 "Player%d: War with player %d who has never been met. "
4238 "Reverted to No Contact state.", plrno, i);
4239 ds->type = DS_NO_CONTACT;
4240 }
4241#endif
4242
4243 if (valid_dst_closest(ds) != ds->max_state) {
4244 sg_regr(3020000,
4245 "Player%d: closest diplstate to player %d less than current. "
4246 "Updated.", plrno, i);
4247 ds->max_state = ds->type;
4248 }
4249
4250 ds->first_contact_turn =
4251 secfile_lookup_int_default(loading->file, 0,
4252 "%s.first_contact_turn", buf);
4253 ds->turns_left =
4254 secfile_lookup_int_default(loading->file, -2, "%s.turns_left", buf);
4255 ds->has_reason_to_cancel =
4256 secfile_lookup_int_default(loading->file, 0,
4257 "%s.has_reason_to_cancel", buf);
4258 ds->contact_turns_left =
4259 secfile_lookup_int_default(loading->file, 0,
4260 "%s.contact_turns_left", buf);
4261
4262 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.embassy",
4263 buf)) {
4264 BV_SET(plr->real_embassy, i);
4265 }
4266 /* 'gives_shared_vision' is loaded in sg_load_players() as all cities
4267 * must be known. */
4268 } players_iterate_end;
4269
4270 /* load ai data */
4271 players_iterate(aplayer) {
4272 char buf[32];
4273
4274 fc_snprintf(buf, sizeof(buf), "player%d.ai%d", plrno,
4275 player_index(aplayer));
4276
4277 plr->ai_common.love[player_index(aplayer)] =
4278 secfile_lookup_int_default(loading->file, 1, "%s.love", buf);
4279 CALL_FUNC_EACH_AI(player_load_relations, plr, aplayer, loading->file, plrno);
4280 } players_iterate_end;
4281
4282 plr->server.adv->wonder_city = secfile_lookup_int_default(loading->file, 0,
4283 "player%d.adv.wonder_city",
4284 plrno);
4285
4286 CALL_FUNC_EACH_AI(player_load, plr, loading->file, plrno);
4287
4288 /* Some sane defaults */
4289 plr->ai_common.fuzzy = 0;
4290 plr->ai_common.expand = 100;
4291 plr->ai_common.science_cost = 100;
4292
4293
4294 level = secfile_lookup_str_default(loading->file, NULL,
4295 "player%d.ai.level", plrno);
4296 if (level != NULL && !fc_strcasecmp("Handicapped", level)) {
4297 /* Up to freeciv-3.1 Restricted AI level was known as Handicapped */
4298 plr->ai_common.skill_level = AI_LEVEL_RESTRICTED;
4299 } else {
4300 plr->ai_common.skill_level = ai_level_by_name(level, fc_strcasecmp);
4301 }
4302
4303 if (!ai_level_is_valid(plr->ai_common.skill_level)) {
4304 log_sg("Player%d: Invalid AI level \"%s\". "
4305 "Changed to \"%s\".", plrno, level,
4306 ai_level_name(game.info.skill_level));
4307 plr->ai_common.skill_level = game.info.skill_level;
4308 }
4309
4310 barb_str = secfile_lookup_str_default(loading->file, "None",
4311 "player%d.ai.barb_type", plrno);
4312 plr->ai_common.barbarian_type = barbarian_type_by_name(barb_str, fc_strcasecmp);
4313
4314 if (!barbarian_type_is_valid(plr->ai_common.barbarian_type)) {
4315 log_sg("Player%d: Invalid barbarian type \"%s\". "
4316 "Changed to \"None\".", plrno, barb_str);
4317 plr->ai_common.barbarian_type = NOT_A_BARBARIAN;
4318 }
4319
4320 if (is_barbarian(plr)) {
4321 server.nbarbarians++;
4322 }
4323
4324 if (is_ai(plr)) {
4325 set_ai_level_directer(plr, plr->ai_common.skill_level);
4326 CALL_PLR_AI_FUNC(gained_control, plr, plr);
4327 }
4328
4329 /* Load nation style. */
4330 {
4331 struct nation_style *style;
4332
4333 str = secfile_lookup_str(loading->file, "player%d.style_by_name", plrno);
4334
4335 sg_failure_ret(str != NULL, "%s", secfile_error());
4336 style = style_by_rule_name(str);
4337 if (style == NULL) {
4338 style = style_by_number(0);
4339 log_sg("Player%d: unsupported city_style_name \"%s\". "
4340 "Changed to \"%s\".", plrno, str, style_rule_name(style));
4341 }
4342 plr->style = style;
4343 }
4344
4345 sg_failure_ret(secfile_lookup_int(loading->file, &plr->nturns_idle,
4346 "player%d.idle_turns", plrno),
4347 "%s", secfile_error());
4348 kind = secfile_lookup_str(loading->file, "player%d.kind", plrno);
4349 if (sex_by_name(kind) == SEX_MALE) {
4350 plr->is_male = TRUE;
4351 } else {
4352 plr->is_male = FALSE;
4353 }
4354 sg_failure_ret(secfile_lookup_bool(loading->file, &plr->is_alive,
4355 "player%d.is_alive", plrno),
4356 "%s", secfile_error());
4357 sg_failure_ret(secfile_lookup_int(loading->file, &plr->turns_alive,
4358 "player%d.turns_alive", plrno),
4359 "%s", secfile_error());
4360 sg_failure_ret(secfile_lookup_int(loading->file, &plr->last_war_action,
4361 "player%d.last_war", plrno),
4362 "%s", secfile_error());
4363 plr->phase_done = secfile_lookup_bool_default(loading->file, FALSE,
4364 "player%d.phase_done", plrno);
4365 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.gold,
4366 "player%d.gold", plrno),
4367 "%s", secfile_error());
4368 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.tax,
4369 "player%d.rates.tax", plrno),
4370 "%s", secfile_error());
4371 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.science,
4372 "player%d.rates.science", plrno),
4373 "%s", secfile_error());
4374 sg_failure_ret(secfile_lookup_int(loading->file, &plr->economic.luxury,
4375 "player%d.rates.luxury", plrno),
4376 "%s", secfile_error());
4377 plr->economic.infra_points = secfile_lookup_int_default(loading->file, 0,
4378 "player%d.infrapts",
4379 plrno);
4380 plr->server.bulbs_last_turn =
4381 secfile_lookup_int_default(loading->file, 0,
4382 "player%d.research.bulbs_last_turn", plrno);
4383
4384 /* Traits */
4385 if (plr->nation) {
4386 for (i = 0; i < loading->trait.size; i++) {
4387 enum trait tr = trait_by_name(loading->trait.order[i], fc_strcasecmp);
4388
4389 if (trait_is_valid(tr)) {
4390 int val;
4391
4392 sg_failure_ret(secfile_lookup_int(loading->file, &val, "player%d.trait%d.val",
4393 plrno, i),
4394 "%s", secfile_error());
4395 plr->ai_common.traits[tr].val = val;
4396
4397 sg_failure_ret(secfile_lookup_int(loading->file, &val,
4398 "player%d.trait%d.mod", plrno, i),
4399 "%s", secfile_error());
4400 plr->ai_common.traits[tr].mod = val;
4401 }
4402 }
4403 }
4404
4405 /* Achievements */
4406 {
4407 int count;
4408
4409 count = secfile_lookup_int_default(loading->file, -1,
4410 "player%d.achievement_count", plrno);
4411
4412 if (count > 0) {
4413 for (i = 0; i < count; i++) {
4414 const char *name;
4415 struct achievement *pach;
4416 bool first;
4417
4418 name = secfile_lookup_str(loading->file,
4419 "player%d.achievement%d.name", plrno, i);
4420 pach = achievement_by_rule_name(name);
4421
4422 sg_failure_ret(pach != NULL,
4423 "Unknown achievement \"%s\".", name);
4424
4425 sg_failure_ret(secfile_lookup_bool(loading->file, &first,
4426 "player%d.achievement%d.first",
4427 plrno, i),
4428 "achievement error: %s", secfile_error());
4429
4430 sg_failure_ret(pach->first == NULL || !first,
4431 "Multiple players listed as first to get achievement \"%s\".",
4432 name);
4433
4434 BV_SET(pach->achievers, player_index(plr));
4435
4436 if (first) {
4437 pach->first = plr;
4438 }
4439 }
4440 }
4441 }
4442
4443 /* Player score. */
4444 plr->score.happy =
4445 secfile_lookup_int_default(loading->file, 0,
4446 "score%d.happy", plrno);
4447 plr->score.content =
4448 secfile_lookup_int_default(loading->file, 0,
4449 "score%d.content", plrno);
4450 plr->score.unhappy =
4451 secfile_lookup_int_default(loading->file, 0,
4452 "score%d.unhappy", plrno);
4453 plr->score.angry =
4454 secfile_lookup_int_default(loading->file, 0,
4455 "score%d.angry", plrno);
4456
4457 /* Make sure that the score about specialists in current ruleset that
4458 * were not present at saving time are set to zero. */
4459 specialist_type_iterate(sp) {
4460 plr->score.specialists[sp] = 0;
4461 } specialist_type_iterate_end;
4462
4463 for (i = 0; i < loading->specialist.size; i++) {
4464 plr->score.specialists[specialist_index(loading->specialist.order[i])]
4465 = secfile_lookup_int_default(loading->file, 0,
4466 "score%d.specialists%d", plrno, i);
4467 }
4468
4469 plr->score.wonders =
4470 secfile_lookup_int_default(loading->file, 0,
4471 "score%d.wonders", plrno);
4472 plr->score.techs =
4473 secfile_lookup_int_default(loading->file, 0,
4474 "score%d.techs", plrno);
4475 plr->score.techout =
4476 secfile_lookup_int_default(loading->file, 0,
4477 "score%d.techout", plrno);
4478 plr->score.landarea =
4479 secfile_lookup_int_default(loading->file, 0,
4480 "score%d.landarea", plrno);
4481 plr->score.settledarea =
4482 secfile_lookup_int_default(loading->file, 0,
4483 "score%d.settledarea", plrno);
4484 plr->score.population =
4485 secfile_lookup_int_default(loading->file, 0,
4486 "score%d.population", plrno);
4487 plr->score.cities =
4488 secfile_lookup_int_default(loading->file, 0,
4489 "score%d.cities", plrno);
4490 plr->score.units =
4491 secfile_lookup_int_default(loading->file, 0,
4492 "score%d.units", plrno);
4493 plr->score.pollution =
4494 secfile_lookup_int_default(loading->file, 0,
4495 "score%d.pollution", plrno);
4496 plr->score.literacy =
4497 secfile_lookup_int_default(loading->file, 0,
4498 "score%d.literacy", plrno);
4499 plr->score.bnp =
4500 secfile_lookup_int_default(loading->file, 0,
4501 "score%d.bnp", plrno);
4502 plr->score.mfg =
4503 secfile_lookup_int_default(loading->file, 0,
4504 "score%d.mfg", plrno);
4505 plr->score.spaceship =
4506 secfile_lookup_int_default(loading->file, 0,
4507 "score%d.spaceship", plrno);
4508 plr->score.units_built =
4509 secfile_lookup_int_default(loading->file, 0,
4510 "score%d.units_built", plrno);
4511 plr->score.units_killed =
4512 secfile_lookup_int_default(loading->file, 0,
4513 "score%d.units_killed", plrno);
4514 plr->score.units_lost =
4515 secfile_lookup_int_default(loading->file, 0,
4516 "score%d.units_lost", plrno);
4517 plr->score.units_used =
4518 secfile_lookup_int_default(loading->file, 0,
4519 "score%d.units_used", plrno);
4520 plr->score.culture =
4521 secfile_lookup_int_default(loading->file, 0,
4522 "score%d.culture", plrno);
4523 plr->score.game =
4524 secfile_lookup_int_default(loading->file, 0,
4525 "score%d.total", plrno);
4526
4527 /* Load space ship data. */
4528 {
4529 struct player_spaceship *ship = &plr->spaceship;
4530 char prefix[32];
4531 const char *st;
4532 int ei;
4533
4534 fc_snprintf(prefix, sizeof(prefix), "player%d.spaceship", plrno);
4535 spaceship_init(ship);
4536 sg_failure_ret(secfile_lookup_int(loading->file,
4537 &ei,
4538 "%s.state", prefix),
4539 "%s", secfile_error());
4540 ship->state = ei;
4541
4542 if (ship->state != SSHIP_NONE) {
4543 sg_failure_ret(secfile_lookup_int(loading->file, &ship->structurals,
4544 "%s.structurals", prefix),
4545 "%s", secfile_error());
4546 sg_failure_ret(secfile_lookup_int(loading->file, &ship->components,
4547 "%s.components", prefix),
4548 "%s", secfile_error());
4549 sg_failure_ret(secfile_lookup_int(loading->file, &ship->modules,
4550 "%s.modules", prefix),
4551 "%s", secfile_error());
4552 sg_failure_ret(secfile_lookup_int(loading->file, &ship->fuel,
4553 "%s.fuel", prefix),
4554 "%s", secfile_error());
4555 sg_failure_ret(secfile_lookup_int(loading->file, &ship->propulsion,
4556 "%s.propulsion", prefix),
4557 "%s", secfile_error());
4558 sg_failure_ret(secfile_lookup_int(loading->file, &ship->habitation,
4559 "%s.habitation", prefix),
4560 "%s", secfile_error());
4561 sg_failure_ret(secfile_lookup_int(loading->file, &ship->life_support,
4562 "%s.life_support", prefix),
4563 "%s", secfile_error());
4564 sg_failure_ret(secfile_lookup_int(loading->file, &ship->solar_panels,
4565 "%s.solar_panels", prefix),
4566 "%s", secfile_error());
4567
4568 st = secfile_lookup_str(loading->file, "%s.structure", prefix);
4569 sg_failure_ret(st != NULL, "%s", secfile_error())
4570 for (i = 0; i < NUM_SS_STRUCTURALS && st[i]; i++) {
4571 sg_failure_ret(st[i] == '1' || st[i] == '0',
4572 "Undefined value '%c' within '%s.structure'.", st[i],
4573 prefix)
4574
4575 if (!(st[i] == '0')) {
4576 BV_SET(ship->structure, i);
4577 }
4578 }
4579 if (ship->state >= SSHIP_LAUNCHED) {
4580 sg_failure_ret(secfile_lookup_int(loading->file, &ship->launch_year,
4581 "%s.launch_year", prefix),
4582 "%s", secfile_error());
4583 }
4584 spaceship_calc_derived(ship);
4585 }
4586 }
4587
4588 /* Load lost wonder data. */
4589 str = secfile_lookup_str(loading->file, "player%d.lost_wonders", plrno);
4590 /* If not present, probably an old savegame; nothing to be done */
4591 if (str != NULL) {
4592 int k;
4593
4594 sg_failure_ret(strlen(str) == loading->improvement.size,
4595 "Invalid length for 'player%d.lost_wonders' ("
4596 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ")",
4597 plrno, strlen(str), loading->improvement.size);
4598 for (k = 0; k < loading->improvement.size; k++) {
4599 sg_failure_ret(str[k] == '1' || str[k] == '0',
4600 "Undefined value '%c' within "
4601 "'player%d.lost_wonders'.", plrno, str[k]);
4602
4603 if (str[k] == '1') {
4604 struct impr_type *pimprove =
4605 improvement_by_rule_name(loading->improvement.order[k]);
4606 if (pimprove) {
4607 plr->wonders[improvement_index(pimprove)] = WONDER_LOST;
4608 }
4609 }
4610 }
4611 }
4612
4613 plr->history =
4614 secfile_lookup_int_default(loading->file, 0, "player%d.history", plrno);
4615 plr->server.huts =
4616 secfile_lookup_int_default(loading->file, 0, "player%d.hut_count", plrno);
4617}
4618
4619/************************************************************************/
4622 static void sg_save_player_main(struct savedata *saving,
4623 struct player *plr)
4624{
4625 int i, k, plrno = player_number(plr);
4626 struct player_spaceship *ship = &plr->spaceship;
4627 const char *flag_names[PLRF_COUNT];
4628 int set_count;
4629
4630 /* Check status and return if not OK (sg_success FALSE). */
4631 sg_check_ret();
4632
4633 set_count = 0;
4634 for (i = 0; i < PLRF_COUNT; i++) {
4635 if (player_has_flag(plr, i)) {
4636 flag_names[set_count++] = plr_flag_id_name(i);
4637 }
4638 }
4639
4640 secfile_insert_str_vec(saving->file, flag_names, set_count,
4641 "player%d.flags", plrno);
4642
4643 secfile_insert_str(saving->file, ai_name(plr->ai),
4644 "player%d.ai_type", plrno);
4645 secfile_insert_str(saving->file, player_name(plr),
4646 "player%d.name", plrno);
4647 secfile_insert_str(saving->file, plr->username,
4648 "player%d.username", plrno);
4649 secfile_insert_bool(saving->file, plr->unassigned_user,
4650 "player%d.unassigned_user", plrno);
4651 if (plr->rgb != NULL) {
4652 rgbcolor_save(saving->file, plr->rgb, "player%d.color", plrno);
4653 } else {
4654 /* Colorless players are ok in pregame */
4655 if (game_was_started()) {
4656 log_sg("Game has started, yet player %d has no color defined.", plrno);
4657 }
4658 }
4659 secfile_insert_str(saving->file, plr->ranked_username,
4660 "player%d.ranked_username", plrno);
4661 secfile_insert_bool(saving->file, plr->unassigned_ranked,
4662 "player%d.unassigned_ranked", plrno);
4663 secfile_insert_str(saving->file, plr->server.orig_username,
4664 "player%d.orig_username", plrno);
4665 secfile_insert_str(saving->file,
4666 player_delegation_get(plr) ? player_delegation_get(plr)
4667 : "",
4668 "player%d.delegation_username", plrno);
4669 secfile_insert_str(saving->file, nation_rule_name(nation_of_player(plr)),
4670 "player%d.nation", plrno);
4671 secfile_insert_int(saving->file, plr->team ? team_index(plr->team) : -1,
4672 "player%d.team_no", plrno);
4673
4674 secfile_insert_str(saving->file,
4675 government_rule_name(government_of_player(plr)),
4676 "player%d.government_name", plrno);
4677
4678 if (plr->target_government) {
4679 secfile_insert_str(saving->file,
4680 government_rule_name(plr->target_government),
4681 "player%d.target_government_name", plrno);
4682 }
4683
4684 secfile_insert_str(saving->file, style_rule_name(plr->style),
4685 "player%d.style_by_name", plrno);
4686
4687 secfile_insert_int(saving->file, plr->nturns_idle,
4688 "player%d.idle_turns", plrno);
4689 if (plr->is_male) {
4690 secfile_insert_str(saving->file, sex_rule_name(SEX_MALE),
4691 "player%d.kind", plrno);
4692 } else {
4693 secfile_insert_str(saving->file, sex_rule_name(SEX_FEMALE),
4694 "player%d.kind", plrno);
4695 }
4696 secfile_insert_bool(saving->file, plr->is_alive,
4697 "player%d.is_alive", plrno);
4698 secfile_insert_int(saving->file, plr->turns_alive,
4699 "player%d.turns_alive", plrno);
4700 secfile_insert_int(saving->file, plr->last_war_action,
4701 "player%d.last_war", plrno);
4702 secfile_insert_bool(saving->file, plr->phase_done,
4703 "player%d.phase_done", plrno);
4704
4705 players_iterate(pplayer) {
4706 char buf[32];
4707 struct player_diplstate *ds = player_diplstate_get(plr, pplayer);
4708
4709 i = player_index(pplayer);
4710
4711 /* save diplomatic state */
4712 fc_snprintf(buf, sizeof(buf), "player%d.diplstate%d", plrno, i);
4713
4714 secfile_insert_enum(saving->file, ds->type,
4715 diplstate_type, "%s.current", buf);
4716 secfile_insert_enum(saving->file, ds->max_state,
4717 diplstate_type, "%s.closest", buf);
4718 secfile_insert_int(saving->file, ds->first_contact_turn,
4719 "%s.first_contact_turn", buf);
4720 secfile_insert_int(saving->file, ds->turns_left,
4721 "%s.turns_left", buf);
4722 secfile_insert_int(saving->file, ds->has_reason_to_cancel,
4723 "%s.has_reason_to_cancel", buf);
4724 secfile_insert_int(saving->file, ds->contact_turns_left,
4725 "%s.contact_turns_left", buf);
4726 secfile_insert_bool(saving->file, player_has_real_embassy(plr, pplayer),
4727 "%s.embassy", buf);
4728 secfile_insert_bool(saving->file, gives_shared_vision(plr, pplayer),
4729 "%s.gives_shared_vision", buf);
4730 secfile_insert_bool(saving->file, gives_shared_tiles(plr, pplayer),
4731 "%s.gives_shared_tiles", buf);
4732 } players_iterate_end;
4733
4734 players_iterate(aplayer) {
4735 i = player_index(aplayer);
4736 /* save ai data */
4737 secfile_insert_int(saving->file, plr->ai_common.love[i],
4738 "player%d.ai%d.love", plrno, i);
4739 CALL_FUNC_EACH_AI(player_save_relations, plr, aplayer, saving->file, plrno);
4740 } players_iterate_end;
4741
4742 secfile_insert_int(saving->file, plr->server.adv->wonder_city,
4743 "player%d.adv.wonder_city", plrno);
4744
4745 CALL_FUNC_EACH_AI(player_save, plr, saving->file, plrno);
4746
4747 /* Multipliers (policies) */
4748 i = multiplier_count();
4749
4750 for (k = 0; k < i; k++) {
4751 secfile_insert_int(saving->file, plr->multipliers[k].value,
4752 "player%d.multiplier%d.val", plrno, k);
4753 secfile_insert_int(saving->file, plr->multipliers[k].target,
4754 "player%d.multiplier%d.target", plrno, k);
4755 secfile_insert_int(saving->file, plr->multipliers[k].changed,
4756 "player%d.multiplier%d.changed", plrno, k);
4757 }
4758
4759 secfile_insert_str(saving->file, ai_level_name(plr->ai_common.skill_level),
4760 "player%d.ai.level", plrno);
4761 secfile_insert_str(saving->file, barbarian_type_name(plr->ai_common.barbarian_type),
4762 "player%d.ai.barb_type", plrno);
4763 secfile_insert_int(saving->file, plr->economic.gold,
4764 "player%d.gold", plrno);
4765 secfile_insert_int(saving->file, plr->economic.tax,
4766 "player%d.rates.tax", plrno);
4767 secfile_insert_int(saving->file, plr->economic.science,
4768 "player%d.rates.science", plrno);
4769 secfile_insert_int(saving->file, plr->economic.luxury,
4770 "player%d.rates.luxury", plrno);
4771 secfile_insert_int(saving->file, plr->economic.infra_points,
4772 "player%d.infrapts", plrno);
4773 secfile_insert_int(saving->file, plr->server.bulbs_last_turn,
4774 "player%d.research.bulbs_last_turn", plrno);
4775
4776 /* Save traits */
4777 {
4778 enum trait tr;
4779 int j;
4780
4781 for (tr = trait_begin(), j = 0; tr != trait_end(); tr = trait_next(tr), j++) {
4782 secfile_insert_int(saving->file, plr->ai_common.traits[tr].val,
4783 "player%d.trait%d.val", plrno, j);
4784 secfile_insert_int(saving->file, plr->ai_common.traits[tr].mod,
4785 "player%d.trait%d.mod", plrno, j);
4786 }
4787 }
4788
4789 /* Save achievements */
4790 {
4791 int j = 0;
4792
4793 achievements_iterate(pach) {
4794 if (achievement_player_has(pach, plr)) {
4795 secfile_insert_str(saving->file, achievement_rule_name(pach),
4796 "player%d.achievement%d.name", plrno, j);
4797 if (pach->first == plr) {
4798 secfile_insert_bool(saving->file, TRUE,
4799 "player%d.achievement%d.first", plrno, j);
4800 } else {
4801 secfile_insert_bool(saving->file, FALSE,
4802 "player%d.achievement%d.first", plrno, j);
4803 }
4804
4805 j++;
4806 }
4807 } achievements_iterate_end;
4808
4809 secfile_insert_int(saving->file, j,
4810 "player%d.achievement_count", plrno);
4811 }
4812
4813 secfile_insert_int(saving->file, plr->revolution_finishes,
4814 "player%d.revolution_finishes", plrno);
4815
4816 /* Player score */
4817 secfile_insert_int(saving->file, plr->score.happy,
4818 "score%d.happy", plrno);
4819 secfile_insert_int(saving->file, plr->score.content,
4820 "score%d.content", plrno);
4821 secfile_insert_int(saving->file, plr->score.unhappy,
4822 "score%d.unhappy", plrno);
4823 secfile_insert_int(saving->file, plr->score.angry,
4824 "score%d.angry", plrno);
4825 specialist_type_iterate(sp) {
4826 secfile_insert_int(saving->file, plr->score.specialists[sp],
4827 "score%d.specialists%d", plrno, sp);
4828 } specialist_type_iterate_end;
4829 secfile_insert_int(saving->file, plr->score.wonders,
4830 "score%d.wonders", plrno);
4831 secfile_insert_int(saving->file, plr->score.techs,
4832 "score%d.techs", plrno);
4833 secfile_insert_int(saving->file, plr->score.techout,
4834 "score%d.techout", plrno);
4835 secfile_insert_int(saving->file, plr->score.landarea,
4836 "score%d.landarea", plrno);
4837 secfile_insert_int(saving->file, plr->score.settledarea,
4838 "score%d.settledarea", plrno);
4839 secfile_insert_int(saving->file, plr->score.population,
4840 "score%d.population", plrno);
4841 secfile_insert_int(saving->file, plr->score.cities,
4842 "score%d.cities", plrno);
4843 secfile_insert_int(saving->file, plr->score.units,
4844 "score%d.units", plrno);
4845 secfile_insert_int(saving->file, plr->score.pollution,
4846 "score%d.pollution", plrno);
4847 secfile_insert_int(saving->file, plr->score.literacy,
4848 "score%d.literacy", plrno);
4849 secfile_insert_int(saving->file, plr->score.bnp,
4850 "score%d.bnp", plrno);
4851 secfile_insert_int(saving->file, plr->score.mfg,
4852 "score%d.mfg", plrno);
4853 secfile_insert_int(saving->file, plr->score.spaceship,
4854 "score%d.spaceship", plrno);
4855 secfile_insert_int(saving->file, plr->score.units_built,
4856 "score%d.units_built", plrno);
4857 secfile_insert_int(saving->file, plr->score.units_killed,
4858 "score%d.units_killed", plrno);
4859 secfile_insert_int(saving->file, plr->score.units_lost,
4860 "score%d.units_lost", plrno);
4861 secfile_insert_int(saving->file, plr->score.units_used,
4862 "score%d.units_used", plrno);
4863 secfile_insert_int(saving->file, plr->score.culture,
4864 "score%d.culture", plrno);
4865 secfile_insert_int(saving->file, plr->score.game,
4866 "score%d.total", plrno);
4867
4868 /* Save space ship status. */
4869 secfile_insert_int(saving->file, ship->state, "player%d.spaceship.state",
4870 plrno);
4871 if (ship->state != SSHIP_NONE) {
4872 char buf[32];
4873 char st[NUM_SS_STRUCTURALS+1];
4874 int ssi;
4875
4876 fc_snprintf(buf, sizeof(buf), "player%d.spaceship", plrno);
4877
4878 secfile_insert_int(saving->file, ship->structurals,
4879 "%s.structurals", buf);
4880 secfile_insert_int(saving->file, ship->components,
4881 "%s.components", buf);
4882 secfile_insert_int(saving->file, ship->modules,
4883 "%s.modules", buf);
4884 secfile_insert_int(saving->file, ship->fuel, "%s.fuel", buf);
4885 secfile_insert_int(saving->file, ship->propulsion, "%s.propulsion", buf);
4886 secfile_insert_int(saving->file, ship->habitation, "%s.habitation", buf);
4887 secfile_insert_int(saving->file, ship->life_support,
4888 "%s.life_support", buf);
4889 secfile_insert_int(saving->file, ship->solar_panels,
4890 "%s.solar_panels", buf);
4891
4892 for (ssi = 0; ssi < NUM_SS_STRUCTURALS; ssi++) {
4893 st[ssi] = BV_ISSET(ship->structure, ssi) ? '1' : '0';
4894 }
4895 st[ssi] = '\0';
4896 secfile_insert_str(saving->file, st, "%s.structure", buf);
4897 if (ship->state >= SSHIP_LAUNCHED) {
4898 secfile_insert_int(saving->file, ship->launch_year,
4899 "%s.launch_year", buf);
4900 }
4901 }
4902
4903 /* Save lost wonders info. */
4904 {
4905 char lost[B_LAST+1];
4906
4907 improvement_iterate(pimprove) {
4908 if (is_wonder(pimprove) && wonder_is_lost(plr, pimprove)) {
4909 lost[improvement_index(pimprove)] = '1';
4910 } else {
4911 lost[improvement_index(pimprove)] = '0';
4912 }
4913 } improvement_iterate_end;
4914 lost[improvement_count()] = '\0';
4915 secfile_insert_str(saving->file, lost,
4916 "player%d.lost_wonders", plrno);
4917 }
4918
4919 secfile_insert_int(saving->file, plr->history,
4920 "player%d.history", plrno);
4921 secfile_insert_int(saving->file, plr->server.huts,
4922 "player%d.hut_count", plrno);
4923
4924 secfile_insert_bool(saving->file, plr->server.border_vision,
4925 "player%d.border_vision", plrno);
4926
4927 if (saving->scenario) {
4928 if (plr->autoselect_weight < 0) { /* Apply default behavior */
4929 int def = 1; /* We want users to get a player in a scenario */
4930
4931 if (player_has_flag(plr, PLRF_SCENARIO_RESERVED)) {
4932 /* This isn't usable player */
4933 def = 0;
4934 }
4935
4936 secfile_insert_int(saving->file, def,
4937 "player%d.autoselect_weight", plrno);
4938 } else {
4939 secfile_insert_int(saving->file, plr->autoselect_weight,
4940 "player%d.autoselect_weight", plrno);
4941 }
4942 }
4943}
4944
4945/************************************************************************/
4948 static void sg_load_player_cities(struct loaddata *loading,
4949 struct player *plr)
4950{
4951 int ncities, i, plrno = player_number(plr);
4952 bool tasks_handled;
4953 int wlist_max_length, routes_max;
4954
4955 /* Check status and return if not OK (sg_success FALSE). */
4956 sg_check_ret();
4957
4958 sg_failure_ret(secfile_lookup_int(loading->file, &ncities,
4959 "player%d.ncities", plrno),
4960 "%s", secfile_error());
4961
4962 if (!plr->is_alive && ncities > 0) {
4963 log_sg("'player%d.ncities' = %d for dead player!", plrno, ncities);
4964 ncities = 0;
4965 }
4966
4967 wlist_max_length = secfile_lookup_int_default(loading->file, 0,
4968 "player%d.wl_max_length",
4969 plrno);
4970 routes_max = secfile_lookup_int_default(loading->file, 0,
4971 "player%d.routes_max_length", plrno);
4972
4973 /* Load all cities of the player. */
4974 for (i = 0; i < ncities; i++) {
4975 char buf[32];
4976 struct city *pcity;
4977
4978 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
4979
4980 /* Create a dummy city. */
4981 pcity = create_city_virtual(plr, NULL, buf);
4982 adv_city_alloc(pcity);
4983 if (!sg_load_player_city(loading, plr, pcity, buf,
4984 wlist_max_length, routes_max)) {
4985 adv_city_free(pcity);
4986 destroy_city_virtual(pcity);
4987 sg_failure_ret(FALSE, "Error loading city %d of player %d.", i, plrno);
4988 }
4989
4990 identity_number_reserve(pcity->id);
4991 idex_register_city(&wld, pcity);
4992
4993 /* Load the information about the nationality of citizens. This is done
4994 * here because the city sanity check called by citizens_update() requires
4995 * that the city is registered. */
4996 sg_load_player_city_citizens(loading, plr, pcity, buf);
4997
4998 /* After everything is loaded, but before vision. */
4999 map_claim_ownership(city_tile(pcity), plr, city_tile(pcity), TRUE);
5000
5001 /* adding the city contribution to fog-of-war */
5002 pcity->server.vision = vision_new(plr, city_tile(pcity));
5003 vision_reveal_tiles(pcity->server.vision, game.server.vision_reveal_tiles);
5004 city_refresh_vision(pcity);
5005
5006 city_list_append(plr->cities, pcity);
5007 }
5008
5009 tasks_handled = FALSE;
5010 for (i = 0; !tasks_handled; i++) {
5011 int city_id;
5012 struct city *pcity = NULL;
5013
5014 city_id = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.city",
5015 plrno, i);
5016
5017 if (city_id != -1) {
5018 pcity = player_city_by_number(plr, city_id);
5019 }
5020
5021 if (pcity != NULL) {
5022 const char *str;
5023 int nat_x, nat_y;
5024 struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
5025
5026 nat_x = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.x", plrno, i);
5027 nat_y = secfile_lookup_int_default(loading->file, -1, "player%d.task%d.y", plrno, i);
5028
5029 ptask->ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5030
5031 str = secfile_lookup_str(loading->file, "player%d.task%d.activity", plrno, i);
5032 ptask->act = unit_activity_by_name(str, fc_strcasecmp);
5033
5034 sg_failure_ret(unit_activity_is_valid(ptask->act),
5035 "Unknown workertask activity %s", str);
5036
5037 str = secfile_lookup_str(loading->file, "player%d.task%d.target", plrno, i);
5038
5039 if (strcmp("-", str)) {
5040 ptask->tgt = extra_type_by_rule_name(str);
5041
5042 sg_failure_ret(ptask->tgt != NULL,
5043 "Unknown workertask target %s", str);
5044 } else {
5045 ptask->tgt = NULL;
5046
5047 if (ptask->act == ACTIVITY_IRRIGATE) {
5048 ptask->act = ACTIVITY_CULTIVATE;
5049 } else if (ptask->act == ACTIVITY_MINE) {
5050 ptask->act = ACTIVITY_MINE;
5051 }
5052 }
5053
5054 ptask->want = secfile_lookup_int_default(loading->file, 1,
5055 "player%d.task%d.want", plrno, i);
5056
5057 worker_task_list_append(pcity->task_reqs, ptask);
5058 } else {
5059 tasks_handled = TRUE;
5060 }
5061 }
5062}
5063
5064/************************************************************************/
5067 static bool sg_load_player_city(struct loaddata *loading, struct player *plr,
5068 struct city *pcity, const char *citystr,
5069 int wlist_max_length, int routes_max)
5070{
5071 struct player *past;
5072 const char *kind, *name, *str;
5073 int id, i, repair, sp_count = 0, workers = 0, value;
5074 int nat_x, nat_y;
5075 citizens size;
5076 const char *stylename;
5077 int partner;
5078 int want;
5079 int tmp_int;
5080 const struct civ_map *nmap = &(wld.map);
5081
5082 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x", citystr),
5083 FALSE, "%s", secfile_error());
5084 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y", citystr),
5085 FALSE, "%s", secfile_error());
5086 pcity->tile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
5087 sg_warn_ret_val(NULL != pcity->tile, FALSE,
5088 "%s has invalid center tile (%d, %d)",
5089 citystr, nat_x, nat_y);
5090 sg_warn_ret_val(NULL == tile_city(pcity->tile), FALSE,
5091 "%s duplicates city (%d, %d)", citystr, nat_x, nat_y);
5092
5093 /* Instead of dying, use 'citystr' string for damaged name. */
5094 city_name_set(pcity, secfile_lookup_str_default(loading->file, citystr,
5095 "%s.name", citystr));
5096
5097 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->id, "%s.id",
5098 citystr), FALSE, "%s", secfile_error());
5099
5100 id = secfile_lookup_int_default(loading->file, player_number(plr),
5101 "%s.original", citystr);
5102 past = player_by_number(id);
5103 if (NULL != past) {
5104 pcity->original = past;
5105 }
5106
5107 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.size",
5108 citystr), FALSE, "%s", secfile_error());
5109 size = (citizens)value; /* set the correct type */
5110 sg_warn_ret_val(value == (int)size, FALSE,
5111 "Invalid city size: %d, set to %d", value, size);
5112 city_size_set(pcity, size);
5113
5114 for (i = 0; i < loading->specialist.size; i++) {
5115 sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
5116 citystr, i),
5117 FALSE, "%s", secfile_error());
5118 pcity->specialists[specialist_index(loading->specialist.order[i])]
5119 = (citizens)value;
5120 sp_count += value;
5121 }
5122
5123 partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
5124 for (i = 0; partner != 0; i++) {
5125 struct trade_route *proute = fc_malloc(sizeof(struct trade_route));
5126 const char *dir;
5127 const char *good_str;
5128
5129 /* Append to routes list immediately, so the pointer can be found for freeing
5130 * even if we abort */
5131 trade_route_list_append(pcity->routes, proute);
5132
5133 proute->partner = partner;
5134 dir = secfile_lookup_str(loading->file, "%s.route_direction%d", citystr, i);
5135 sg_warn_ret_val(dir != NULL, FALSE,
5136 "No traderoute direction found for %s", citystr);
5137 proute->dir = route_direction_by_name(dir, fc_strcasecmp);
5138 sg_warn_ret_val(route_direction_is_valid(proute->dir), FALSE,
5139 "Illegal route direction %s", dir);
5140 good_str = secfile_lookup_str(loading->file, "%s.route_good%d", citystr, i);
5141 sg_warn_ret_val(dir != NULL, FALSE,
5142 "No good found for %s", citystr);
5143 proute->goods = goods_by_rule_name(good_str);
5144 sg_warn_ret_val(proute->goods != NULL, FALSE,
5145 "Illegal good %s", good_str);
5146
5147 /* Next one */
5148 partner = secfile_lookup_int_default(loading->file, 0,
5149 "%s.traderoute%d", citystr, i + 1);
5150 }
5151
5152 for (; i < routes_max; i++) {
5153 (void) secfile_entry_lookup(loading->file, "%s.traderoute%d", citystr, i);
5154 (void) secfile_entry_lookup(loading->file, "%s.route_direction%d", citystr, i);
5155 (void) secfile_entry_lookup(loading->file, "%s.route_good%d", citystr, i);
5156 }
5157
5158 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->food_stock,
5159 "%s.food_stock", citystr),
5160 FALSE, "%s", secfile_error());
5161 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->shield_stock,
5162 "%s.shield_stock", citystr),
5163 FALSE, "%s", secfile_error());
5164 pcity->history =
5165 secfile_lookup_int_default(loading->file, 0, "%s.history", citystr);
5166
5167 pcity->airlift =
5168 secfile_lookup_int_default(loading->file, 0, "%s.airlift", citystr);
5169 pcity->was_happy =
5170 secfile_lookup_bool_default(loading->file, FALSE, "%s.was_happy",
5171 citystr);
5172 pcity->had_famine =
5173 secfile_lookup_bool_default(loading->file, FALSE, "%s.had_famine",
5174 citystr);
5175
5176 pcity->turn_plague =
5177 secfile_lookup_int_default(loading->file, 0, "%s.turn_plague", citystr);
5178
5179 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->anarchy,
5180 "%s.anarchy", citystr),
5181 FALSE, "%s", secfile_error());
5182 pcity->rapture =
5183 secfile_lookup_int_default(loading->file, 0, "%s.rapture", citystr);
5184 pcity->steal =
5185 secfile_lookup_int_default(loading->file, 0, "%s.steal", citystr);
5186
5187 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_founded,
5188 "%s.turn_founded", citystr),
5189 FALSE, "%s", secfile_error());
5190 sg_warn_ret_val(secfile_lookup_int(loading->file, &tmp_int,
5191 "%s.acquire_t", citystr),
5192 FALSE, "%s", secfile_error());
5193 pcity->acquire_t = tmp_int;
5194 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_buy, "%s.did_buy",
5195 citystr), FALSE, "%s", secfile_error());
5196 sg_warn_ret_val(secfile_lookup_bool(loading->file, &pcity->did_sell, "%s.did_sell",
5197 citystr), FALSE, "%s", secfile_error());
5198
5199 sg_warn_ret_val(secfile_lookup_int(loading->file, &pcity->turn_last_built,
5200 "%s.turn_last_built", citystr),
5201 FALSE, "%s", secfile_error());
5202
5203 kind = secfile_lookup_str(loading->file, "%s.currently_building_kind",
5204 citystr);
5205 name = secfile_lookup_str(loading->file, "%s.currently_building_name",
5206 citystr);
5207 pcity->production = universal_by_rule_name(kind, name);
5208 sg_warn_ret_val(pcity->production.kind != universals_n_invalid(), FALSE,
5209 "%s.currently_building: unknown \"%s\" \"%s\".",
5210 citystr, kind, name);
5211
5212 want = secfile_lookup_int_default(loading->file, 0,
5213 "%s.current_want", citystr);
5214 if (pcity->production.kind == VUT_IMPROVEMENT) {
5215 pcity->server.adv->
5216 building_want[improvement_index(pcity->production.value.building)]
5217 = want;
5218 }
5219
5220 kind = secfile_lookup_str(loading->file, "%s.changed_from_kind",
5221 citystr);
5222 name = secfile_lookup_str(loading->file, "%s.changed_from_name",
5223 citystr);
5224 pcity->changed_from = universal_by_rule_name(kind, name);
5225 sg_warn_ret_val(pcity->changed_from.kind != universals_n_invalid(), FALSE,
5226 "%s.changed_from: unknown \"%s\" \"%s\".",
5227 citystr, kind, name);
5228
5229 pcity->before_change_shields =
5230 secfile_lookup_int_default(loading->file, pcity->shield_stock,
5231 "%s.before_change_shields", citystr);
5232 pcity->caravan_shields =
5233 secfile_lookup_int_default(loading->file, 0,
5234 "%s.caravan_shields", citystr);
5235 pcity->disbanded_shields =
5236 secfile_lookup_int_default(loading->file, 0,
5237 "%s.disbanded_shields", citystr);
5238 pcity->last_turns_shield_surplus =
5239 secfile_lookup_int_default(loading->file, 0,
5240 "%s.last_turns_shield_surplus",
5241 citystr);
5242
5243 stylename = secfile_lookup_str_default(loading->file, NULL,
5244 "%s.style", citystr);
5245 if (stylename != NULL) {
5246 pcity->style = city_style_by_rule_name(stylename);
5247 } else {
5248 pcity->style = 0;
5249 }
5250 if (pcity->style < 0) {
5251 pcity->style = city_style(pcity);
5252 }
5253
5254 pcity->server.synced = FALSE; /* Must re-sync with clients */
5255
5256 /* Initialise list of city improvements. */
5257 for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
5258 pcity->built[i].turn = I_NEVER;
5259 }
5260
5261 /* Load city improvements. */
5262 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
5263 sg_warn_ret_val(str != NULL, FALSE, "%s", secfile_error());
5264 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
5265 "Invalid length of '%s.improvements' ("
5266 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
5267 citystr, strlen(str), loading->improvement.size);
5268 for (i = 0; i < loading->improvement.size; i++) {
5269 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
5270 "Undefined value '%c' within '%s.improvements'.",
5271 str[i], citystr)
5272
5273 if (str[i] == '1') {
5274 struct impr_type *pimprove
5275 = improvement_by_rule_name(loading->improvement.order[i]);
5276
5277 if (pimprove) {
5278 city_add_improvement(pcity, pimprove);
5279 }
5280 }
5281 }
5282
5283 sg_failure_ret_val(loading->worked_tiles != NULL, FALSE,
5284 "No worked tiles map defined.");
5285
5286 city_freeze_workers(pcity);
5287
5288 /* Load new savegame with variable (squared) city radius and worked
5289 * tiles map */
5290
5291 int radius_sq
5292 = secfile_lookup_int_default(loading->file, -1, "%s.city_radius_sq",
5293 citystr);
5294 city_map_radius_sq_set(pcity, radius_sq);
5295
5296 city_tile_iterate(nmap, CITY_MAP_MAX_RADIUS_SQ, city_tile(pcity), ptile) {
5297 if (loading->worked_tiles[ptile->index] == pcity->id) {
5298 if (sq_map_distance(ptile, pcity->tile) > radius_sq) {
5299 log_sg("[%s] '%s' (%d, %d) has worker outside current radius "
5300 "at (%d, %d); repairing", citystr, city_name_get(pcity),
5301 TILE_XY(pcity->tile), TILE_XY(ptile));
5302 pcity->specialists[DEFAULT_SPECIALIST]++;
5303 sp_count++;
5304 } else {
5305 tile_set_worked(ptile, pcity);
5306 workers++;
5307 }
5308
5309#ifdef FREECIV_DEBUG
5310 /* Set this tile to unused; a check for not resetted tiles is
5311 * included in game_load_internal() */
5312 loading->worked_tiles[ptile->index] = -1;
5313#endif /* FREECIV_DEBUG */
5314 }
5315 } city_tile_iterate_end;
5316
5317 if (tile_worked(city_tile(pcity)) != pcity) {
5318 struct city *pwork = tile_worked(city_tile(pcity));
5319
5320 if (NULL != pwork) {
5321 log_sg("[%s] city center of '%s' (%d,%d) [%d] is worked by '%s' "
5322 "(%d,%d) [%d]; repairing", citystr, city_name_get(pcity),
5323 TILE_XY(city_tile(pcity)), city_size_get(pcity), city_name_get(pwork),
5324 TILE_XY(city_tile(pwork)), city_size_get(pwork));
5325
5326 tile_set_worked(city_tile(pcity), NULL); /* Remove tile from pwork */
5327 pwork->specialists[DEFAULT_SPECIALIST]++;
5328 auto_arrange_workers(pwork);
5329 } else {
5330 log_sg("[%s] city center of '%s' (%d,%d) [%d] is empty; repairing",
5331 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)),
5332 city_size_get(pcity));
5333 }
5334
5335 /* Repair pcity */
5336 tile_set_worked(city_tile(pcity), pcity);
5337 city_repair_size(pcity, -1);
5338 }
5339
5340 repair = city_size_get(pcity) - sp_count - (workers - FREE_WORKED_TILES);
5341 if (0 != repair) {
5342 log_sg("[%s] size mismatch for '%s' (%d,%d): size [%d] != "
5343 "(workers [%d] - free worked tiles [%d]) + specialists [%d]",
5344 citystr, city_name_get(pcity), TILE_XY(city_tile(pcity)), city_size_get(pcity),
5345 workers, FREE_WORKED_TILES, sp_count);
5346
5347 /* Repair pcity */
5348 city_repair_size(pcity, repair);
5349 }
5350
5351 /* worklist_init() done in create_city_virtual() */
5352 worklist_load(loading->file, wlist_max_length, &pcity->worklist, "%s", citystr);
5353
5354 /* Load city options. */
5355 BV_CLR_ALL(pcity->city_options);
5356 for (i = 0; i < loading->coptions.size; i++) {
5357 if (secfile_lookup_bool_default(loading->file, FALSE, "%s.option%d",
5358 citystr, i)) {
5359 BV_SET(pcity->city_options, loading->coptions.order[i]);
5360 }
5361 }
5362 sg_warn_ret_val(secfile_lookup_int(loading->file, &tmp_int,
5363 "%s.wlcb", citystr),
5364 FALSE, "%s", secfile_error());
5365 pcity->wlcb = tmp_int;
5366
5367 /* Load the city rally point. */
5368 {
5369 int len = secfile_lookup_int_default(loading->file, 0,
5370 "%s.rally_point_length", citystr);
5371 int unconverted;
5372
5373 pcity->rally_point.length = len;
5374 if (len > 0) {
5375 const char *rally_orders, *rally_dirs, *rally_activities;
5376
5377 pcity->rally_point.orders
5378 = fc_malloc(len * sizeof(*(pcity->rally_point.orders)));
5379 pcity->rally_point.persistent
5380 = secfile_lookup_bool_default(loading->file, FALSE,
5381 "%s.rally_point_persistent", citystr);
5382 pcity->rally_point.vigilant
5383 = secfile_lookup_bool_default(loading->file, FALSE,
5384 "%s.rally_point_vigilant", citystr);
5385
5386 rally_orders
5387 = secfile_lookup_str_default(loading->file, "",
5388 "%s.rally_point_orders", citystr);
5389 rally_dirs
5390 = secfile_lookup_str_default(loading->file, "",
5391 "%s.rally_point_dirs", citystr);
5392 rally_activities
5393 = secfile_lookup_str_default(loading->file, "",
5394 "%s.rally_point_activities", citystr);
5395
5396 for (i = 0; i < len; i++) {
5397 struct unit_order *order = &pcity->rally_point.orders[i];
5398
5399 if (rally_orders[i] == '\0' || rally_dirs[i] == '\0'
5400 || rally_activities[i] == '\0') {
5401 log_sg("Invalid rally point.");
5402 free(pcity->rally_point.orders);
5403 pcity->rally_point.orders = NULL;
5404 pcity->rally_point.length = 0;
5405 break;
5406 }
5407 order->order = char2order(rally_orders[i]);
5408 order->dir = char2dir(rally_dirs[i]);
5409 order->activity = char2activity(rally_activities[i]);
5410
5411 unconverted = secfile_lookup_int_default(loading->file, ACTION_NONE,
5412 "%s.rally_point_action_vec,%d",
5413 citystr, i);
5414
5415 if (unconverted >= 0 && unconverted < loading-> action.size) {
5416 /* Look up what action id the unconverted number represents. */
5417 order->action = loading->action.order[unconverted];
5418 } else {
5419 if (order->order == ORDER_PERFORM_ACTION) {
5420 log_sg("Invalid action id in order for city rally point %d",
5421 pcity->id);
5422 }
5423
5424 order->action = ACTION_NONE;
5425 }
5426
5427 order->target
5428 = secfile_lookup_int_default(loading->file, NO_TARGET,
5429 "%s.rally_point_tgt_vec,%d",
5430 citystr, i);
5431 order->sub_target
5432 = secfile_lookup_int_default(loading->file, -1,
5433 "%s.rally_point_sub_tgt_vec,%d",
5434 citystr, i);
5435 }
5436 } else {
5437 pcity->rally_point.orders = NULL;
5438
5439 (void) secfile_entry_lookup(loading->file, "%s.rally_point_persistent",
5440 citystr);
5441 (void) secfile_entry_lookup(loading->file, "%s.rally_point_vigilant",
5442 citystr);
5443 (void) secfile_entry_lookup(loading->file, "%s.rally_point_orders",
5444 citystr);
5445 (void) secfile_entry_lookup(loading->file, "%s.rally_point_dirs",
5446 citystr);
5447 (void) secfile_entry_lookup(loading->file, "%s.rally_point_activities",
5448 citystr);
5449 (void) secfile_entry_lookup(loading->file, "%s.rally_point_action_vec",
5450 citystr);
5451 (void) secfile_entry_lookup(loading->file,
5452 "%s.rally_point_tgt_vec", citystr);
5453 (void) secfile_entry_lookup(loading->file,
5454 "%s.rally_point_sub_tgt_vec", citystr);
5455 }
5456 }
5457
5458 /* Load the city manager parameters. */
5459 {
5460 bool enabled = secfile_lookup_bool_default(loading->file, FALSE,
5461 "%s.cma_enabled", citystr);
5462 if (enabled) {
5463 struct cm_parameter *param = fc_calloc(1, sizeof(struct cm_parameter));
5464
5465 for (i = 0; i < O_LAST; i++) {
5466 param->minimal_surplus[i] = secfile_lookup_int_default(
5467 loading->file, 0, "%s.cma_minimal_surplus,%d", citystr, i);
5468 param->factor[i] = secfile_lookup_int_default(
5469 loading->file, 0, "%s.cma_factor,%d", citystr, i);
5470 }
5471
5472 param->max_growth = secfile_lookup_bool_default(
5473 loading->file, FALSE, "%s.max_growth", citystr);
5474 param->require_happy = secfile_lookup_bool_default(
5475 loading->file, FALSE, "%s.require_happy", citystr);
5476 param->allow_disorder = secfile_lookup_bool_default(
5477 loading->file, FALSE, "%s.allow_disorder", citystr);
5478 param->allow_specialists = secfile_lookup_bool_default(
5479 loading->file, FALSE, "%s.allow_specialists", citystr);
5480 param->happy_factor = secfile_lookup_int_default(
5481 loading->file, 0, "%s.happy_factor", citystr);
5482 pcity->cm_parameter = param;
5483 } else {
5484 pcity->cm_parameter = NULL;
5485
5486 for (i = 0; i < O_LAST; i++) {
5487 (void) secfile_entry_lookup(loading->file,
5488 "%s.cma_minimal_surplus,%d", citystr, i);
5489 (void) secfile_entry_lookup(loading->file,
5490 "%s.cma_factor,%d", citystr, i);
5491 }
5492
5493 (void) secfile_entry_lookup(loading->file, "%s.max_growth",
5494 citystr);
5495 (void) secfile_entry_lookup(loading->file, "%s.require_happy",
5496 citystr);
5497 (void) secfile_entry_lookup(loading->file, "%s.allow_disorder",
5498 citystr);
5499 (void) secfile_entry_lookup(loading->file, "%s.allow_specialists",
5500 citystr);
5501 (void) secfile_entry_lookup(loading->file, "%s.happy_factor",
5502 citystr);
5503 }
5504 }
5505
5506 CALL_FUNC_EACH_AI(city_load, loading->file, pcity, citystr);
5507
5508 return TRUE;
5509}
5510
5511/************************************************************************/
5514 static void sg_load_player_city_citizens(struct loaddata *loading,
5515 struct player *plr,
5516 struct city *pcity,
5517 const char *citystr)
5518{
5519 if (game.info.citizen_nationality) {
5520 citizens size;
5521
5522 citizens_init(pcity);
5523 player_slots_iterate(pslot) {
5524 int nationality;
5525
5526 nationality = secfile_lookup_int_default(loading->file, -1,
5527 "%s.citizen%d", citystr,
5528 player_slot_index(pslot));
5529 if (nationality > 0 && !player_slot_is_used(pslot)) {
5530 log_sg("Citizens of an invalid nation for %s (player slot %d)!",
5531 city_name_get(pcity), player_slot_index(pslot));
5532 continue;
5533 }
5534
5535 if (nationality != -1 && player_slot_is_used(pslot)) {
5536 sg_warn(nationality >= 0 && nationality <= MAX_CITY_SIZE,
5537 "Invalid value for citizens of player %d in %s: %d.",
5538 player_slot_index(pslot), city_name_get(pcity), nationality);
5539 citizens_nation_set(pcity, pslot, nationality);
5540 }
5541 } player_slots_iterate_end;
5542 /* Sanity check. */
5543 size = citizens_count(pcity);
5544 if (size != city_size_get(pcity)) {
5545 if (size != 0) {
5546 /* size == 0 can be result from the fact that ruleset had no
5547 * nationality enabled at saving time, so no citizens at all
5548 * were saved. But something more serious must be going on if
5549 * citizens have been saved partially - if some of them are there. */
5550 log_sg("City size and number of citizens does not match in %s "
5551 "(%d != %d)! Repairing ...", city_name_get(pcity),
5552 city_size_get(pcity), size);
5553 }
5554 citizens_update(pcity, NULL);
5555 }
5556 }
5557}
5558
5559/************************************************************************/
5562 static void sg_save_player_cities(struct savedata *saving,
5563 struct player *plr)
5564{
5565 int wlist_max_length = 0, rally_point_max_length = 0, routes_max = 0;
5566 int i = 0;
5567 int plrno = player_number(plr);
5568 bool nations[MAX_NUM_PLAYER_SLOTS];
5569
5570 /* Check status and return if not OK (sg_success FALSE). */
5571 sg_check_ret();
5572
5573 secfile_insert_int(saving->file, city_list_size(plr->cities),
5574 "player%d.ncities", plrno);
5575
5576 if (game.info.citizen_nationality) {
5577 /* Initialise the nation list for the citizens information. */
5578 player_slots_iterate(pslot) {
5579 nations[player_slot_index(pslot)] = FALSE;
5580 } player_slots_iterate_end;
5581 }
5582
5583 /* First determine length of longest worklist, rally point order, and the
5584 * nationalities we have. */
5585 city_list_iterate(plr->cities, pcity) {
5586 int routes;
5587
5588 /* Check the sanity of the city. */
5589 city_refresh(pcity);
5590 sanity_check_city(pcity);
5591
5592 if (pcity->worklist.length > wlist_max_length) {
5593 wlist_max_length = pcity->worklist.length;
5594 }
5595
5596 if (pcity->rally_point.length > rally_point_max_length) {
5597 rally_point_max_length = pcity->rally_point.length;
5598 }
5599
5600 routes = city_num_trade_routes(pcity);
5601 if (routes > routes_max) {
5602 routes_max = routes;
5603 }
5604
5605 if (game.info.citizen_nationality) {
5606 /* Find all nations of the citizens,*/
5607 players_iterate(pplayer) {
5608 if (!nations[player_index(pplayer)]
5609 && citizens_nation_get(pcity, pplayer->slot) != 0) {
5610 nations[player_index(pplayer)] = TRUE;
5611 }
5612 } players_iterate_end;
5613 }
5614 } city_list_iterate_end;
5615
5616 secfile_insert_int(saving->file, wlist_max_length,
5617 "player%d.wl_max_length", plrno);
5618 secfile_insert_int(saving->file, routes_max,
5619 "player%d.routes_max_length", plrno);
5620
5621 city_list_iterate(plr->cities, pcity) {
5622 struct tile *pcenter = city_tile(pcity);
5623 char impr_buf[B_LAST + 1];
5624 char buf[32];
5625 int j, nat_x, nat_y;
5626
5627 fc_snprintf(buf, sizeof(buf), "player%d.c%d", plrno, i);
5628
5629
5630 index_to_native_pos(&nat_x, &nat_y, tile_index(pcenter));
5631 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
5632 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
5633
5634 secfile_insert_int(saving->file, pcity->id, "%s.id", buf);
5635
5636 if (pcity->original != NULL) {
5637 secfile_insert_int(saving->file, player_number(pcity->original),
5638 "%s.original", buf);
5639 } else {
5640 secfile_insert_int(saving->file, -1, "%s.original", buf);
5641 }
5642 secfile_insert_int(saving->file, city_size_get(pcity), "%s.size", buf);
5643
5644 j = 0;
5645 specialist_type_iterate(sp) {
5646 secfile_insert_int(saving->file, pcity->specialists[sp], "%s.nspe%d",
5647 buf, j++);
5648 } specialist_type_iterate_end;
5649
5650 j = 0;
5651 trade_routes_iterate(pcity, proute) {
5652 secfile_insert_int(saving->file, proute->partner, "%s.traderoute%d",
5653 buf, j);
5654 secfile_insert_str(saving->file, route_direction_name(proute->dir),
5655 "%s.route_direction%d", buf, j);
5656 secfile_insert_str(saving->file, goods_rule_name(proute->goods),
5657 "%s.route_good%d", buf, j);
5658 j++;
5659 } trade_routes_iterate_end;
5660
5661 /* Save dummy values to keep tabular format happy */
5662 for (; j < routes_max; j++) {
5663 secfile_insert_int(saving->file, 0, "%s.traderoute%d", buf, j);
5664 secfile_insert_str(saving->file, route_direction_name(RDIR_BIDIRECTIONAL),
5665 "%s.route_direction%d", buf, j);
5666 secfile_insert_str(saving->file, goods_rule_name(goods_by_number(0)),
5667 "%s.route_good%d", buf, j);
5668 }
5669
5670 secfile_insert_int(saving->file, pcity->food_stock, "%s.food_stock",
5671 buf);
5672 secfile_insert_int(saving->file, pcity->shield_stock, "%s.shield_stock",
5673 buf);
5674 secfile_insert_int(saving->file, pcity->history, "%s.history",
5675 buf);
5676
5677 secfile_insert_int(saving->file, pcity->airlift, "%s.airlift",
5678 buf);
5679 secfile_insert_bool(saving->file, pcity->was_happy, "%s.was_happy",
5680 buf);
5681 secfile_insert_bool(saving->file, pcity->had_famine, "%s.had_famine",
5682 buf);
5683 secfile_insert_int(saving->file, pcity->turn_plague, "%s.turn_plague",
5684 buf);
5685
5686 secfile_insert_int(saving->file, pcity->anarchy, "%s.anarchy", buf);
5687 secfile_insert_int(saving->file, pcity->rapture, "%s.rapture", buf);
5688 secfile_insert_int(saving->file, pcity->steal, "%s.steal", buf);
5689 secfile_insert_int(saving->file, pcity->turn_founded, "%s.turn_founded",
5690 buf);
5691 secfile_insert_int(saving->file, pcity->acquire_t, "%s.acquire_t", buf);
5692 secfile_insert_bool(saving->file, pcity->did_buy, "%s.did_buy", buf);
5693 secfile_insert_bool(saving->file, pcity->did_sell, "%s.did_sell", buf);
5694 secfile_insert_int(saving->file, pcity->turn_last_built,
5695 "%s.turn_last_built", buf);
5696
5697 /* For visual debugging, variable length strings together here */
5698 secfile_insert_str(saving->file, city_name_get(pcity), "%s.name", buf);
5699
5700 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->production),
5701 "%s.currently_building_kind", buf);
5702 secfile_insert_str(saving->file, universal_rule_name(&pcity->production),
5703 "%s.currently_building_name", buf);
5704
5705 if (pcity->production.kind == VUT_IMPROVEMENT) {
5706 secfile_insert_int(saving->file,
5707 pcity->server.adv->
5708 building_want[improvement_index(pcity->production.value.building)],
5709 "%s.current_want", buf);
5710 } else {
5711 secfile_insert_int(saving->file, 0,
5712 "%s.current_want", buf);
5713 }
5714
5715 secfile_insert_str(saving->file, universal_type_rule_name(&pcity->changed_from),
5716 "%s.changed_from_kind", buf);
5717 secfile_insert_str(saving->file, universal_rule_name(&pcity->changed_from),
5718 "%s.changed_from_name", buf);
5719
5720 secfile_insert_int(saving->file, pcity->before_change_shields,
5721 "%s.before_change_shields", buf);
5722 secfile_insert_int(saving->file, pcity->caravan_shields,
5723 "%s.caravan_shields", buf);
5724 secfile_insert_int(saving->file, pcity->disbanded_shields,
5725 "%s.disbanded_shields", buf);
5726 secfile_insert_int(saving->file, pcity->last_turns_shield_surplus,
5727 "%s.last_turns_shield_surplus", buf);
5728
5729 secfile_insert_str(saving->file, city_style_rule_name(pcity->style),
5730 "%s.style", buf);
5731
5732 /* Save the squared city radius and all tiles within the corresponing
5733 * city map. */
5734 secfile_insert_int(saving->file, pcity->city_radius_sq,
5735 "player%d.c%d.city_radius_sq", plrno, i);
5736 /* The tiles worked by the city are saved using the main map.
5737 * See also sg_save_map_worked(). */
5738
5739 /* Save improvement list as bytevector. Note that improvement order
5740 * is saved in savefile.improvement_order. */
5741 improvement_iterate(pimprove) {
5742 impr_buf[improvement_index(pimprove)]
5743 = (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) ? '0'
5744 : '1';
5745 } improvement_iterate_end;
5746 impr_buf[improvement_count()] = '\0';
5747
5748 sg_failure_ret(strlen(impr_buf) < sizeof(impr_buf),
5749 "Invalid size of the improvement vector (%s.improvements: "
5750 SIZE_T_PRINTF " < " SIZE_T_PRINTF ").", buf,
5751 strlen(impr_buf), sizeof(impr_buf));
5752 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
5753
5754 worklist_save(saving->file, &pcity->worklist, wlist_max_length, "%s",
5755 buf);
5756
5757 for (j = 0; j < CITYO_LAST; j++) {
5758 secfile_insert_bool(saving->file, BV_ISSET(pcity->city_options, j),
5759 "%s.option%d", buf, j);
5760 }
5761 secfile_insert_int(saving->file, pcity->wlcb,
5762 "%s.wlcb", buf);
5763
5764 CALL_FUNC_EACH_AI(city_save, saving->file, pcity, buf);
5765
5766 if (game.info.citizen_nationality) {
5767 /* Save nationality of the citizens,*/
5768 players_iterate(pplayer) {
5769 if (nations[player_index(pplayer)]) {
5770 secfile_insert_int(saving->file,
5771 citizens_nation_get(pcity, pplayer->slot),
5772 "%s.citizen%d", buf, player_index(pplayer));
5773 }
5774 } players_iterate_end;
5775 }
5776
5777 secfile_insert_int(saving->file, pcity->rally_point.length,
5778 "%s.rally_point_length", buf);
5779 if (pcity->rally_point.length) {
5780 int len = pcity->rally_point.length;
5781 char orders[len + 1], dirs[len + 1], activities[len + 1];
5782 int actions[len];
5783 int targets[len];
5784 int sub_targets[len];
5785
5786 secfile_insert_bool(saving->file, pcity->rally_point.persistent,
5787 "%s.rally_point_persistent", buf);
5788 secfile_insert_bool(saving->file, pcity->rally_point.vigilant,
5789 "%s.rally_point_vigilant", buf);
5790
5791 for (j = 0; j < len; j++) {
5792 orders[j] = order2char(pcity->rally_point.orders[j].order);
5793 dirs[j] = '?';
5794 activities[j] = '?';
5795 targets[j] = NO_TARGET;
5796 sub_targets[j] = NO_TARGET;
5797 actions[j] = -1;
5798 switch (pcity->rally_point.orders[j].order) {
5799 case ORDER_MOVE:
5800 case ORDER_ACTION_MOVE:
5801 dirs[j] = dir2char(pcity->rally_point.orders[j].dir);
5802 break;
5803 case ORDER_ACTIVITY:
5804 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5805 activities[j]
5806 = activity2char(pcity->rally_point.orders[j].activity);
5807 break;
5808 case ORDER_PERFORM_ACTION:
5809 actions[j] = pcity->rally_point.orders[j].action;
5810 targets[j] = pcity->rally_point.orders[j].target;
5811 sub_targets[j] = pcity->rally_point.orders[j].sub_target;
5812 break;
5813 case ORDER_FULL_MP:
5814 case ORDER_LAST:
5815 break;
5816 }
5817 }
5818 orders[len] = dirs[len] = activities[len] = '\0';
5819
5820 secfile_insert_str(saving->file, orders, "%s.rally_point_orders", buf);
5821 secfile_insert_str(saving->file, dirs, "%s.rally_point_dirs", buf);
5822 secfile_insert_str(saving->file, activities,
5823 "%s.rally_point_activities", buf);
5824
5825 secfile_insert_int_vec(saving->file, actions, len,
5826 "%s.rally_point_action_vec", buf);
5827 /* Fill in dummy values for order targets so the registry will save
5828 * the unit table in a tabular format. */
5829 for (j = len; j < rally_point_max_length; j++) {
5830 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5831 buf, j);
5832 }
5833
5834 secfile_insert_int_vec(saving->file, targets, len,
5835 "%s.rally_point_tgt_vec", buf);
5836 /* Fill in dummy values for order targets so the registry will save
5837 * the unit table in a tabular format. */
5838 for (j = len; j < rally_point_max_length; j++) {
5839 secfile_insert_int(saving->file, NO_TARGET,
5840 "%s.rally_point_tgt_vec,%d", buf, j);
5841 }
5842
5843 secfile_insert_int_vec(saving->file, sub_targets, len,
5844 "%s.rally_point_sub_tgt_vec", buf);
5845 /* Fill in dummy values for order targets so the registry will save
5846 * the unit table in a tabular format. */
5847 for (j = len; j < rally_point_max_length; j++) {
5848 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5849 buf, j);
5850 }
5851 } else {
5852 /* Put all the same fields into the savegame - otherwise the
5853 * registry code can't correctly use a tabular format and the
5854 * savegame will be bigger. */
5855 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_persistent",
5856 buf);
5857 secfile_insert_bool(saving->file, FALSE, "%s.rally_point_vigilant",
5858 buf);
5859 secfile_insert_str(saving->file, "-", "%s.rally_point_orders", buf);
5860 secfile_insert_str(saving->file, "-", "%s.rally_point_dirs", buf);
5861 secfile_insert_str(saving->file, "-", "%s.rally_point_activities",
5862 buf);
5863
5864 /* Fill in dummy values for order targets so the registry will save
5865 * the unit table in a tabular format. */
5866
5867 /* The start of a vector has no number. */
5868 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec",
5869 buf);
5870 for (j = 1; j < rally_point_max_length; j++) {
5871 secfile_insert_int(saving->file, -1, "%s.rally_point_action_vec,%d",
5872 buf, j);
5873 }
5874
5875 /* The start of a vector has no number. */
5876 secfile_insert_int(saving->file, NO_TARGET, "%s.rally_point_tgt_vec",
5877 buf);
5878 for (j = 1; j < rally_point_max_length; j++) {
5879 secfile_insert_int(saving->file, NO_TARGET,
5880 "%s.rally_point_tgt_vec,%d", buf, j);
5881 }
5882
5883 /* The start of a vector has no number. */
5884 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec",
5885 buf);
5886 for (j = 1; j < rally_point_max_length; j++) {
5887 secfile_insert_int(saving->file, -1, "%s.rally_point_sub_tgt_vec,%d",
5888 buf, j);
5889 }
5890 }
5891
5892 secfile_insert_bool(saving->file, pcity->cm_parameter != NULL,
5893 "%s.cma_enabled", buf);
5894 if (pcity->cm_parameter) {
5895 secfile_insert_int_vec(saving->file,
5896 pcity->cm_parameter->minimal_surplus, O_LAST,
5897 "%s.cma_minimal_surplus", buf);
5898 secfile_insert_int_vec(saving->file,
5899 pcity->cm_parameter->factor, O_LAST,
5900 "%s.cma_factor", buf);
5901 secfile_insert_bool(saving->file, pcity->cm_parameter->max_growth,
5902 "%s.max_growth", buf);
5903 secfile_insert_bool(saving->file, pcity->cm_parameter->require_happy,
5904 "%s.require_happy", buf);
5905 secfile_insert_bool(saving->file, pcity->cm_parameter->allow_disorder,
5906 "%s.allow_disorder", buf);
5907 secfile_insert_bool(saving->file,
5908 pcity->cm_parameter->allow_specialists,
5909 "%s.allow_specialists", buf);
5910 secfile_insert_int(saving->file, pcity->cm_parameter->happy_factor,
5911 "%s.happy_factor", buf);
5912 } else {
5913 int zeros[O_LAST];
5914
5915 memset(zeros, 0, sizeof(zeros));
5916 secfile_insert_int_vec(saving->file, zeros, O_LAST,
5917 "%s.cma_minimal_surplus", buf);
5918 secfile_insert_int_vec(saving->file, zeros, O_LAST,
5919 "%s.cma_factor", buf);
5920 secfile_insert_bool(saving->file, FALSE, "%s.max_growth", buf);
5921 secfile_insert_bool(saving->file, FALSE, "%s.require_happy", buf);
5922 secfile_insert_bool(saving->file, FALSE, "%s.allow_disorder", buf);
5923 secfile_insert_bool(saving->file, FALSE, "%s.allow_specialists", buf);
5924 secfile_insert_int(saving->file, 0, "%s.happy_factor", buf);
5925 }
5926
5927 i++;
5928 } city_list_iterate_end;
5929
5930 i = 0;
5931 city_list_iterate(plr->cities, pcity) {
5932 worker_task_list_iterate(pcity->task_reqs, ptask) {
5933 int nat_x, nat_y;
5934
5935 index_to_native_pos(&nat_x, &nat_y, tile_index(ptask->ptile));
5936 secfile_insert_int(saving->file, pcity->id, "player%d.task%d.city",
5937 plrno, i);
5938 secfile_insert_int(saving->file, nat_y, "player%d.task%d.y", plrno, i);
5939 secfile_insert_int(saving->file, nat_x, "player%d.task%d.x", plrno, i);
5940 secfile_insert_str(saving->file, unit_activity_name(ptask->act),
5941 "player%d.task%d.activity",
5942 plrno, i);
5943 if (ptask->tgt != NULL) {
5944 secfile_insert_str(saving->file, extra_rule_name(ptask->tgt),
5945 "player%d.task%d.target",
5946 plrno, i);
5947 } else {
5948 secfile_insert_str(saving->file, "-",
5949 "player%d.task%d.target",
5950 plrno, i);
5951 }
5952 secfile_insert_int(saving->file, ptask->want, "player%d.task%d.want", plrno, i);
5953
5954 i++;
5955 } worker_task_list_iterate_end;
5956 } city_list_iterate_end;
5957}
5958
5959/************************************************************************/
5962 static void sg_load_player_units(struct loaddata *loading,
5963 struct player *plr)
5964{
5965 int nunits, i, plrno = player_number(plr);
5966 size_t orders_max_length;
5967
5968 /* Check status and return if not OK (sg_success FALSE). */
5969 sg_check_ret();
5970
5971 sg_failure_ret(secfile_lookup_int(loading->file, &nunits,
5972 "player%d.nunits", plrno),
5973 "%s", secfile_error());
5974 if (!plr->is_alive && nunits > 0) {
5975 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
5976 nunits = 0; /* Some old savegames may be buggy. */
5977 }
5978
5979 orders_max_length = secfile_lookup_int_default(loading->file, 0,
5980 "player%d.orders_max_length",
5981 plrno);
5982
5983 for (i = 0; i < nunits; i++) {
5984 struct unit *punit;
5985 struct city *pcity;
5986 const char *name;
5987 char buf[32];
5988 struct unit_type *type;
5989 struct tile *ptile;
5990
5991 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
5992
5993 name = secfile_lookup_str(loading->file, "%s.type_by_name", buf);
5994 type = unit_type_by_rule_name(name);
5995 sg_failure_ret(type != NULL, "%s: unknown unit type \"%s\".", buf, name);
5996
5997 /* Create a dummy unit. */
5998 punit = unit_virtual_create(plr, NULL, type, 0);
5999 if (!sg_load_player_unit(loading, plr, punit, orders_max_length, buf)) {
6000 unit_virtual_destroy(punit);
6001 sg_failure_ret(FALSE, "Error loading unit %d of player %d.", i, plrno);
6002 }
6003
6004 identity_number_reserve(punit->id);
6005 idex_register_unit(&wld, punit);
6006
6007 if ((pcity = game_city_by_number(punit->homecity))) {
6008 unit_list_prepend(pcity->units_supported, punit);
6009 } else if (punit->homecity > IDENTITY_NUMBER_ZERO) {
6010 log_sg("%s: bad home city %d.", buf, punit->homecity);
6011 punit->homecity = IDENTITY_NUMBER_ZERO;
6012 }
6013
6014 ptile = unit_tile(punit);
6015
6016 /* allocate the unit's contribution to fog of war */
6017 punit->server.vision = vision_new(unit_owner(punit), ptile);
6018 unit_refresh_vision(punit);
6019 /* NOTE: There used to be some map_set_known calls here. These were
6020 * unneeded since unfogging the tile when the unit sees it will
6021 * automatically reveal that tile. */
6022
6023 unit_list_append(plr->units, punit);
6024 unit_list_prepend(unit_tile(punit)->units, punit);
6025 }
6026}
6027
6028/************************************************************************/
6031 static bool sg_load_player_unit(struct loaddata *loading,
6032 struct player *plr, struct unit *punit,
6033 int orders_max_length,
6034 const char *unitstr)
6035{
6036 enum unit_activity activity;
6037 int nat_x, nat_y;
6038 struct extra_type *pextra = NULL;
6039 struct tile *ptile;
6040 int extra_id;
6041 int ei;
6042 const char *facing_str;
6043 int natnbr;
6044 int unconverted;
6045 const char *str;
6046
6047 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->id, "%s.id",
6048 unitstr), FALSE, "%s", secfile_error());
6049 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x", unitstr),
6050 FALSE, "%s", secfile_error());
6051 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y", unitstr),
6052 FALSE, "%s", secfile_error());
6053
6054 ptile = native_pos_to_tile(&(wld.map), nat_x, nat_y);
6055 sg_warn_ret_val(NULL != ptile, FALSE, "%s invalid tile (%d, %d)",
6056 unitstr, nat_x, nat_y);
6057 unit_tile_set(punit, ptile);
6058
6059 facing_str
6060 = secfile_lookup_str_default(loading->file, "x",
6061 "%s.facing", unitstr);
6062 if (facing_str[0] != 'x') {
6063 /* We don't touch punit->facing if savegame does not contain that
6064 * information. Initial orientation set by unit_virtual_create()
6065 * is as good as any. */
6066 enum direction8 facing = char2dir(facing_str[0]);
6067
6068 if (direction8_is_valid(facing)) {
6069 punit->facing = facing;
6070 } else {
6071 log_error("Illegal unit orientation '%s'", facing_str);
6072 }
6073 }
6074
6075 /* If savegame has unit nationality, it doesn't hurt to
6076 * internally set it even if nationality rules are disabled. */
6077 natnbr = secfile_lookup_int_default(loading->file,
6078 player_number(plr),
6079 "%s.nationality", unitstr);
6080
6081 punit->nationality = player_by_number(natnbr);
6082 if (punit->nationality == NULL) {
6083 punit->nationality = plr;
6084 }
6085
6086 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->homecity,
6087 "%s.homecity", unitstr), FALSE,
6088 "%s", secfile_error());
6089 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->moves_left,
6090 "%s.moves", unitstr), FALSE,
6091 "%s", secfile_error());
6092 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->fuel,
6093 "%s.fuel", unitstr), FALSE,
6094 "%s", secfile_error());
6095 sg_warn_ret_val(secfile_lookup_int(loading->file, &ei,
6096 "%s.activity", unitstr), FALSE,
6097 "%s", secfile_error());
6098 activity = unit_activity_by_name(loading->activities.order[ei],
6099 fc_strcasecmp);
6100
6101 punit->birth_turn
6102 = secfile_lookup_int_default(loading->file, game.info.turn,
6103 "%s.born", unitstr);
6104 punit->current_form_turn
6105 = secfile_lookup_int_default(loading->file, game.info.turn,
6106 "%s.current_form_turn", unitstr);
6107
6108 extra_id = secfile_lookup_int_default(loading->file, -2,
6109 "%s.activity_tgt", unitstr);
6110
6111 if (extra_id != -2) {
6112 if (extra_id >= 0 && extra_id < loading->extra.size) {
6113 pextra = loading->extra.order[extra_id];
6114 set_unit_activity_targeted(punit, activity, pextra);
6115 } else if (activity == ACTIVITY_IRRIGATE) {
6116 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
6117 EC_IRRIGATION,
6118 unit_owner(punit),
6119 punit);
6120 if (tgt != NULL) {
6121 set_unit_activity_targeted(punit, ACTIVITY_IRRIGATE, tgt);
6122 } else {
6123 set_unit_activity(punit, ACTIVITY_CULTIVATE);
6124 }
6125 } else if (activity == ACTIVITY_MINE) {
6126 struct extra_type *tgt = next_extra_for_tile(unit_tile(punit),
6127 EC_MINE,
6128 unit_owner(punit),
6129 punit);
6130 if (tgt != NULL) {
6131 set_unit_activity_targeted(punit, ACTIVITY_MINE, tgt);
6132 } else {
6133 set_unit_activity(punit, ACTIVITY_PLANT);
6134 }
6135 } else {
6136 set_unit_activity(punit, activity);
6137 }
6138 } else {
6139 set_unit_activity_targeted(punit, activity, NULL);
6140 } /* activity_tgt == NULL */
6141
6142 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->activity_count,
6143 "%s.activity_count", unitstr), FALSE,
6144 "%s", secfile_error());
6145
6146 punit->changed_from =
6147 secfile_lookup_int_default(loading->file, ACTIVITY_IDLE,
6148 "%s.changed_from", unitstr);
6149
6150 sg_warn_ret_val(secfile_lookup_int(loading->file, &extra_id,
6151 "%s.changed_from_tgt", unitstr), FALSE,
6152 "%s", secfile_error());
6153
6154 if (extra_id >= 0 && extra_id < loading->extra.size) {
6155 punit->changed_from_target = loading->extra.order[extra_id];
6156 } else {
6157 punit->changed_from_target = NULL;
6158 }
6159
6160 punit->changed_from_count =
6161 secfile_lookup_int_default(loading->file, 0,
6162 "%s.changed_from_count", unitstr);
6163
6164 /* Special case: for a long time, we accidentally incremented
6165 * activity_count while a unit was sentried, so it could increase
6166 * without bound (bug #20641) and be saved in old savefiles.
6167 * We zero it to prevent potential trouble overflowing the range
6168 * in network packets, etc. */
6169 if (activity == ACTIVITY_SENTRY) {
6170 punit->activity_count = 0;
6171 }
6172 if (punit->changed_from == ACTIVITY_SENTRY) {
6173 punit->changed_from_count = 0;
6174 }
6175
6176 punit->veteran
6177 = secfile_lookup_int_default(loading->file, 0, "%s.veteran", unitstr);
6178 {
6179 /* Protect against change in veteran system in ruleset */
6180 const int levels = utype_veteran_levels(unit_type_get(punit));
6181
6182 if (punit->veteran >= levels) {
6183 fc_assert(levels >= 1);
6184 punit->veteran = levels - 1;
6185 }
6186 }
6187 punit->done_moving
6188 = secfile_lookup_bool_default(loading->file, (punit->moves_left == 0),
6189 "%s.done_moving", unitstr);
6190 punit->battlegroup
6191 = secfile_lookup_int_default(loading->file, BATTLEGROUP_NONE,
6192 "%s.battlegroup", unitstr);
6193
6194 if (secfile_lookup_bool_default(loading->file, FALSE,
6195 "%s.go", unitstr)) {
6196 int gnat_x, gnat_y;
6197
6198 sg_warn_ret_val(secfile_lookup_int(loading->file, &gnat_x,
6199 "%s.goto_x", unitstr), FALSE,
6200 "%s", secfile_error());
6201 sg_warn_ret_val(secfile_lookup_int(loading->file, &gnat_y,
6202 "%s.goto_y", unitstr), FALSE,
6203 "%s", secfile_error());
6204
6205 punit->goto_tile = native_pos_to_tile(&(wld.map), gnat_x, gnat_y);
6206 } else {
6207 punit->goto_tile = NULL;
6208
6209 /* These variables are not used but needed for saving the unit table.
6210 * Load them to prevent unused variables errors. */
6211 (void) secfile_entry_lookup(loading->file, "%s.goto_x", unitstr);
6212 (void) secfile_entry_lookup(loading->file, "%s.goto_y", unitstr);
6213 }
6214
6215 /* Load AI data of the unit. */
6216 CALL_FUNC_EACH_AI(unit_load, loading->file, punit, unitstr);
6217
6218 unconverted
6219 = secfile_lookup_int_default(loading->file, 0,
6220 "%s.server_side_agent",
6221 unitstr);
6222 if (unconverted >= 0 && unconverted < loading->ssa.size) {
6223 /* Look up what server side agent the unconverted number represents. */
6224 punit->ssa_controller = loading->ssa.order[unconverted];
6225 } else {
6226 log_sg("Invalid server side agent %d for unit %d",
6227 unconverted, punit->id);
6228
6229 punit->ssa_controller = SSA_NONE;
6230 }
6231
6232 sg_warn_ret_val(secfile_lookup_int(loading->file, &punit->hp,
6233 "%s.hp", unitstr), FALSE,
6234 "%s", secfile_error());
6235
6236 punit->server.ord_map
6237 = secfile_lookup_int_default(loading->file, 0, "%s.ord_map", unitstr);
6238 punit->server.ord_city
6239 = secfile_lookup_int_default(loading->file, 0, "%s.ord_city", unitstr);
6240 punit->moved
6241 = secfile_lookup_bool_default(loading->file, FALSE, "%s.moved", unitstr);
6242 punit->paradropped
6243 = secfile_lookup_bool_default(loading->file, FALSE,
6244 "%s.paradropped", unitstr);
6245 str = secfile_lookup_str_default(loading->file, "", "%s.carrying", unitstr);
6246 if (str[0] != '\0') {
6247 punit->carrying = goods_by_rule_name(str);
6248 }
6249
6250 /* The transport status (punit->transported_by) is loaded in
6251 * sg_player_units_transport(). */
6252
6253 /* Initialize upkeep values: these are hopefully initialized
6254 * elsewhere before use (specifically, in city_support(); but
6255 * fixme: check whether always correctly initialized?).
6256 * Below is mainly for units which don't have homecity --
6257 * otherwise these don't get initialized (and AI calculations
6258 * etc may use junk values). */
6259 output_type_iterate(o) {
6260 punit->upkeep[o] = utype_upkeep_cost(unit_type_get(punit), plr, o);
6261 } output_type_iterate_end;
6262
6263 sg_warn_ret_val(secfile_lookup_int(loading->file, &unconverted,
6264 "%s.action_decision", unitstr),
6265 FALSE, "%s", secfile_error());
6266
6267 if (unconverted >= 0 && unconverted < loading->act_dec.size) {
6268 /* Look up what action decision want the unconverted number
6269 * represents. */
6270 punit->action_decision_want = loading->act_dec.order[unconverted];
6271 } else {
6272 log_sg("Invalid action decision want for unit %d", punit->id);
6273
6274 punit->action_decision_want = ACT_DEC_NOTHING;
6275 }
6276
6277 if (punit->action_decision_want != ACT_DEC_NOTHING) {
6278 /* Load the tile to act against. */
6279 int adwt_x, adwt_y;
6280
6281 if (secfile_lookup_int(loading->file, &adwt_x,
6282 "%s.action_decision_tile_x", unitstr)
6283 && secfile_lookup_int(loading->file, &adwt_y,
6284 "%s.action_decision_tile_y", unitstr)) {
6285 punit->action_decision_tile = native_pos_to_tile(&(wld.map),
6286 adwt_x, adwt_y);
6287 } else {
6288 punit->action_decision_want = ACT_DEC_NOTHING;
6289 punit->action_decision_tile = NULL;
6290 log_sg("Bad action_decision_tile for unit %d", punit->id);
6291 }
6292 } else {
6293 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_x", unitstr);
6294 (void) secfile_entry_lookup(loading->file, "%s.action_decision_tile_y", unitstr);
6295 punit->action_decision_tile = NULL;
6296 }
6297
6298 punit->stay = secfile_lookup_bool_default(loading->file, FALSE, "%s.stay", unitstr);
6299
6300 /* Load the unit orders */
6301 {
6302 int len = secfile_lookup_int_default(loading->file, 0,
6303 "%s.orders_length", unitstr);
6304
6305 if (len > 0) {
6306 const char *orders_unitstr, *dir_unitstr, *act_unitstr;
6307 int j;
6308
6309 punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list)));
6310 punit->orders.length = len;
6311 punit->orders.index
6312 = secfile_lookup_int_default(loading->file, 0,
6313 "%s.orders_index", unitstr);
6314 punit->orders.repeat
6315 = secfile_lookup_bool_default(loading->file, FALSE,
6316 "%s.orders_repeat", unitstr);
6317 punit->orders.vigilant
6318 = secfile_lookup_bool_default(loading->file, FALSE,
6319 "%s.orders_vigilant", unitstr);
6320
6321 orders_unitstr
6322 = secfile_lookup_str_default(loading->file, "",
6323 "%s.orders_list", unitstr);
6324 dir_unitstr
6325 = secfile_lookup_str_default(loading->file, "",
6326 "%s.dir_list", unitstr);
6327 act_unitstr
6328 = secfile_lookup_str_default(loading->file, "",
6329 "%s.activity_list", unitstr);
6330
6331 punit->has_orders = TRUE;
6332
6333 for (j = 0; j < len; j++) {
6334 struct unit_order *order = &punit->orders.list[j];
6335 bool action_wants_extra = FALSE;
6336 int order_sub_tgt;
6337
6338 if (orders_unitstr[j] == '\0' || dir_unitstr[j] == '\0'
6339 || act_unitstr[j] == '\0') {
6340 log_sg("Invalid unit orders.");
6341 free_unit_orders(punit);
6342 break;
6343 }
6344 order->order = char2order(orders_unitstr[j]);
6345 order->dir = char2dir(dir_unitstr[j]);
6346 order->activity = char2activity(act_unitstr[j]);
6347
6348 unconverted = secfile_lookup_int_default(loading->file, ACTION_NONE,
6349 "%s.action_vec,%d",
6350 unitstr, j);
6351
6352 if (unconverted >= 0 && unconverted < loading-> action.size) {
6353 /* Look up what action id the unconverted number represents. */
6354 order->action = loading->action.order[unconverted];
6355 } else {
6356 if (order->order == ORDER_PERFORM_ACTION) {
6357 log_sg("Invalid action id in order for unit %d", punit->id);
6358 }
6359
6360 order->action = ACTION_NONE;
6361 }
6362
6363 if (order->order == ORDER_LAST
6364 || (order->order == ORDER_MOVE && !direction8_is_valid(order->dir))
6365 || (order->order == ORDER_ACTION_MOVE
6366 && !direction8_is_valid(order->dir))
6367 || (order->order == ORDER_PERFORM_ACTION
6368 && !action_id_exists(order->action))
6369 || (order->order == ORDER_ACTIVITY
6370 && order->activity == ACTIVITY_LAST)) {
6371 /* An invalid order. Just drop the orders for this unit. */
6372 free(punit->orders.list);
6373 punit->orders.list = NULL;
6374 punit->has_orders = FALSE;
6375 break;
6376 }
6377
6378 order->target = secfile_lookup_int_default(loading->file, NO_TARGET,
6379 "%s.tgt_vec,%d",
6380 unitstr, j);
6381 order_sub_tgt = secfile_lookup_int_default(loading->file, -1,
6382 "%s.sub_tgt_vec,%d",
6383 unitstr, j);
6384
6385 if (order->order == ORDER_PERFORM_ACTION) {
6386 /* Validate sub target */
6387 switch (action_id_get_sub_target_kind(order->action)) {
6388 case ASTK_BUILDING:
6389 /* Sub target is a building. */
6390 if (!improvement_by_number(order_sub_tgt)) {
6391 /* Sub target is invalid. */
6392 log_sg("Cannot find building %d for %s to %s",
6393 order_sub_tgt, unit_rule_name(punit),
6394 action_id_name_translation(order->action));
6395 order->sub_target = B_LAST;
6396 } else {
6397 order->sub_target = order_sub_tgt;
6398 }
6399 break;
6400 case ASTK_TECH:
6401 /* Sub target is a technology. */
6402 if (order_sub_tgt == A_NONE
6403 || (!valid_advance_by_number(order_sub_tgt)
6404 && order_sub_tgt != A_FUTURE)) {
6405 /* Target tech is invalid. */
6406 log_sg("Cannot find tech %d for %s to steal",
6407 order_sub_tgt, unit_rule_name(punit));
6408 order->sub_target = A_NONE;
6409 } else {
6410 order->sub_target = order_sub_tgt;
6411 }
6412 break;
6413 case ASTK_EXTRA:
6414 case ASTK_EXTRA_NOT_THERE:
6415 /* These take an extra. */
6416 action_wants_extra = TRUE;
6417 break;
6418 case ASTK_NONE:
6419 /* None of these can take a sub target. */
6420 fc_assert_msg(order_sub_tgt == -1,
6421 "Specified sub target for action %d unsupported.",
6422 order->action);
6423 order->sub_target = NO_TARGET;
6424 break;
6425 case ASTK_COUNT:
6426 fc_assert_msg(order_sub_tgt == -1,
6427 "Bad action action %d.",
6428 order->action);
6429 order->sub_target = NO_TARGET;
6430 break;
6431 }
6432 }
6433
6434 if (order->order == ORDER_ACTIVITY || action_wants_extra) {
6435 enum unit_activity act;
6436
6437 if (order_sub_tgt < 0 || order_sub_tgt >= loading->extra.size) {
6438 if (order_sub_tgt != EXTRA_NONE) {
6439 log_sg("Cannot find extra %d for %s to build",
6440 order_sub_tgt, unit_rule_name(punit));
6441 }
6442
6443 order->sub_target = EXTRA_NONE;
6444 } else {
6445 order->sub_target = order_sub_tgt;
6446 }
6447
6448 /* An action or an activity may require an extra target. */
6449 if (action_wants_extra) {
6450 act = action_id_get_activity(order->action);
6451 } else {
6452 act = order->activity;
6453 }
6454
6455 if (unit_activity_is_valid(act)
6456 && unit_activity_needs_target_from_client(act)
6457 && order->sub_target == EXTRA_NONE) {
6458 /* Missing required action extra target. */
6459 free(punit->orders.list);
6460 punit->orders.list = NULL;
6461 punit->has_orders = FALSE;
6462 break;
6463 }
6464 } else if (order->order != ORDER_PERFORM_ACTION) {
6465 if (order_sub_tgt != -1) {
6466 log_sg("Unexpected sub_target %d (expected %d) for order type %d",
6467 order_sub_tgt, -1, order->order);
6468 }
6469 order->sub_target = NO_TARGET;
6470 }
6471 }
6472
6473 for (; j < orders_max_length; j++) {
6474 (void) secfile_entry_lookup(loading->file,
6475 "%s.action_vec,%d", unitstr, j);
6476 (void) secfile_entry_lookup(loading->file,
6477 "%s.tgt_vec,%d", unitstr, j);
6478 (void) secfile_entry_lookup(loading->file,
6479 "%s.sub_tgt_vec,%d", unitstr, j);
6480 }
6481 } else {
6482 int j;
6483
6484 punit->has_orders = FALSE;
6485 punit->orders.list = NULL;
6486
6487 (void) secfile_entry_lookup(loading->file, "%s.orders_index", unitstr);
6488 (void) secfile_entry_lookup(loading->file, "%s.orders_repeat", unitstr);
6489 (void) secfile_entry_lookup(loading->file, "%s.orders_vigilant", unitstr);
6490 (void) secfile_entry_lookup(loading->file, "%s.orders_list", unitstr);
6491 (void) secfile_entry_lookup(loading->file, "%s.dir_list", unitstr);
6492 (void) secfile_entry_lookup(loading->file, "%s.activity_list", unitstr);
6493 (void) secfile_entry_lookup(loading->file, "%s.action_vec", unitstr);
6494 (void) secfile_entry_lookup(loading->file, "%s.tgt_vec", unitstr);
6495 (void) secfile_entry_lookup(loading->file, "%s.sub_tgt_vec", unitstr);
6496
6497 for (j = 1; j < orders_max_length; j++) {
6498 (void) secfile_entry_lookup(loading->file,
6499 "%s.action_vec,%d", unitstr, j);
6500 (void) secfile_entry_lookup(loading->file,
6501 "%s.tgt_vec,%d", unitstr, j);
6502 (void) secfile_entry_lookup(loading->file,
6503 "%s.sub_tgt_vec,%d", unitstr, j);
6504 }
6505 }
6506 }
6507
6508 return TRUE;
6509}
6510
6511/************************************************************************/
6515 static void sg_load_player_units_transport(struct loaddata *loading,
6516 struct player *plr)
6517{
6518 int nunits, i, plrno = player_number(plr);
6519
6520 /* Check status and return if not OK (sg_success FALSE). */
6521 sg_check_ret();
6522
6523 /* Recheck the number of units for the player. This is a copied from
6524 * sg_load_player_units(). */
6525 sg_failure_ret(secfile_lookup_int(loading->file, &nunits,
6526 "player%d.nunits", plrno),
6527 "%s", secfile_error());
6528 if (!plr->is_alive && nunits > 0) {
6529 log_sg("'player%d.nunits' = %d for dead player!", plrno, nunits);
6530 nunits = 0; /* Some old savegames may be buggy. */
6531 }
6532
6533 for (i = 0; i < nunits; i++) {
6534 int id_unit, id_trans;
6535 struct unit *punit, *ptrans;
6536
6537 id_unit = secfile_lookup_int_default(loading->file, -1,
6538 "player%d.u%d.id",
6539 plrno, i);
6540 punit = player_unit_by_number(plr, id_unit);
6541 fc_assert_action(punit != NULL, continue);
6542
6543 id_trans = secfile_lookup_int_default(loading->file, -1,
6544 "player%d.u%d.transported_by",
6545 plrno, i);
6546 if (id_trans == -1) {
6547 /* Not transported. */
6548 continue;
6549 }
6550
6551 ptrans = game_unit_by_number(id_trans);
6552 fc_assert_action(id_trans == -1 || ptrans != NULL, continue);
6553
6554 if (ptrans) {
6555#ifndef FREECIV_NDEBUG
6556 bool load_success =
6557#endif
6558 unit_transport_load(punit, ptrans, TRUE);
6559
6560 fc_assert_action(load_success, continue);
6561 }
6562 }
6563}
6564
6565/************************************************************************/
6568 static void sg_save_player_units(struct savedata *saving,
6569 struct player *plr)
6570{
6571 int i = 0;
6572 int longest_order = 0;
6573 int plrno = player_number(plr);
6574
6575 /* Check status and return if not OK (sg_success FALSE). */
6576 sg_check_ret();
6577
6578 secfile_insert_int(saving->file, unit_list_size(plr->units),
6579 "player%d.nunits", plrno);
6580
6581 /* Find the longest unit order so different order length won't break
6582 * storing units in the tabular format. */
6583 unit_list_iterate(plr->units, punit) {
6584 if (punit->has_orders) {
6585 if (longest_order < punit-> orders.length) {
6586 longest_order = punit->orders.length;
6587 }
6588 }
6589 } unit_list_iterate_end;
6590
6591 secfile_insert_int(saving->file, longest_order,
6592 "player%d.orders_max_length", plrno);
6593
6594 unit_list_iterate(plr->units, punit) {
6595 char buf[32];
6596 char dirbuf[2] = " ";
6597 int nat_x, nat_y;
6598 int last_order, j;
6599
6600 fc_snprintf(buf, sizeof(buf), "player%d.u%d", plrno, i);
6601 dirbuf[0] = dir2char(punit->facing);
6602 secfile_insert_int(saving->file, punit->id, "%s.id", buf);
6603
6604 index_to_native_pos(&nat_x, &nat_y, tile_index(unit_tile(punit)));
6605 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
6606 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
6607
6608 secfile_insert_str(saving->file, dirbuf, "%s.facing", buf);
6609 if (game.info.citizen_nationality) {
6610 secfile_insert_int(saving->file, player_number(unit_nationality(punit)),
6611 "%s.nationality", buf);
6612 }
6613 secfile_insert_int(saving->file, punit->veteran, "%s.veteran", buf);
6614 secfile_insert_int(saving->file, punit->hp, "%s.hp", buf);
6615 secfile_insert_int(saving->file, punit->homecity, "%s.homecity", buf);
6616 secfile_insert_str(saving->file, unit_rule_name(punit),
6617 "%s.type_by_name", buf);
6618
6619 secfile_insert_int(saving->file, punit->activity, "%s.activity", buf);
6620 secfile_insert_int(saving->file, punit->activity_count,
6621 "%s.activity_count", buf);
6622 if (punit->activity_target == NULL) {
6623 secfile_insert_int(saving->file, -1, "%s.activity_tgt", buf);
6624 } else {
6625 secfile_insert_int(saving->file, extra_index(punit->activity_target),
6626 "%s.activity_tgt", buf);
6627 }
6628
6629 secfile_insert_int(saving->file, punit->changed_from,
6630 "%s.changed_from", buf);
6631 secfile_insert_int(saving->file, punit->changed_from_count,
6632 "%s.changed_from_count", buf);
6633 if (punit->changed_from_target == NULL) {
6634 secfile_insert_int(saving->file, -1, "%s.changed_from_tgt", buf);
6635 } else {
6636 secfile_insert_int(saving->file, extra_index(punit->changed_from_target),
6637 "%s.changed_from_tgt", buf);
6638 }
6639
6640 secfile_insert_bool(saving->file, punit->done_moving,
6641 "%s.done_moving", buf);
6642 secfile_insert_int(saving->file, punit->moves_left, "%s.moves", buf);
6643 secfile_insert_int(saving->file, punit->fuel, "%s.fuel", buf);
6644 secfile_insert_int(saving->file, punit->birth_turn,
6645 "%s.born", buf);
6646 secfile_insert_int(saving->file, punit->current_form_turn,
6647 "%s.current_form_turn", buf);
6648 secfile_insert_int(saving->file, punit->battlegroup,
6649 "%s.battlegroup", buf);
6650
6651 if (punit->goto_tile) {
6652 index_to_native_pos(&nat_x, &nat_y, tile_index(punit->goto_tile));
6653 secfile_insert_bool(saving->file, TRUE, "%s.go", buf);
6654 secfile_insert_int(saving->file, nat_x, "%s.goto_x", buf);
6655 secfile_insert_int(saving->file, nat_y, "%s.goto_y", buf);
6656 } else {
6657 secfile_insert_bool(saving->file, FALSE, "%s.go", buf);
6658 /* Set this values to allow saving it as table. */
6659 secfile_insert_int(saving->file, 0, "%s.goto_x", buf);
6660 secfile_insert_int(saving->file, 0, "%s.goto_y", buf);
6661 }
6662
6663 secfile_insert_int(saving->file, punit->ssa_controller,
6664 "%s.server_side_agent", buf);
6665
6666 /* Save AI data of the unit. */
6667 CALL_FUNC_EACH_AI(unit_save, saving->file, punit, buf);
6668
6669 secfile_insert_int(saving->file, punit->server.ord_map,
6670 "%s.ord_map", buf);
6671 secfile_insert_int(saving->file, punit->server.ord_city,
6672 "%s.ord_city", buf);
6673 secfile_insert_bool(saving->file, punit->moved, "%s.moved", buf);
6674 secfile_insert_bool(saving->file, punit->paradropped,
6675 "%s.paradropped", buf);
6676 secfile_insert_int(saving->file, unit_transport_get(punit)
6677 ? unit_transport_get(punit)->id : -1,
6678 "%s.transported_by", buf);
6679 if (punit->carrying != NULL) {
6680 secfile_insert_str(saving->file, goods_rule_name(punit->carrying),
6681 "%s.carrying", buf);
6682 } else {
6683 secfile_insert_str(saving->file, "", "%s.carrying", buf);
6684 }
6685
6686 secfile_insert_int(saving->file, punit->action_decision_want,
6687 "%s.action_decision", buf);
6688
6689 /* Stored as tile rather than direction to make sure the target tile is
6690 * sane. */
6691 if (punit->action_decision_tile) {
6692 index_to_native_pos(&nat_x, &nat_y,
6693 tile_index(punit->action_decision_tile));
6694 secfile_insert_int(saving->file, nat_x,
6695 "%s.action_decision_tile_x", buf);
6696 secfile_insert_int(saving->file, nat_y,
6697 "%s.action_decision_tile_y", buf);
6698 } else {
6699 /* Dummy values to get tabular format. */
6700 secfile_insert_int(saving->file, -1,
6701 "%s.action_decision_tile_x", buf);
6702 secfile_insert_int(saving->file, -1,
6703 "%s.action_decision_tile_y", buf);
6704 }
6705
6706 secfile_insert_bool(saving->file, punit->stay,
6707 "%s.stay", buf);
6708
6709 if (punit->has_orders) {
6710 int len = punit->orders.length;
6711 char orders_buf[len + 1], dir_buf[len + 1];
6712 char act_buf[len + 1];
6713 int action_buf[len];
6714 int tgt_vec[len];
6715 int sub_tgt_vec[len];
6716
6717 last_order = len;
6718
6719 secfile_insert_int(saving->file, len, "%s.orders_length", buf);
6720 secfile_insert_int(saving->file, punit->orders.index,
6721 "%s.orders_index", buf);
6722 secfile_insert_bool(saving->file, punit->orders.repeat,
6723 "%s.orders_repeat", buf);
6724 secfile_insert_bool(saving->file, punit->orders.vigilant,
6725 "%s.orders_vigilant", buf);
6726
6727 for (j = 0; j < len; j++) {
6728 orders_buf[j] = order2char(punit->orders.list[j].order);
6729 dir_buf[j] = '?';
6730 act_buf[j] = '?';
6731 tgt_vec[j] = NO_TARGET;
6732 sub_tgt_vec[j] = -1;
6733 action_buf[j] = -1;
6734 switch (punit->orders.list[j].order) {
6735 case ORDER_MOVE:
6736 case ORDER_ACTION_MOVE:
6737 dir_buf[j] = dir2char(punit->orders.list[j].dir);
6738 break;
6739 case ORDER_ACTIVITY:
6740 sub_tgt_vec[j] = punit->orders.list[j].sub_target;
6741 act_buf[j] = activity2char(punit->orders.list[j].activity);
6742 break;
6743 case ORDER_PERFORM_ACTION:
6744 action_buf[j] = punit->orders.list[j].action;
6745 tgt_vec[j] = punit->orders.list[j].target;
6746 sub_tgt_vec[j] = punit->orders.list[j].sub_target;
6747 break;
6748 case ORDER_FULL_MP:
6749 case ORDER_LAST:
6750 break;
6751 }
6752 }
6753 orders_buf[len] = dir_buf[len] = act_buf[len] = '\0';
6754
6755 secfile_insert_str(saving->file, orders_buf, "%s.orders_list", buf);
6756 secfile_insert_str(saving->file, dir_buf, "%s.dir_list", buf);
6757 secfile_insert_str(saving->file, act_buf, "%s.activity_list", buf);
6758
6759 secfile_insert_int_vec(saving->file, action_buf, len,
6760 "%s.action_vec", buf);
6761 /* Fill in dummy values for order targets so the registry will save
6762 * the unit table in a tabular format. */
6763 for (j = last_order; j < longest_order; j++) {
6764 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6765 }
6766
6767 secfile_insert_int_vec(saving->file, tgt_vec, len,
6768 "%s.tgt_vec", buf);
6769 /* Fill in dummy values for order targets so the registry will save
6770 * the unit table in a tabular format. */
6771 for (j = last_order; j < longest_order; j++) {
6772 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6773 }
6774
6775 secfile_insert_int_vec(saving->file, sub_tgt_vec, len,
6776 "%s.sub_tgt_vec", buf);
6777 /* Fill in dummy values for order targets so the registry will save
6778 * the unit table in a tabular format. */
6779 for (j = last_order; j < longest_order; j++) {
6780 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6781 }
6782 } else {
6783
6784 /* Put all the same fields into the savegame - otherwise the
6785 * registry code can't correctly use a tabular format and the
6786 * savegame will be bigger. */
6787 secfile_insert_int(saving->file, 0, "%s.orders_length", buf);
6788 secfile_insert_int(saving->file, 0, "%s.orders_index", buf);
6789 secfile_insert_bool(saving->file, FALSE, "%s.orders_repeat", buf);
6790 secfile_insert_bool(saving->file, FALSE, "%s.orders_vigilant", buf);
6791 secfile_insert_str(saving->file, "-", "%s.orders_list", buf);
6792 secfile_insert_str(saving->file, "-", "%s.dir_list", buf);
6793 secfile_insert_str(saving->file, "-", "%s.activity_list", buf);
6794
6795 /* Fill in dummy values for order targets so the registry will save
6796 * the unit table in a tabular format. */
6797
6798 /* The start of a vector has no number. */
6799 secfile_insert_int(saving->file, -1, "%s.action_vec", buf);
6800 for (j = 1; j < longest_order; j++) {
6801 secfile_insert_int(saving->file, -1, "%s.action_vec,%d", buf, j);
6802 }
6803
6804 /* The start of a vector has no number. */
6805 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec", buf);
6806 for (j = 1; j < longest_order; j++) {
6807 secfile_insert_int(saving->file, NO_TARGET, "%s.tgt_vec,%d", buf, j);
6808 }
6809
6810 /* The start of a vector has no number. */
6811 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec", buf);
6812 for (j = 1; j < longest_order; j++) {
6813 secfile_insert_int(saving->file, -1, "%s.sub_tgt_vec,%d", buf, j);
6814 }
6815 }
6816
6817 i++;
6818 } unit_list_iterate_end;
6819}
6820
6821/************************************************************************/
6824 static void sg_load_player_attributes(struct loaddata *loading,
6825 struct player *plr)
6826{
6827 int plrno = player_number(plr);
6828
6829 /* Check status and return if not OK (sg_success FALSE). */
6830 sg_check_ret();
6831
6832 /* Toss any existing attribute_block (should not exist) */
6833 if (plr->attribute_block.data) {
6834 free(plr->attribute_block.data);
6835 plr->attribute_block.data = NULL;
6836 }
6837
6838 /* This is a big heap of opaque data for the client, check everything! */
6839 plr->attribute_block.length = secfile_lookup_int_default(
6840 loading->file, 0, "player%d.attribute_v2_block_length", plrno);
6841
6842 if (0 > plr->attribute_block.length) {
6843 log_sg("player%d.attribute_v2_block_length=%d too small", plrno,
6844 plr->attribute_block.length);
6845 plr->attribute_block.length = 0;
6846 } else if (MAX_ATTRIBUTE_BLOCK < plr->attribute_block.length) {
6847 log_sg("player%d.attribute_v2_block_length=%d too big (max %d)",
6848 plrno, plr->attribute_block.length, MAX_ATTRIBUTE_BLOCK);
6849 plr->attribute_block.length = 0;
6850 } else if (0 < plr->attribute_block.length) {
6851 int part_nr, parts;
6852 int quoted_length;
6853 char *quoted;
6854#ifndef FREECIV_NDEBUG
6855 size_t actual_length;
6856#endif
6857
6858 sg_failure_ret(
6859 secfile_lookup_int(loading->file, &quoted_length,
6860 "player%d.attribute_v2_block_length_quoted",
6861 plrno), "%s", secfile_error());
6862 sg_failure_ret(
6863 secfile_lookup_int(loading->file, &parts,
6864 "player%d.attribute_v2_block_parts", plrno),
6865 "%s", secfile_error());
6866
6867 quoted = fc_malloc(quoted_length + 1);
6868 quoted[0] = '\0';
6869 plr->attribute_block.data = fc_malloc(plr->attribute_block.length);
6870 for (part_nr = 0; part_nr < parts; part_nr++) {
6871 const char *current =
6872 secfile_lookup_str(loading->file,
6873 "player%d.attribute_v2_block_data.part%d",
6874 plrno, part_nr);
6875 if (!current) {
6876 log_sg("attribute_v2_block_parts=%d actual=%d", parts, part_nr);
6877 break;
6878 }
6879 log_debug("attribute_v2_block_length_quoted=%d"
6880 " have=" SIZE_T_PRINTF " part=" SIZE_T_PRINTF,
6881 quoted_length, strlen(quoted), strlen(current));
6882 fc_assert(strlen(quoted) + strlen(current) <= quoted_length);
6883 strcat(quoted, current);
6884 }
6885 fc_assert_msg(quoted_length == strlen(quoted),
6886 "attribute_v2_block_length_quoted=%d"
6887 " actual=" SIZE_T_PRINTF,
6888 quoted_length, strlen(quoted));
6889
6890#ifndef FREECIV_NDEBUG
6891 actual_length =
6892#endif
6893 unquote_block(quoted,
6894 plr->attribute_block.data,
6895 plr->attribute_block.length);
6896 fc_assert(actual_length == plr->attribute_block.length);
6897 free(quoted);
6898 }
6899}
6900
6901/************************************************************************/
6904 static void sg_save_player_attributes(struct savedata *saving,
6905 struct player *plr)
6906{
6907 int plrno = player_number(plr);
6908
6909 /* Check status and return if not OK (sg_success FALSE). */
6910 sg_check_ret();
6911
6912 /* This is a big heap of opaque data from the client. Although the binary
6913 * format is not user editable, keep the lines short enough for debugging,
6914 * and hope that data compression will keep the file a reasonable size.
6915 * Note that the "quoted" format is a multiple of 3.
6916 */
6917#define PART_SIZE (3*256)
6918#define PART_ADJUST (3)
6919 if (plr->attribute_block.data) {
6920 char part[PART_SIZE + PART_ADJUST];
6921 int parts;
6922 int current_part_nr;
6923 char *quoted = quote_block(plr->attribute_block.data,
6924 plr->attribute_block.length);
6925 char *quoted_at = strchr(quoted, ':');
6926 size_t bytes_left = strlen(quoted);
6927 size_t bytes_at_colon = 1 + (quoted_at - quoted);
6928 size_t bytes_adjust = bytes_at_colon % PART_ADJUST;
6929
6930 secfile_insert_int(saving->file, plr->attribute_block.length,
6931 "player%d.attribute_v2_block_length", plrno);
6932 secfile_insert_int(saving->file, bytes_left,
6933 "player%d.attribute_v2_block_length_quoted", plrno);
6934
6935 /* Try to wring some compression efficiencies out of the "quoted" format.
6936 * The first line has a variable length decimal, mis-aligning triples.
6937 */
6938 if ((bytes_left - bytes_adjust) > PART_SIZE) {
6939 /* first line can be longer */
6940 parts = 1 + (bytes_left - bytes_adjust - 1) / PART_SIZE;
6941 } else {
6942 parts = 1;
6943 }
6944
6945 secfile_insert_int(saving->file, parts,
6946 "player%d.attribute_v2_block_parts", plrno);
6947
6948 if (parts > 1) {
6949 size_t size_of_current_part = PART_SIZE + bytes_adjust;
6950
6951 /* first line can be longer */
6952 memcpy(part, quoted, size_of_current_part);
6953 part[size_of_current_part] = '\0';
6954 secfile_insert_str(saving->file, part,
6955 "player%d.attribute_v2_block_data.part%d",
6956 plrno, 0);
6957 bytes_left -= size_of_current_part;
6958 quoted_at = &quoted[size_of_current_part];
6959 current_part_nr = 1;
6960 } else {
6961 quoted_at = quoted;
6962 current_part_nr = 0;
6963 }
6964
6965 for (; current_part_nr < parts; current_part_nr++) {
6966 size_t size_of_current_part = MIN(bytes_left, PART_SIZE);
6967
6968 memcpy(part, quoted_at, size_of_current_part);
6969 part[size_of_current_part] = '\0';
6970 secfile_insert_str(saving->file, part,
6971 "player%d.attribute_v2_block_data.part%d",
6972 plrno,
6973 current_part_nr);
6974 bytes_left -= size_of_current_part;
6975 quoted_at = &quoted_at[size_of_current_part];
6976 }
6977 fc_assert(bytes_left == 0);
6978 free(quoted);
6979 }
6980#undef PART_ADJUST
6981#undef PART_SIZE
6982}
6983
6984/************************************************************************/
6987 static void sg_load_player_vision(struct loaddata *loading,
6988 struct player *plr)
6989{
6990 int plrno = player_number(plr);
6991 int total_ncities =
6992 secfile_lookup_int_default(loading->file, -1,
6993 "player%d.dc_total", plrno);
6994 int i;
6995 bool someone_alive = FALSE;
6996
6997 /* Check status and return if not OK (sg_success FALSE). */
6998 sg_check_ret();
6999
7000 if (game.server.revealmap & REVEAL_MAP_DEAD) {
7001 player_list_iterate(team_members(plr->team), pteam_member) {
7002 if (pteam_member->is_alive) {
7003 someone_alive = TRUE;
7004 break;
7005 }
7006 } player_list_iterate_end;
7007
7008 if (!someone_alive) {
7009 /* Reveal all for completely dead teams. */
7010 map_know_and_see_all(plr);
7011 }
7012 }
7013
7014 if (-1 == total_ncities
7015 || !game.info.fogofwar
7016 || !secfile_lookup_bool_default(loading->file, TRUE,
7017 "game.save_private_map")) {
7018 /* We have:
7019 * - a dead player;
7020 * - fogged cities are not saved for any reason;
7021 * - a savegame with fog of war turned off;
7022 * - or game.save_private_map is not set to FALSE in the scenario /
7023 * savegame. The players private knowledge is set to be what they could
7024 * see without fog of war. */
7025 whole_map_iterate(&(wld.map), ptile) {
7026 if (map_is_known(ptile, plr)) {
7027 struct city *pcity = tile_city(ptile);
7028
7029 update_player_tile_last_seen(plr, ptile);
7030 update_player_tile_knowledge(plr, ptile);
7031
7032 if (NULL != pcity) {
7033 update_dumb_city(plr, pcity);
7034 }
7035 }
7036 } whole_map_iterate_end;
7037
7038 /* Nothing more to do; */
7039 return;
7040 }
7041
7042 /* Load player map (terrain). */
7043 LOAD_MAP_CHAR(ch, ptile,
7044 map_get_player_tile(ptile, plr)->terrain
7045 = char2terrain(ch), loading->file,
7046 "player%d.map_t%04d", plrno);
7047
7048 /* Load player map (extras). */
7049 halfbyte_iterate_extras(j, loading->extra.size) {
7050 LOAD_MAP_CHAR(ch, ptile,
7051 sg_extras_set_dbv(&(map_get_player_tile(ptile, plr)->extras),
7052 ch, loading->extra.order + 4 * j),
7053 loading->file, "player%d.map_e%02d_%04d", plrno, j);
7054 } halfbyte_iterate_extras_end;
7055
7056 whole_map_iterate(&(wld.map), ptile) {
7057 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7058
7059 extra_type_by_cause_iterate(EC_RESOURCE, pres) {
7060 if (BV_ISSET(plrtile->extras, extra_number(pres))
7061 && terrain_has_resource(plrtile->terrain, pres)) {
7062 plrtile->resource = pres;
7063 }
7064 } extra_type_by_cause_iterate_end;
7065 } whole_map_iterate_end;
7066
7067 if (game.server.foggedborders) {
7068 /* Load player map (border). */
7069 int x, y;
7070
7071 for (y = 0; y < wld.map.ysize; y++) {
7072 const char *buffer
7073 = secfile_lookup_str(loading->file, "player%d.map_owner%04d",
7074 plrno, y);
7075 const char *buffer2
7076 = secfile_lookup_str(loading->file, "player%d.extras_owner%04d",
7077 plrno, y);
7078 const char *ptr = buffer;
7079 const char *ptr2 = buffer2;
7080
7081 sg_failure_ret(NULL != buffer,
7082 "Savegame corrupt - map line %d not found.", y);
7083 for (x = 0; x < wld.map.xsize; x++) {
7084 char token[TOKEN_SIZE];
7085 char token2[TOKEN_SIZE];
7086 int number;
7087 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7088
7089 scanin(&ptr, ",", token, sizeof(token));
7090 sg_failure_ret('\0' != token[0],
7091 "Savegame corrupt - map size not correct.");
7092 if (strcmp(token, "-") == 0) {
7093 map_get_player_tile(ptile, plr)->owner = NULL;
7094 } else {
7095 sg_failure_ret(str_to_int(token, &number),
7096 "Savegame corrupt - got tile owner=%s in (%d, %d).",
7097 token, x, y);
7098 map_get_player_tile(ptile, plr)->owner = player_by_number(number);
7099 }
7100
7101 scanin(&ptr2, ",", token2, sizeof(token2));
7102 sg_failure_ret('\0' != token2[0],
7103 "Savegame corrupt - map size not correct.");
7104 if (strcmp(token2, "-") == 0) {
7105 map_get_player_tile(ptile, plr)->extras_owner = NULL;
7106 } else {
7107 sg_failure_ret(str_to_int(token2, &number),
7108 "Savegame corrupt - got extras owner=%s in (%d, %d).",
7109 token, x, y);
7110 map_get_player_tile(ptile, plr)->extras_owner = player_by_number(number);
7111 }
7112 }
7113 }
7114 }
7115
7116 /* Load player map (update time). */
7117 for (i = 0; i < 4; i++) {
7118 /* put 4-bit segments of 16-bit "updated" field */
7119 if (i == 0) {
7120 LOAD_MAP_CHAR(ch, ptile,
7121 map_get_player_tile(ptile, plr)->last_updated
7122 = ascii_hex2bin(ch, i),
7123 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7124 } else {
7125 LOAD_MAP_CHAR(ch, ptile,
7126 map_get_player_tile(ptile, plr)->last_updated
7127 |= ascii_hex2bin(ch, i),
7128 loading->file, "player%d.map_u%02d_%04d", plrno, i);
7129 }
7130 }
7131
7132 /* Load player map known cities. */
7133 for (i = 0; i < total_ncities; i++) {
7134 struct vision_site *pdcity;
7135 char buf[32];
7136 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7137
7138 pdcity = vision_site_new(0, NULL, NULL);
7139 if (sg_load_player_vision_city(loading, plr, pdcity, buf)) {
7140 change_playertile_site(map_get_player_tile(pdcity->location, plr),
7141 pdcity);
7142 identity_number_reserve(pdcity->identity);
7143 } else {
7144 /* Error loading the data. */
7145 log_sg("Skipping seen city %d for player %d.", i, plrno);
7146 if (pdcity != NULL) {
7147 vision_site_destroy(pdcity);
7148 }
7149 }
7150 }
7151
7152 /* Repair inconsistent player maps. */
7153 whole_map_iterate(&(wld.map), ptile) {
7154 if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
7155 struct city *pcity = tile_city(ptile);
7156
7157 update_player_tile_knowledge(plr, ptile);
7158 reality_check_city(plr, ptile);
7159
7160 if (NULL != pcity) {
7161 update_dumb_city(plr, pcity);
7162 }
7163 } else if (!game.server.foggedborders && map_is_known(ptile, plr)) {
7164 /* Non fogged borders aren't loaded. See hrm Bug #879084 */
7165 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7166
7167 plrtile->owner = tile_owner(ptile);
7168 }
7169 } whole_map_iterate_end;
7170}
7171
7172/************************************************************************/
7175 static bool sg_load_player_vision_city(struct loaddata *loading,
7176 struct player *plr,
7177 struct vision_site *pdcity,
7178 const char *citystr)
7179{
7180 const char *str;
7181 int i, id, size;
7182 citizens city_size;
7183 int nat_x, nat_y;
7184 const char *stylename;
7185 enum capital_type cap;
7186 const char *vname;
7187
7188 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_x, "%s.x",
7189 citystr),
7190 FALSE, "%s", secfile_error());
7191 sg_warn_ret_val(secfile_lookup_int(loading->file, &nat_y, "%s.y",
7192 citystr),
7193 FALSE, "%s", secfile_error());
7194 pdcity->location = native_pos_to_tile(&(wld.map), nat_x, nat_y);
7195 sg_warn_ret_val(NULL != pdcity->location, FALSE,
7196 "%s invalid tile (%d,%d)", citystr, nat_x, nat_y);
7197
7198 sg_warn_ret_val(secfile_lookup_int(loading->file, &id, "%s.owner",
7199 citystr),
7200 FALSE, "%s", secfile_error());
7201 pdcity->owner = player_by_number(id);
7202 sg_warn_ret_val(NULL != pdcity->owner, FALSE,
7203 "%s has invalid owner (%d); skipping.", citystr, id);
7204
7205 sg_warn_ret_val(secfile_lookup_int(loading->file, &pdcity->identity,
7206 "%s.id", citystr),
7207 FALSE, "%s", secfile_error());
7208 sg_warn_ret_val(IDENTITY_NUMBER_ZERO < pdcity->identity, FALSE,
7209 "%s has invalid id (%d); skipping.", citystr, id);
7210
7211 sg_warn_ret_val(secfile_lookup_int(loading->file, &size,
7212 "%s.size", citystr),
7213 FALSE, "%s", secfile_error());
7214 city_size = (citizens)size; /* set the correct type */
7215 sg_warn_ret_val(size == (int)city_size, FALSE,
7216 "Invalid city size: %d; set to %d.", size, city_size);
7217 vision_site_size_set(pdcity, city_size);
7218
7219 /* Initialise list of improvements */
7220 BV_CLR_ALL(pdcity->improvements);
7221 str = secfile_lookup_str(loading->file, "%s.improvements", citystr);
7222 sg_warn_ret_val(str != NULL, FALSE, "%s", secfile_error());
7223 sg_warn_ret_val(strlen(str) == loading->improvement.size, FALSE,
7224 "Invalid length of '%s.improvements' ("
7225 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7226 citystr, strlen(str), loading->improvement.size);
7227 for (i = 0; i < loading->improvement.size; i++) {
7228 sg_warn_ret_val(str[i] == '1' || str[i] == '0', FALSE,
7229 "Undefined value '%c' within '%s.improvements'.",
7230 str[i], citystr)
7231
7232 if (str[i] == '1') {
7233 struct impr_type *pimprove =
7234 improvement_by_rule_name(loading->improvement.order[i]);
7235 if (pimprove) {
7236 BV_SET(pdcity->improvements, improvement_index(pimprove));
7237 }
7238 }
7239 }
7240
7241 vname = secfile_lookup_str_default(loading->file, NULL,
7242 "%s.name", citystr);
7243
7244 if (vname != NULL) {
7245 pdcity->name = fc_strdup(vname);
7246 }
7247
7248 pdcity->occupied = secfile_lookup_bool_default(loading->file, FALSE,
7249 "%s.occupied", citystr);
7250 pdcity->walls = secfile_lookup_bool_default(loading->file, FALSE,
7251 "%s.walls", citystr);
7252 pdcity->happy = secfile_lookup_bool_default(loading->file, FALSE,
7253 "%s.happy", citystr);
7254 pdcity->unhappy = secfile_lookup_bool_default(loading->file, FALSE,
7255 "%s.unhappy", citystr);
7256 stylename = secfile_lookup_str_default(loading->file, NULL,
7257 "%s.style", citystr);
7258 if (stylename != NULL) {
7259 pdcity->style = city_style_by_rule_name(stylename);
7260 } else {
7261 pdcity->style = 0;
7262 }
7263 if (pdcity->style < 0) {
7264 pdcity->style = 0;
7265 }
7266
7267 pdcity->city_image = secfile_lookup_int_default(loading->file, -100,
7268 "%s.city_image", citystr);
7269
7270 cap = capital_type_by_name(secfile_lookup_str_default(loading->file, NULL,
7271 "%s.capital", citystr),
7272 fc_strcasecmp);
7273
7274 if (capital_type_is_valid(cap)) {
7275 pdcity->capital = cap;
7276 } else {
7277 pdcity->capital = CAPITAL_NOT;
7278 }
7279
7280 return TRUE;
7281}
7282
7283/************************************************************************/
7286 static void sg_save_player_vision(struct savedata *saving,
7287 struct player *plr)
7288{
7289 int i, plrno = player_number(plr);
7290
7291 /* Check status and return if not OK (sg_success FALSE). */
7292 sg_check_ret();
7293
7294 if (!game.info.fogofwar || !game.server.save_options.save_private_map) {
7295 /* The player can see all, there's no reason to save the private map. */
7296 return;
7297 }
7298
7299 /* Save the map (terrain). */
7300 SAVE_MAP_CHAR(ptile,
7301 terrain2char(map_get_player_tile(ptile, plr)->terrain),
7302 saving->file, "player%d.map_t%04d", plrno);
7303
7304 if (game.server.foggedborders) {
7305 /* Save the map (borders). */
7306 int x, y;
7307
7308 for (y = 0; y < wld.map.ysize; y++) {
7309 char line[wld.map.xsize * TOKEN_SIZE];
7310
7311 line[0] = '\0';
7312 for (x = 0; x < wld.map.xsize; x++) {
7313 char token[TOKEN_SIZE];
7314 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7315 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7316
7317 if (plrtile == NULL || plrtile->owner == NULL) {
7318 strcpy(token, "-");
7319 } else {
7320 fc_snprintf(token, sizeof(token), "%d",
7321 player_number(plrtile->owner));
7322 }
7323 strcat(line, token);
7324 if (x < wld.map.xsize) {
7325 strcat(line, ",");
7326 }
7327 }
7328 secfile_insert_str(saving->file, line, "player%d.map_owner%04d",
7329 plrno, y);
7330 }
7331
7332 for (y = 0; y < wld.map.ysize; y++) {
7333 char line[wld.map.xsize * TOKEN_SIZE];
7334
7335 line[0] = '\0';
7336 for (x = 0; x < wld.map.xsize; x++) {
7337 char token[TOKEN_SIZE];
7338 struct tile *ptile = native_pos_to_tile(&(wld.map), x, y);
7339 struct player_tile *plrtile = map_get_player_tile(ptile, plr);
7340
7341 if (plrtile == NULL || plrtile->extras_owner == NULL) {
7342 strcpy(token, "-");
7343 } else {
7344 fc_snprintf(token, sizeof(token), "%d",
7345 player_number(plrtile->extras_owner));
7346 }
7347 strcat(line, token);
7348 if (x < wld.map.xsize) {
7349 strcat(line, ",");
7350 }
7351 }
7352 secfile_insert_str(saving->file, line, "player%d.extras_owner%04d",
7353 plrno, y);
7354 }
7355 }
7356
7357 /* Save the map (extras). */
7358 halfbyte_iterate_extras(j, game.control.num_extra_types) {
7359 int mod[4];
7360 int l;
7361
7362 for (l = 0; l < 4; l++) {
7363 if (4 * j + 1 > game.control.num_extra_types) {
7364 mod[l] = -1;
7365 } else {
7366 mod[l] = 4 * j + l;
7367 }
7368 }
7369
7370 SAVE_MAP_CHAR(ptile,
7371 sg_extras_get_dbv(&(map_get_player_tile(ptile, plr)->extras),
7372 map_get_player_tile(ptile, plr)->resource,
7373 mod),
7374 saving->file, "player%d.map_e%02d_%04d", plrno, j);
7375 } halfbyte_iterate_extras_end;
7376
7377 /* Save the map (update time). */
7378 for (i = 0; i < 4; i++) {
7379 /* put 4-bit segments of 16-bit "updated" field */
7380 SAVE_MAP_CHAR(ptile,
7381 bin2ascii_hex(
7382 map_get_player_tile(ptile, plr)->last_updated, i),
7383 saving->file, "player%d.map_u%02d_%04d", plrno, i);
7384 }
7385
7386 /* Save known cities. */
7387 i = 0;
7388 whole_map_iterate(&(wld.map), ptile) {
7389 struct vision_site *pdcity = map_get_player_city(ptile, plr);
7390 char impr_buf[B_LAST + 1];
7391 char buf[32];
7392
7393 fc_snprintf(buf, sizeof(buf), "player%d.dc%d", plrno, i);
7394
7395 if (NULL != pdcity && plr != vision_site_owner(pdcity)) {
7396 int nat_x, nat_y;
7397
7398 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
7399 secfile_insert_int(saving->file, nat_y, "%s.y", buf);
7400 secfile_insert_int(saving->file, nat_x, "%s.x", buf);
7401
7402 secfile_insert_int(saving->file, pdcity->identity, "%s.id", buf);
7403 secfile_insert_int(saving->file, player_number(vision_site_owner(pdcity)),
7404 "%s.owner", buf);
7405
7406 secfile_insert_int(saving->file, vision_site_size_get(pdcity),
7407 "%s.size", buf);
7408 secfile_insert_bool(saving->file, pdcity->occupied,
7409 "%s.occupied", buf);
7410 secfile_insert_bool(saving->file, pdcity->walls, "%s.walls", buf);
7411 secfile_insert_bool(saving->file, pdcity->happy, "%s.happy", buf);
7412 secfile_insert_bool(saving->file, pdcity->unhappy, "%s.unhappy", buf);
7413 secfile_insert_str(saving->file, city_style_rule_name(pdcity->style),
7414 "%s.style", buf);
7415 secfile_insert_int(saving->file, pdcity->city_image, "%s.city_image", buf);
7416 secfile_insert_str(saving->file, capital_type_name(pdcity->capital),
7417 "%s.capital", buf);
7418
7419 /* Save improvement list as bitvector. Note that improvement order
7420 * is saved in savefile.improvement.order. */
7421 improvement_iterate(pimprove) {
7422 impr_buf[improvement_index(pimprove)]
7423 = BV_ISSET(pdcity->improvements, improvement_index(pimprove))
7424 ? '1' : '0';
7425 } improvement_iterate_end;
7426 impr_buf[improvement_count()] = '\0';
7427 sg_failure_ret(strlen(impr_buf) < sizeof(impr_buf),
7428 "Invalid size of the improvement vector (%s.improvements: "
7429 SIZE_T_PRINTF " < " SIZE_T_PRINTF" ).",
7430 buf, strlen(impr_buf), sizeof(impr_buf));
7431 secfile_insert_str(saving->file, impr_buf, "%s.improvements", buf);
7432 if (pdcity->name != NULL) {
7433 secfile_insert_str(saving->file, pdcity->name, "%s.name", buf);
7434 }
7435
7436 i++;
7437 }
7438 } whole_map_iterate_end;
7439
7440 secfile_insert_int(saving->file, i, "player%d.dc_total", plrno);
7441}
7442
7443/* =======================================================================
7444 * Load / save the researches.
7445 * ======================================================================= */
7446
7447/************************************************************************/
7450 static void sg_load_researches(struct loaddata *loading)
7451{
7452 struct research *presearch;
7453 int count;
7454 int number;
7455 const char *str;
7456 int i, j;
7457 int *vlist_research;
7458
7459 vlist_research = NULL;
7460 /* Check status and return if not OK (sg_success FALSE). */
7461 sg_check_ret();
7462
7463 /* Initialize all researches. */
7464 researches_iterate(pinitres) {
7465 init_tech(pinitres, FALSE);
7466 } researches_iterate_end;
7467
7468 /* May be unsaved (e.g. scenario case). */
7469 count = secfile_lookup_int_default(loading->file, 0, "research.count");
7470 for (i = 0; i < count; i++) {
7471 sg_failure_ret(secfile_lookup_int(loading->file, &number,
7472 "research.r%d.number", i),
7473 "%s", secfile_error());
7474 presearch = research_by_number(number);
7475 sg_failure_ret(presearch != NULL,
7476 "Invalid research number %d in 'research.r%d.number'",
7477 number, i);
7478
7479 presearch->tech_goal = technology_load(loading->file,
7480 "research.r%d.goal", i);
7481 sg_failure_ret(secfile_lookup_int(loading->file,
7482 &presearch->techs_researched,
7483 "research.r%d.techs", i),
7484 "%s", secfile_error());
7485 sg_failure_ret(secfile_lookup_int(loading->file,
7486 &presearch->future_tech,
7487 "research.r%d.futuretech", i),
7488 "%s", secfile_error());
7489 sg_failure_ret(secfile_lookup_int(loading->file,
7490 &presearch->bulbs_researched,
7491 "research.r%d.bulbs", i),
7492 "%s", secfile_error());
7493 sg_failure_ret(secfile_lookup_int(loading->file,
7494 &presearch->bulbs_researching_saved,
7495 "research.r%d.bulbs_before", i),
7496 "%s", secfile_error());
7497 presearch->researching_saved = technology_load(loading->file,
7498 "research.r%d.saved", i);
7499 presearch->researching = technology_load(loading->file,
7500 "research.r%d.now", i);
7501 sg_failure_ret(secfile_lookup_int(loading->file,
7502 &presearch->free_bulbs,
7503 "research.r%d.free_bulbs", i),
7504 "%s", secfile_error());
7505
7506 str = secfile_lookup_str(loading->file, "research.r%d.done", i);
7507 sg_failure_ret(str != NULL, "%s", secfile_error());
7508 sg_failure_ret(strlen(str) == loading->technology.size,
7509 "Invalid length of 'research.r%d.done' ("
7510 SIZE_T_PRINTF " ~= " SIZE_T_PRINTF ").",
7511 i, strlen(str), loading->technology.size);
7512 for (j = 0; j < loading->technology.size; j++) {
7513 sg_failure_ret(str[j] == '1' || str[j] == '0',
7514 "Undefined value '%c' within 'research.r%d.done'.",
7515 str[j], i);
7516
7517 if (str[j] == '1') {
7518 struct advance *padvance =
7519 advance_by_rule_name(loading->technology.order[j]);
7520
7521 if (padvance) {
7522 research_invention_set(presearch, advance_number(padvance),
7523 TECH_KNOWN);
7524 }
7525 }
7526 }
7527
7528 if (game.server.multiresearch) {
7529 size_t count_res;
7530 int tn;
7531
7532 vlist_research = secfile_lookup_int_vec(loading->file, &count_res,
7533 "research.r%d.vbs", i);
7534
7535 for (tn = 0; tn < count_res; tn++) {
7536 struct advance *padvance = advance_by_rule_name(loading->technology.order[tn]);
7537
7538 if (padvance != NULL) {
7539 presearch->inventions[advance_index(padvance)].bulbs_researched_saved
7540 = vlist_research[tn];
7541 }
7542 }
7543 }
7544 }
7545
7546 /* In case of tech_leakage, we can update research only after all the
7547 * researches have been loaded */
7548 researches_iterate(pupres) {
7549 research_update(pupres);
7550 } researches_iterate_end;
7551}
7552
7553/************************************************************************/
7556 static void sg_save_researches(struct savedata *saving)
7557{
7558 char invs[A_LAST];
7559 int i = 0;
7560 int *vlist_research;
7561
7562 vlist_research = NULL;
7563 /* Check status and return if not OK (sg_success FALSE). */
7564 sg_check_ret();
7565
7566 if (saving->save_players) {
7567 researches_iterate(presearch) {
7568 secfile_insert_int(saving->file, research_number(presearch),
7569 "research.r%d.number", i);
7570 technology_save(saving->file, "research.r%d.goal",
7571 i, presearch->tech_goal);
7572 secfile_insert_int(saving->file, presearch->techs_researched,
7573 "research.r%d.techs", i);
7574 secfile_insert_int(saving->file, presearch->future_tech,
7575 "research.r%d.futuretech", i);
7576 secfile_insert_int(saving->file, presearch->bulbs_researching_saved,
7577 "research.r%d.bulbs_before", i);
7578 if (game.server.multiresearch) {
7579 vlist_research = fc_calloc(game.control.num_tech_types, sizeof(int));
7580 advance_index_iterate(A_FIRST, j) {
7581 vlist_research[j] = presearch->inventions[j].bulbs_researched_saved;
7582 } advance_index_iterate_end;
7583 secfile_insert_int_vec(saving->file, vlist_research,
7584 game.control.num_tech_types,
7585 "research.r%d.vbs", i);
7586 if (vlist_research) {
7587 free(vlist_research);
7588 }
7589 }
7590 technology_save(saving->file, "research.r%d.saved",
7591 i, presearch->researching_saved);
7592 secfile_insert_int(saving->file, presearch->bulbs_researched,
7593 "research.r%d.bulbs", i);
7594 technology_save(saving->file, "research.r%d.now",
7595 i, presearch->researching);
7596 secfile_insert_int(saving->file, presearch->free_bulbs,
7597 "research.r%d.free_bulbs", i);
7598 /* Save technology lists as bytevector. Note that technology order is
7599 * saved in savefile.technology.order */
7600 advance_index_iterate(A_NONE, tech_id) {
7601 invs[tech_id] = (valid_advance_by_number(tech_id) != NULL
7602 && research_invention_state(presearch, tech_id)
7603 == TECH_KNOWN ? '1' : '0');
7604 } advance_index_iterate_end;
7605 invs[game.control.num_tech_types] = '\0';
7606 secfile_insert_str(saving->file, invs, "research.r%d.done", i);
7607 i++;
7608 } researches_iterate_end;
7609 secfile_insert_int(saving->file, i, "research.count");
7610 }
7611}
7612
7613/* =======================================================================
7614 * Load / save the event cache. Should be the last thing to do.
7615 * ======================================================================= */
7616
7617/************************************************************************/
7620 static void sg_load_event_cache(struct loaddata *loading)
7621{
7622 /* Check status and return if not OK (sg_success FALSE). */
7623 sg_check_ret();
7624
7625 event_cache_load(loading->file, "event_cache");
7626}
7627
7628/************************************************************************/
7631 static void sg_save_event_cache(struct savedata *saving)
7632{
7633 /* Check status and return if not OK (sg_success FALSE). */
7634 sg_check_ret();
7635
7636 if (saving->scenario) {
7637 /* Do _not_ save events in a scenario. */
7638 return;
7639 }
7640
7641 event_cache_save(saving->file, "event_cache");
7642}
7643
7644/* =======================================================================
7645 * Load / save the open treaties
7646 * ======================================================================= */
7647
7648/************************************************************************/
7651 static void sg_load_treaties(struct loaddata *loading)
7652{
7653 int tidx;
7654 const char *plr0;
7655
7656 /* Check status and return if not OK (sg_success FALSE). */
7657 sg_check_ret();
7658
7659 for (tidx = 0; (plr0 = secfile_lookup_str_default(loading->file, NULL,
7660 "treaty%d.plr0", tidx)) != NULL ;
7661 tidx++) {
7662 const char *plr1;
7663 const char *ct;
7664 int cidx;
7665 struct player *p0, *p1;
7666
7667 plr1 = secfile_lookup_str(loading->file, "treaty%d.plr1", tidx);
7668
7669 p0 = player_by_name(plr0);
7670 p1 = player_by_name(plr1);
7671
7672 if (p0 == NULL || p1 == NULL) {
7673 log_error("Treaty between unknown players %s and %s", plr0, plr1);
7674 } else {
7675 struct Treaty *ptreaty = fc_malloc(sizeof(*ptreaty));
7676
7677 init_treaty(ptreaty, p0, p1);
7678 treaty_add(ptreaty);
7679
7680 for (cidx = 0; (ct = secfile_lookup_str_default(loading->file, NULL,
7681 "treaty%d.clause%d.type",
7682 tidx, cidx)) != NULL ;
7683 cidx++ ) {
7684 enum clause_type type = clause_type_by_name(ct, fc_strcasecmp);
7685 const char *plrx;
7686
7687 if (!clause_type_is_valid(type)) {
7688 log_error("Invalid clause type \"%s\"", ct);
7689 } else {
7690 struct player *pgiver = NULL;
7691
7692 plrx = secfile_lookup_str(loading->file, "treaty%d.clause%d.from",
7693 tidx, cidx);
7694
7695 if (!fc_strcasecmp(plrx, plr0)) {
7696 pgiver = p0;
7697 } else if (!fc_strcasecmp(plrx, plr1)) {
7698 pgiver = p1;
7699 } else {
7700 log_error("Clause giver %s is not participant of the treaty"
7701 "between %s and %s", plrx, plr0, plr1);
7702 }
7703
7704 if (pgiver != NULL) {
7705 int value;
7706
7707 value = secfile_lookup_int_default(loading->file, 0,
7708 "treaty%d.clause%d.value",
7709 tidx, cidx);
7710
7711 add_clause(ptreaty, pgiver, type, value, NULL);
7712 }
7713 }
7714 }
7715
7716 /* These must be after clauses have been added so that acceptance
7717 * does not get cleared by what seems like changes to the treaty. */
7718 ptreaty->accept0 = secfile_lookup_bool_default(loading->file, FALSE,
7719 "treaty%d.accept0", tidx);
7720 ptreaty->accept1 = secfile_lookup_bool_default(loading->file, FALSE,
7721 "treaty%d.accept1", tidx);
7722 }
7723 }
7724}
7725
7726 typedef struct {
7727 int tidx;
7728 struct section_file *file;
7729} treaty_cb_data;
7730
7731/************************************************************************/
7734 static void treaty_save(struct Treaty *ptr, void *data_in)
7735{
7736 char tpath[512];
7737 int cidx = 0;
7738 treaty_cb_data *data = (treaty_cb_data *)data_in;
7739
7740 fc_snprintf(tpath, sizeof(tpath), "treaty%d", data->tidx++);
7741
7742 secfile_insert_str(data->file, player_name(ptr->plr0), "%s.plr0", tpath);
7743 secfile_insert_str(data->file, player_name(ptr->plr1), "%s.plr1", tpath);
7744 secfile_insert_bool(data->file, ptr->accept0, "%s.accept0", tpath);
7745 secfile_insert_bool(data->file, ptr->accept1, "%s.accept1", tpath);
7746
7747 clause_list_iterate(ptr->clauses, pclaus) {
7748 char cpath[512];
7749
7750 fc_snprintf(cpath, sizeof(cpath), "%s.clause%d", tpath, cidx++);
7751
7752 secfile_insert_str(data->file, clause_type_name(pclaus->type), "%s.type", cpath);
7753 secfile_insert_str(data->file, player_name(pclaus->from), "%s.from", cpath);
7754 secfile_insert_int(data->file, pclaus->value, "%s.value", cpath);
7755 } clause_list_iterate_end;
7756}
7757
7758/************************************************************************/
7761 static void sg_save_treaties(struct savedata *saving)
7762{
7763 treaty_cb_data data = { .tidx = 0, .file = saving->file };
7764
7765 treaties_iterate(treaty_save, &data);
7766}
7767
7768/* =======================================================================
7769 * Load / save the history report
7770 * ======================================================================= */
7771
7772/************************************************************************/
7775 static void sg_load_history(struct loaddata *loading)
7776{
7777 struct history_report *hist = history_report_get();
7778 int turn;
7779
7780 /* Check status and return if not OK (sg_success FALSE). */
7781 sg_check_ret();
7782
7783 turn = secfile_lookup_int_default(loading->file, -2, "history.turn");
7784
7785 if (turn + 1 >= game.info.turn) {
7786 const char *str;
7787
7788 hist->turn = turn;
7789 str = secfile_lookup_str(loading->file, "history.title");
7790 sg_failure_ret(str != NULL, "%s", secfile_error());
7791 sz_strlcpy(hist->title, str);
7792 str = secfile_lookup_str(loading->file, "history.body");
7793 sg_failure_ret(str != NULL, "%s", secfile_error());
7794 sz_strlcpy(hist->body, str);
7795 }
7796}
7797
7798/************************************************************************/
7801 static void sg_save_history(struct savedata *saving)
7802{
7803 struct history_report *hist = history_report_get();
7804
7805 secfile_insert_int(saving->file, hist->turn, "history.turn");
7806
7807 if (hist->turn + 1 >= game.info.turn) {
7808 secfile_insert_str(saving->file, hist->title, "history.title");
7809 secfile_insert_str(saving->file, hist->body, "history.body");
7810 }
7811}
7812
7813/* =======================================================================
7814 * Load / save the mapimg definitions.
7815 * ======================================================================= */
7816
7817/************************************************************************/
7820 static void sg_load_mapimg(struct loaddata *loading)
7821{
7822 int mapdef_count, i;
7823
7824 /* Check status and return if not OK (sg_success FALSE). */
7825 sg_check_ret();
7826
7827 /* Clear all defined map images. */
7828 while (mapimg_count() > 0) {
7829 mapimg_delete(0);
7830 }
7831
7832 mapdef_count = secfile_lookup_int_default(loading->file, 0,
7833 "mapimg.count");
7834 log_verbose("Saved map image definitions: %d.", mapdef_count);
7835
7836 if (0 >= mapdef_count) {
7837 return;
7838 }
7839
7840 for (i = 0; i < mapdef_count; i++) {
7841 const char *p;
7842
7843 p = secfile_lookup_str(loading->file, "mapimg.mapdef%d", i);
7844 if (NULL == p) {
7845 log_verbose("[Mapimg %4d] Missing definition.", i);
7846 continue;
7847 }
7848
7849 if (!mapimg_define(p, FALSE)) {
7850 log_error("Invalid map image definition %4d: %s.", i, p);
7851 }
7852
7853 log_verbose("Mapimg %4d loaded.", i);
7854 }
7855}
7856
7857/************************************************************************/
7860 static void sg_save_mapimg(struct savedata *saving)
7861{
7862 /* Check status and return if not OK (sg_success FALSE). */
7863 sg_check_ret();
7864
7865 secfile_insert_int(saving->file, mapimg_count(), "mapimg.count");
7866 if (mapimg_count() > 0) {
7867 int i;
7868
7869 for (i = 0; i < mapimg_count(); i++) {
7870 char buf[MAX_LEN_MAPDEF];
7871
7872 mapimg_id2str(i, buf, sizeof(buf));
7873 secfile_insert_str(saving->file, buf, "mapimg.mapdef%d", i);
7874 }
7875 }
7876}
7877
7878/* =======================================================================
7879 * Sanity checks for loading / saving a game.
7880 * ======================================================================= */
7881
7882/************************************************************************/
7885 static void sg_load_sanitycheck(struct loaddata *loading)
7886{
7887 int players;
7888
7889 /* Check status and return if not OK (sg_success FALSE). */
7890 sg_check_ret();
7891
7892 if (game.info.is_new_game) {
7893 /* Nothing to do for new games (or not started scenarios). */
7894 return;
7895 }
7896
7897 /* Old savegames may have maxplayers lower than current player count,
7898 * fix. */
7899 players = normal_player_count();
7900 if (game.server.max_players < players) {
7901 log_verbose("Max players lower than current players, fixing");
7902 game.server.max_players = players;
7903 }
7904
7905 /* Fix ferrying sanity */
7906 players_iterate(pplayer) {
7907 unit_list_iterate_safe(pplayer->units, punit) {
7908 if (!unit_transport_get(punit)
7909 && !can_unit_exist_at_tile(&(wld.map), punit, unit_tile(punit))) {
7910 log_sg("Removing %s unferried %s in %s at (%d, %d)",
7911 nation_rule_name(nation_of_player(pplayer)),
7912 unit_rule_name(punit),
7913 terrain_rule_name(unit_tile(punit)->terrain),
7914 TILE_XY(unit_tile(punit)));
7915 bounce_unit(punit, TRUE);
7916 }
7917 } unit_list_iterate_safe_end;
7918 } players_iterate_end;
7919
7920 /* Fix stacking issues. We don't rely on the savegame preserving
7921 * alliance invariants (old savegames often did not) so if there are any
7922 * unallied units on the same tile we just bounce them. */
7923 players_iterate(pplayer) {
7924 players_iterate(aplayer) {
7925 resolve_unit_stacks(pplayer, aplayer, TRUE);
7926 } players_iterate_end;
7927 } players_iterate_end;
7928
7929 /* Recalculate the potential buildings for each city. Has caused some
7930 * problems with game random state.
7931 * This also changes the game state if you save the game directly after
7932 * loading it and compare the results. */
7933 players_iterate(pplayer) {
7934 /* Building advisor needs data phase open in order to work */
7935 adv_data_phase_init(pplayer, FALSE);
7936 building_advisor(pplayer);
7937 /* Close data phase again so it can be opened again when game starts. */
7938 adv_data_phase_done(pplayer);
7939 } players_iterate_end;
7940
7941 /* Prevent a buggy or intentionally crafted save game from crashing
7942 * Freeciv. See hrm Bug #887748 */
7943 players_iterate(pplayer) {
7944 city_list_iterate(pplayer->cities, pcity) {
7945 worker_task_list_iterate(pcity->task_reqs, ptask) {
7946 if (!worker_task_is_sane(ptask)) {
7947 log_error("[city id: %d] Bad worker task %d.",
7948 pcity->id, ptask->act);
7949 worker_task_list_remove(pcity->task_reqs, ptask);
7950 free(ptask);
7951 ptask = NULL;
7952 }
7953 } worker_task_list_iterate_end;
7954 } city_list_iterate_end;
7955 } players_iterate_end;
7956
7957 /* Check worked tiles map */
7958#ifdef FREECIV_DEBUG
7959 if (loading->worked_tiles != NULL) {
7960 /* check the entire map for unused worked tiles */
7961 whole_map_iterate(&(wld.map), ptile) {
7962 if (loading->worked_tiles[ptile->index] != -1) {
7963 log_error("[city id: %d] Unused worked tile at (%d, %d).",
7964 loading->worked_tiles[ptile->index], TILE_XY(ptile));
7965 }
7966 } whole_map_iterate_end;
7967 }
7968#endif /* FREECIV_DEBUG */
7969
7970 /* Check researching technologies and goals. */
7971 researches_iterate(presearch) {
7972 int techs;
7973
7974 if (presearch->researching != A_UNSET
7975 && !is_future_tech(presearch->researching)
7976 && (valid_advance_by_number(presearch->researching) == NULL
7977 || (research_invention_state(presearch, presearch->researching)
7978 != TECH_PREREQS_KNOWN))) {
7979 log_sg(_("%s had invalid researching technology."),
7980 research_name_translation(presearch));
7981 presearch->researching = A_UNSET;
7982 }
7983 if (presearch->tech_goal != A_UNSET
7984 && !is_future_tech(presearch->tech_goal)
7985 && (valid_advance_by_number(presearch->tech_goal) == NULL
7986 || !research_invention_reachable(presearch, presearch->tech_goal)
7987 || (research_invention_state(presearch, presearch->tech_goal)
7988 == TECH_KNOWN))) {
7989 log_sg(_("%s had invalid technology goal."),
7990 research_name_translation(presearch));
7991 presearch->tech_goal = A_UNSET;
7992 }
7993
7994 techs = recalculate_techs_researched(presearch);
7995
7996 if (presearch->techs_researched != techs) {
7997 sg_regr(3000300,
7998 _("%s had finished researches count wrong."),
7999 research_name_translation(presearch));
8000 presearch->techs_researched = techs;
8001 }
8002 } researches_iterate_end;
8003
8004 /* Check if some player has more than one of some UTYF_UNIQUE unit type */
8005 players_iterate(pplayer) {
8006 int unique_count[U_LAST];
8007
8008 memset(unique_count, 0, sizeof(unique_count));
8009
8010 unit_list_iterate(pplayer->units, punit) {
8011 unique_count[utype_index(unit_type_get(punit))]++;
8012 } unit_list_iterate_end;
8013
8014 unit_type_iterate(ut) {
8015 if (unique_count[utype_index(ut)] > 1 && utype_has_flag(ut, UTYF_UNIQUE)) {
8016 log_sg(_("%s has multiple units of type %s though it should be possible "
8017 "to have only one."),
8018 player_name(pplayer), utype_name_translation(ut));
8019 }
8020 } unit_type_iterate_end;
8021 } players_iterate_end;
8022
8023 players_iterate(pplayer) {
8024 unit_list_iterate_safe(pplayer->units, punit) {
8025 if (!unit_order_list_is_sane(&(wld.map), punit->orders.length,
8026 punit->orders.list)) {
8027 log_sg("Invalid unit orders for unit %d.", punit->id);
8028 free_unit_orders(punit);
8029 }
8030 } unit_list_iterate_safe_end;
8031 } players_iterate_end;
8032
8033 /* Check max rates (rules may have changed since saving) */
8034 players_iterate(pplayer) {
8035 player_limit_to_max_rates(pplayer);
8036 } players_iterate_end;
8037
8038 if (0 == strlen(server.game_identifier)
8039 || !is_base64url(server.game_identifier)) {
8040 /* This uses fc_rand(), so random state has to be initialized before. */
8041 randomize_base64url_string(server.game_identifier,
8042 sizeof(server.game_identifier));
8043 }
8044
8045 /* Restore game random state, just in case various initialization code
8046 * inexplicably altered the previously existing state. */
8047 if (!game.info.is_new_game) {
8048 fc_rand_set_state(loading->rstate);
8049 }
8050
8051 /* At the end do the default sanity checks. */
8052 sanity_check();
8053}
8054
8055/************************************************************************/
8058 static void sg_save_sanitycheck(struct savedata *saving)
8059{
8060 /* Check status and return if not OK (sg_success FALSE). */
8061 sg_check_ret();
8062}
achievement_player_has
bool achievement_player_has(const struct achievement *pach, const struct player *pplayer)
Definition achievements.c:364
achievement_rule_name
const char * achievement_rule_name(struct achievement *pach)
Definition achievements.c:114
achievement_by_rule_name
struct achievement * achievement_by_rule_name(const char *name)
Definition achievements.c:123
achievements.h
achievements_iterate_end
#define achievements_iterate_end
Definition achievements.h:70
achievements_iterate
#define achievements_iterate(_ach_)
Definition achievements.h:64
actions
static struct action * actions[MAX_NUM_ACTIONS]
Definition actions.c:97
action_id_name_translation
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2002
action_by_rule_name
struct action * action_by_rule_name(const char *name)
Definition actions.c:1831
action_id_rule_name
const char * action_id_rule_name(action_id act_id)
Definition actions.c:1991
action_id_exists
bool action_id_exists(const action_id act_id)
Definition actions.c:1820
action_id_get_sub_target_kind
#define action_id_get_sub_target_kind(act_id)
Definition actions.h:654
NUM_ACTIONS
#define NUM_ACTIONS
Definition actions.h:313
action_id_get_activity
#define action_id_get_activity(act_id)
Definition actions.h:699
ACTION_NONE
#define ACTION_NONE
Definition actions.h:309
building_advisor
void building_advisor(struct player *pplayer)
Definition advbuilding.c:175
advbuilding.h
adv_data_phase_init
bool adv_data_phase_init(struct player *pplayer, bool is_new_phase)
Definition advdata.c:263
adv_data_phase_done
void adv_data_phase_done(struct player *pplayer)
Definition advdata.c:565
advdata.h
ai_name
const char * ai_name(const struct ai_type *ai)
Definition ai.c:335
ai_type_get_count
int ai_type_get_count(void)
Definition ai.c:327
ai.h
CALL_FUNC_EACH_AI
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
CALL_PLR_AI_FUNC
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
ai_type_iterate_end
#define ai_type_iterate_end
Definition ai.h:369
ai_type_iterate
#define ai_type_iterate(NAME_ai)
Definition ai.h:362
ai_traits_init
void ai_traits_init(struct player *pplayer)
Definition aitraits.c:33
aitraits.h
str
#define str
Definition astring.c:76
barbarian.h
dbv_bits
int dbv_bits(struct dbv *pdbv)
Definition bitvector.c:108
dbv_set
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
dbv_isset
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
dbv_clr_all
void dbv_clr_all(struct dbv *pdbv)
Definition bitvector.c:179
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
BV_CLR
#define BV_CLR(bv, bit)
Definition bitvector.h:86
has_capabilities
bool has_capabilities(const char *us, const char *them)
Definition capability.c:86
capability.h
citizens_nation_get
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
citizens_nation_set
void citizens_nation_set(struct city *pcity, const struct player_slot *pslot, citizens count)
Definition citizens.c:145
citizens_count
citizens citizens_count(const struct city *pcity)
Definition citizens.c:162
citizens_init
void citizens_init(struct city *pcity)
Definition citizens.c:32
citizens.h
citizens_update
void citizens_update(struct city *pcity, struct player *plr)
Definition citizenshand.c:202
citizenshand.h
city_map_radius_sq_set
void city_map_radius_sq_set(struct city *pcity, int radius_sq)
Definition city.c:147
city_name_set
void city_name_set(struct city *pcity, const char *new_name)
Definition city.c:1136
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1128
city_style_rule_name
const char * city_style_rule_name(const int style)
Definition city.c:1757
create_city_virtual
struct city * create_city_virtual(struct player *pplayer, struct tile *ptile, const char *name)
Definition city.c:3418
city_illness_calc
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2861
city_size_set
void city_size_set(struct city *pcity, citizens size)
Definition city.c:1171
city_add_improvement
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Definition city.c:3345
destroy_city_virtual
void destroy_city_virtual(struct city *pcity)
Definition city.c:3504
city_style_by_rule_name
int city_style_by_rule_name(const char *s)
Definition city.c:1730
city.h
cities_iterate_end
#define cities_iterate_end
Definition city.h:517
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:508
city_tile
#define city_tile(_pcity_)
Definition city.h:564
cities_iterate
#define cities_iterate(pcity)
Definition city.h:512
CITY_MAP_MAX_RADIUS_SQ
#define CITY_MAP_MAX_RADIUS_SQ
Definition city.h:86
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
output_type_iterate
#define output_type_iterate(output)
Definition city.h:833
FREE_WORKED_TILES
#define FREE_WORKED_TILES
Definition city.h:870
MAX_CITY_SIZE
#define MAX_CITY_SIZE
Definition city.h:106
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:510
I_NEVER
#define I_NEVER
Definition city.h:247
city_tile_iterate
#define city_tile_iterate(_nmap, _radius_sq, _city_tile, _tile)
Definition city.h:230
city_tile_iterate_end
#define city_tile_iterate_end
Definition city.h:238
output_type_iterate_end
#define output_type_iterate_end
Definition city.h:839
update_dumb_city
bool update_dumb_city(struct player *pplayer, struct city *pcity)
Definition citytools.c:2740
send_city_suppression
bool send_city_suppression(bool now)
Definition citytools.c:2152
city_freeze_workers
static void void city_freeze_workers(struct city *pcity)
Definition citytools.c:137
city_thaw_workers
void city_thaw_workers(struct city *pcity)
Definition citytools.c:147
reality_check_city
void reality_check_city(struct player *pplayer, struct tile *ptile)
Definition citytools.c:2811
city_refresh_vision
void city_refresh_vision(struct city *pcity)
Definition citytools.c:3413
citytools.h
auto_arrange_workers
void auto_arrange_workers(struct city *pcity)
Definition cityturn.c:366
city_repair_size
void city_repair_size(struct city *pcity, int change)
Definition cityturn.c:851
city_refresh
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
cityturn.h
techs
char * techs
Definition comments.c:30
incite_cost
char * incite_cost
Definition comments.c:74
counter_by_index
struct counter * counter_by_index(int index, enum counter_target target)
Definition counters.c:183
counter_index
int counter_index(const struct counter *pcount)
Definition counters.c:174
counter_by_rule_name
struct counter * counter_by_rule_name(const char *name)
Definition counters.c:115
counter_rule_name
const char * counter_rule_name(struct counter *pcount)
Definition counters.c:165
counters_get_city_counters_count
int counters_get_city_counters_count(void)
Definition counters.c:74
counters.h
punit
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
set_ai_level_directer
void set_ai_level_directer(struct player *pplayer, enum ai_level level)
Definition difficulty.c:39
difficulty.h
valid_dst_closest
enum diplstate_type valid_dst_closest(struct player_diplstate *dst)
Definition diplhand.c:111
diplhand.h
ptreaty
struct Treaty * ptreaty
Definition diplodlg_g.h:28
init_treaty
void init_treaty(struct Treaty *ptreaty, struct player *plr0, struct player *plr1)
Definition diptreaty.c:99
treaties_iterate
void treaties_iterate(treaty_cb cb, void *data)
Definition diptreaty.c:380
add_clause
bool add_clause(struct Treaty *ptreaty, struct player *pfrom, enum clause_type type, int val, struct player *client_player)
Definition diptreaty.c:145
treaty_add
void treaty_add(struct Treaty *ptreaty)
Definition diptreaty.c:361
clause_list_iterate_end
#define clause_list_iterate_end
Definition diptreaty.h:70
clause_list_iterate
#define clause_list_iterate(clauselist, pclause)
Definition diptreaty.h:68
id
int int id
Definition editgui_g.h:28
next_extra_for_tile
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
extra_type_by_rule_name
struct extra_type * extra_type_by_rule_name(const char *name)
Definition extras.c:212
extra_owner
struct player * extra_owner(const struct tile *ptile)
Definition extras.c:1114
extra_number
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
extra_by_number
struct extra_type * extra_by_number(int id)
Definition extras.c:183
extras
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
extra_rule_name
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
extra_type_iterate
#define extra_type_iterate(_p)
Definition extras.h:315
extra_type_iterate_end
#define extra_type_iterate_end
Definition extras.h:321
is_extra_caused_by
#define is_extra_caused_by(e, c)
Definition extras.h:203
extra_index
#define extra_index(_e_)
Definition extras.h:183
EXTRA_NONE
#define EXTRA_NONE
Definition extras.h:85
extra_type_by_cause_iterate_end
#define extra_type_by_cause_iterate_end
Definition extras.h:339
extra_type_by_cause_iterate
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
ruleset
static char * ruleset
Definition fc_manual.c:159
NO_TARGET
#define NO_TARGET
Definition fc_types.h:357
Tech_type_id
int Tech_type_id
Definition fc_types.h:380
citizens
unsigned char citizens
Definition fc_types.h:391
MAX_NUM_PLAYER_SLOTS
#define MAX_NUM_PLAYER_SLOTS
Definition fc_types.h:32
CTGT_CITY
@ CTGT_CITY
Definition fc_types.h:126
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
O_LAST
@ O_LAST
Definition fc_types.h:101
Multiplier_type_id
int Multiplier_type_id
Definition fc_types.h:389
IDENTITY_NUMBER_ZERO
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
fcintl.h
_
#define _(String)
Definition fcintl.h:67
game
struct civ_game game
Definition game.c:62
wld
struct world wld
Definition game.c:63
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:116
initialize_globals
void initialize_globals(void)
Definition game.c:681
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:107
game.h
GAME_DEFAULT_TIMEOUTINTINC
#define GAME_DEFAULT_TIMEOUTINTINC
Definition game.h:594
GAME_DEFAULT_SCORETURN
#define GAME_DEFAULT_SCORETURN
Definition game.h:578
GAME_DEFAULT_TIMEOUTINT
#define GAME_DEFAULT_TIMEOUTINT
Definition game.h:593
GAME_DEFAULT_TIMEOUTINCMULT
#define GAME_DEFAULT_TIMEOUTINCMULT
Definition game.h:596
GAME_DEFAULT_TIMEOUTINC
#define GAME_DEFAULT_TIMEOUTINC
Definition game.h:595
GAME_DEFAULT_RULESETDIR
#define GAME_DEFAULT_RULESETDIR
Definition game.h:672
GAME_DEFAULT_TIMEOUTCOUNTER
#define GAME_DEFAULT_TIMEOUTCOUNTER
Definition game.h:598
GAME_DEFAULT_PHASE_MODE
#define GAME_DEFAULT_PHASE_MODE
Definition game.h:613
government_of_player
struct government * government_of_player(const struct player *pplayer)
Definition government.c:114
government_rule_name
const char * government_rule_name(const struct government *pgovern)
Definition government.c:133
government_by_rule_name
struct government * government_by_rule_name(const char *name)
Definition government.c:55
government.h
governments_iterate
#define governments_iterate(NAME_pgov)
Definition government.h:120
governments_iterate_end
#define governments_iterate_end
Definition government.h:123
owner
struct city * owner
Definition citydlg.c:220
type
GType type
Definition repodlgs.c:1313
idex_register_unit
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
idex_register_city
void idex_register_city(struct world *iworld, struct city *pcity)
Definition idex.c:67
idex.h
improvement_by_number
struct impr_type * improvement_by_number(const Impr_type_id id)
Definition improvement.c:194
great_wonder_is_destroyed
bool great_wonder_is_destroyed(const struct impr_type *pimprove)
Definition improvement.c:993
wonder_is_lost
bool wonder_is_lost(const struct player *pplayer, const struct impr_type *pimprove)
Definition improvement.c:863
improvement_rule_name
const char * improvement_rule_name(const struct impr_type *pimprove)
Definition improvement.c:252
improvement_index
Impr_type_id improvement_index(const struct impr_type *pimprove)
Definition improvement.c:175
is_wonder
bool is_wonder(const struct impr_type *pimprove)
Definition improvement.c:343
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:772
improvement_by_rule_name
struct impr_type * improvement_by_rule_name(const char *name)
Definition improvement.c:367
improvement_count
Impr_type_id improvement_count(void)
Definition improvement.c:164
improvement_iterate_end
#define improvement_iterate_end
Definition improvement.h:205
WONDER_DESTROYED
#define WONDER_DESTROYED
Definition improvement.h:139
improvement_iterate
#define improvement_iterate(_p)
Definition improvement.h:199
WONDER_LOST
#define WONDER_LOST
Definition improvement.h:144
B_LAST
#define B_LAST
Definition improvement.h:42
adv_city_free
void adv_city_free(struct city *pcity)
Definition infracache.c:501
adv_city_alloc
void adv_city_alloc(struct city *pcity)
Definition infracache.c:488
infracache.h
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
log_fatal
#define log_fatal(message,...)
Definition log.h:100
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
log_error
#define log_error(message,...)
Definition log.h:103
startpos_disallow
bool startpos_disallow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1660
nat_x
#define nat_x
nat_y
#define nat_y
sq_map_distance
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:641
map_startpos_new
struct startpos * map_startpos_new(struct tile *ptile)
Definition map.c:1866
startpos_tile
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1676
startpos_allows_all
bool startpos_allows_all(const struct startpos *psp)
Definition map.c:1696
startpos_raw_nations
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1765
main_map_allocate
void main_map_allocate(void)
Definition map.c:519
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
map_startpos_count
int map_startpos_count(void)
Definition map.c:1853
native_pos_to_tile
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:443
startpos_is_excluding
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1753
map_is_empty
bool map_is_empty(void)
Definition map.c:149
startpos_allow
bool startpos_allow(struct startpos *psp, struct nation_type *pnation)
Definition map.c:1643
map_init_topology
void map_init_topology(void)
Definition map.c:303
map.h
map_startpos_iterate
#define map_startpos_iterate(NAME_psp)
Definition map.h:130
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition map.h:137
map_startpos_iterate_end
#define map_startpos_iterate_end
Definition map.h:133
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:545
index_to_native_pos
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:157
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:554
map_generator
map_generator
Definition map_types.h:46
MAPGEN_SCENARIO
@ MAPGEN_SCENARIO
Definition map_types.h:47
mapgen.h
assign_continent_numbers
void assign_continent_numbers(void)
Definition mapgen_utils.c:452
mapgen_utils.h
player_map_init
void player_map_init(struct player *pplayer)
Definition maphand.c:1218
update_player_tile_last_seen
void update_player_tile_last_seen(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1464
map_claim_ownership
void map_claim_ownership(struct tile *ptile, struct player *powner, struct tile *psource, bool claim_bases)
Definition maphand.c:2185
map_is_known
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:894
send_tile_suppression
bool send_tile_suppression(bool now)
Definition maphand.c:475
really_gives_vision
bool really_gives_vision(struct player *me, struct player *them)
Definition maphand.c:345
map_know_and_see_all
void map_know_and_see_all(struct player *pplayer)
Definition maphand.c:1193
update_player_tile_knowledge
bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
Definition maphand.c:1395
map_get_player_city
struct vision_site * map_get_player_city(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1364
tile_claim_bases
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2198
map_set_known
void map_set_known(struct tile *ptile, struct player *pplayer)
Definition maphand.c:1175
map_is_known_and_seen
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
change_playertile_site
void change_playertile_site(struct player_tile *ptile, struct vision_site *new_site)
Definition maphand.c:1156
map_calculate_borders
void map_calculate_borders(void)
Definition maphand.c:2351
give_shared_vision
void give_shared_vision(struct player *pfrom, struct player *pto)
Definition maphand.c:1629
map_get_player_tile
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1379
maphand.h
mapimg_id2str
bool mapimg_id2str(int id, char *str, size_t str_len)
Definition mapimg.c:1311
mapimg_define
bool mapimg_define(const char *maparg, bool check)
Definition mapimg.c:769
mapimg_delete
bool mapimg_delete(int id)
Definition mapimg.c:1204
mapimg_count
int mapimg_count(void)
Definition mapimg.c:573
mapimg.h
MAX_LEN_MAPDEF
#define MAX_LEN_MAPDEF
Definition mapimg.h:65
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
set_meta_patches_string
void set_meta_patches_string(const char *string)
Definition meta.c:172
meta_addr_port
char * meta_addr_port(void)
Definition meta.c:203
default_meta_patches_string
const char * default_meta_patches_string(void)
Definition meta.c:83
get_meta_patches_string
const char * get_meta_patches_string(void)
Definition meta.c:107
meta.h
DEFAULT_META_SERVER_ADDR
#define DEFAULT_META_SERVER_ADDR
Definition meta.h:21
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
movement.h
multiplier_rule_name
const char * multiplier_rule_name(const struct multiplier *pmul)
Definition multipliers.c:106
multiplier_count
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
multiplier_by_rule_name
struct multiplier * multiplier_by_rule_name(const char *name)
Definition multipliers.c:115
multiplier_index
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
multipliers.h
multipliers_iterate
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
multipliers_iterate_end
#define multipliers_iterate_end
Definition multipliers.h:67
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
nation_by_rule_name
struct nation_type * nation_by_rule_name(const char *name)
Definition nation.c:121
nations
static struct nation_type * nations
Definition nation.c:46
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
nation_hash_iterate
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
nation_hash_iterate_end
#define nation_hash_iterate_end
Definition nation.h:95
NO_NATION_SELECTED
#define NO_NATION_SELECTED
Definition nation.h:30
event_cache_load
void event_cache_load(struct section_file *file, const char *section)
Definition notify.c:784
event_cache_save
void event_cache_save(struct section_file *file, const char *section)
Definition notify.c:904
notify.h
packets.h
parts
int parts
Definition packhand.c:132
lines
char * lines
Definition packhand.c:131
len
int len
Definition packhand.c:127
player_slot_is_used
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
player_unit_by_number
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
player_by_number
struct player * player_by_number(const int player_id)
Definition player.c:849
players_on_same_team
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
player_count
int player_count(void)
Definition player.c:817
player_slot_count
int player_slot_count(void)
Definition player.c:418
player_slot_by_number
struct player_slot * player_slot_by_number(int player_id)
Definition player.c:463
player_number
int player_number(const struct player *pplayer)
Definition player.c:837
pplayer_can_make_treaty
enum dipl_reason pplayer_can_make_treaty(const struct player *p1, const struct player *p2, enum diplstate_type treaty)
Definition player.c:159
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:895
player_slot_max_used_number
int player_slot_max_used_number(void)
Definition player.c:476
player_slot_index
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
player_by_name
struct player * player_by_name(const char *name)
Definition player.c:881
player_has_flag
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
player_has_real_embassy
bool player_has_real_embassy(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:240
player_city_by_number
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
player_index
int player_index(const struct player *pplayer)
Definition player.c:829
player_set_nation
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Definition player.c:861
player_diplstate_get
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
slots
struct player_slot * slots
Definition player.c:51
gives_shared_tiles
bool gives_shared_tiles(const struct player *me, const struct player *them)
Definition player.c:1493
gives_shared_vision
bool gives_shared_vision(const struct player *me, const struct player *them)
Definition player.c:1485
players_iterate_end
#define players_iterate_end
Definition player.h:537
dipl_reason
dipl_reason
Definition player.h:190
DIPL_ALLIANCE_PROBLEM_THEM
@ DIPL_ALLIANCE_PROBLEM_THEM
Definition player.h:192
DIPL_ALLIANCE_PROBLEM_US
@ DIPL_ALLIANCE_PROBLEM_US
Definition player.h:192
players_iterate
#define players_iterate(_pplayer)
Definition player.h:532
MAX_ATTRIBUTE_BLOCK
#define MAX_ATTRIBUTE_BLOCK
Definition player.h:221
player_list_iterate
#define player_list_iterate(playerlist, pplayer)
Definition player.h:555
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
player_slots_iterate
#define player_slots_iterate(_pslot)
Definition player.h:523
is_ai
#define is_ai(plr)
Definition player.h:230
player_list_iterate_end
#define player_list_iterate_end
Definition player.h:557
players_iterate_alive_end
#define players_iterate_alive_end
Definition player.h:547
player_slots_iterate_end
#define player_slots_iterate_end
Definition player.h:527
players_iterate_alive
#define players_iterate_alive(_pplayer)
Definition player.h:542
server_player_set_name
void server_player_set_name(struct player *pplayer, const char *name)
Definition plrhand.c:2263
server_create_player
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Definition plrhand.c:1889
normal_player_count
int normal_player_count(void)
Definition plrhand.c:3200
player_limit_to_max_rates
void player_limit_to_max_rates(struct player *pplayer)
Definition plrhand.c:2052
pick_a_nation
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
Definition plrhand.c:2448
set_shuffled_players
void set_shuffled_players(int *shuffled_players)
Definition plrhand.c:2398
player_delegation_set
void player_delegation_set(struct player *pplayer, const char *username)
Definition plrhand.c:3246
shuffle_players
void shuffle_players(void)
Definition plrhand.c:2373
server_remove_player
void server_remove_player(struct player *pplayer)
Definition plrhand.c:1938
server_player_init
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Definition plrhand.c:1614
assign_player_colors
void assign_player_colors(void)
Definition plrhand.c:1729
player_delegation_get
const char * player_delegation_get(const struct player *pplayer)
Definition plrhand.c:3233
fit_nationset_to_players
void fit_nationset_to_players(void)
Definition plrhand.c:2654
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:108
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
fc_rand_is_init
bool fc_rand_is_init(void)
Definition rand.c:200
fc_rand_state
RANDOM_STATE fc_rand_state(void)
Definition rand.c:208
fc_rand_set_state
void fc_rand_set_state(RANDOM_STATE state)
Definition rand.c:229
rand.h
secfile_load
struct section_file * secfile_load(const char *filename, bool allow_duplicates)
Definition registry.c:50
registry.h
secfile_error
const char * secfile_error(void)
Definition section_file.c:36
secfile_lookup_int
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
Definition registry_ini.c:1975
secfile_lookup_str_vec
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
Definition registry_ini.c:2239
secfile_entry_lookup
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
Definition registry_ini.c:1857
entry_str_set_gt_marking
bool entry_str_set_gt_marking(struct entry *pentry, bool gt_marking)
Definition registry_ini.c:3614
secfile_lookup_str
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
Definition registry_ini.c:2175
secfile_lookup_int_vec
int * secfile_lookup_int_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
Definition registry_ini.c:2077
secfile_lookup_bool_default
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
Definition registry_ini.c:1900
secfile_lookup_int_default
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Definition registry_ini.c:2000
secfile_entry_by_path
struct entry * secfile_entry_by_path(const struct section_file *secfile, const char *path)
Definition registry_ini.c:1784
secfile_section_lookup
struct section * secfile_section_lookup(const struct section_file *secfile, const char *path,...)
Definition registry_ini.c:2840
secfile_lookup_str_default
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Definition registry_ini.c:2205
secfile_lookup_bool
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
Definition registry_ini.c:1875
secfile_insert_int
#define secfile_insert_int(secfile, value, path,...)
Definition registry_ini.h:116
secfile_insert_enum
#define secfile_insert_enum(secfile, enumerator, specenum_type, path,...)
Definition registry_ini.h:266
secfile_insert_int_vec
#define secfile_insert_int_vec(secfile, values, dim, path,...)
Definition registry_ini.h:133
secfile_lookup_enum_default
#define secfile_lookup_enum_default(secfile, defval, specenum_type, path,...)
Definition registry_ini.h:516
secfile_insert_str_vec
#define secfile_insert_str_vec(secfile, strings, dim, path,...)
Definition registry_ini.h:201
secfile_insert_str
#define secfile_insert_str(secfile, string, path,...)
Definition registry_ini.h:170
secfile_insert_bool
#define secfile_insert_bool(secfile, value, path,...)
Definition registry_ini.h:79
secfile_replace_str
#define secfile_replace_str(secfile, string, path,...)
Definition registry_ini.h:183
history_report_get
struct history_report * history_report_get(void)
Definition report.c:1824
report.h
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6597
universal_type_rule_name
const char * universal_type_rule_name(const struct universal *psource)
Definition requirements.c:7102
universal_by_rule_name
struct universal universal_by_rule_name(const char *kind, const char *value)
Definition requirements.c:236
research_invention_reachable
bool research_invention_reachable(const struct research *presearch, const Tech_type_id tech)
Definition research.c:668
research_name_translation
const char * research_name_translation(const struct research *presearch)
Definition research.c:156
research_invention_set
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Definition research.c:637
research_by_number
struct research * research_by_number(int number)
Definition research.c:118
research_number
int research_number(const struct research *presearch)
Definition research.c:109
recalculate_techs_researched
int recalculate_techs_researched(const struct research *presearch)
Definition research.c:1345
research_invention_state
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
research_update
void research_update(struct research *presearch)
Definition research.c:501
research.h
researches_iterate
#define researches_iterate(_presearch)
Definition research.h:155
researches_iterate_end
#define researches_iterate_end
Definition research.h:158
rgbcolor_destroy
void rgbcolor_destroy(struct rgbcolor *prgbcolor)
Definition rgbcolor.c:74
rgbcolor_load
bool rgbcolor_load(struct section_file *file, struct rgbcolor **prgbcolor, char *path,...)
Definition rgbcolor.c:90
rgbcolor_save
void rgbcolor_save(struct section_file *file, const struct rgbcolor *prgbcolor, char *path,...)
Definition rgbcolor.c:121
rgbcolor.h
load_rulesets
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Definition ruleset.c:9363
ruleset.h
sanitycheck.h
sanity_check
#define sanity_check()
Definition sanitycheck.h:43
sanity_check_city
#define sanity_check_city(x)
Definition sanitycheck.h:41
current_compat_ver
int current_compat_ver(void)
Definition savecompat.c:222
bin2ascii_hex
char bin2ascii_hex(int value, int halfbyte_wanted)
Definition savecompat.c:232
sg_load_compat
void sg_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:143
ascii_hex2bin
int ascii_hex2bin(char ch, int halfbyte)
Definition savecompat.c:244
sg_load_post_load_compat
void sg_load_post_load_compat(struct loaddata *loading, enum sgf_version format_class)
Definition savecompat.c:194
savecompat.h
sg_check_ret
#define sg_check_ret(...)
Definition savecompat.h:150
sg_warn
#define sg_warn(condition, message,...)
Definition savecompat.h:160
hex_chars
#define hex_chars
Definition savecompat.h:205
sg_failure_ret_val
#define sg_failure_ret_val(condition, _val, message,...)
Definition savecompat.h:184
sg_failure_ret
#define sg_failure_ret(condition, message,...)
Definition savecompat.h:177
sg_regr
#define sg_regr(fixversion, message,...)
Definition savecompat.h:193
SAVEGAME_3
@ SAVEGAME_3
Definition savecompat.h:27
log_sg
#define log_sg
Definition savecompat.h:146
sg_warn_ret_val
#define sg_warn_ret_val(condition, _val, message,...)
Definition savecompat.h:171
savegame3_save
void savegame3_save(struct section_file *sfile, const char *save_reason, bool scenario)
Definition savegame3.c:429
sg_save_history
static void sg_save_history(struct savedata *saving)
Definition savegame3.c:7801
sg_extras_get_bv
static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1196
sg_save_counters
static void sg_save_counters(struct savedata *saving)
Definition savegame3.c:2750
unit_ordering_apply
static void unit_ordering_apply(void)
Definition savegame3.c:1077
sg_load_players_basic
static void sg_load_players_basic(struct loaddata *loading)
Definition savegame3.c:3616
loaddata_new
static struct loaddata * loaddata_new(struct section_file *file)
Definition savegame3.c:582
worklist_save
static void worklist_save(struct section_file *file, const struct worklist *pwl, int max_length, const char *path,...)
Definition savegame3.c:1010
sg_load_map_known
static void sg_load_map_known(struct loaddata *loading)
Definition savegame3.c:3497
sg_load_map_owner
static void sg_load_map_owner(struct loaddata *loading)
Definition savegame3.c:3167
sg_success
bool sg_success
Definition savecompat.c:34
ACTIVITY_OLD_FALLOUT_SG3
#define ACTIVITY_OLD_FALLOUT_SG3
Definition savegame3.c:152
quote_block
static char * quote_block(const void *const data, int length)
Definition savegame3.c:895
halfbyte_iterate_extras_end
#define halfbyte_iterate_extras_end
Definition savegame3.c:260
halfbyte_iterate_extras
#define halfbyte_iterate_extras(e, num_extras_types)
Definition savegame3.c:255
sg_load_map
static void sg_load_map(struct loaddata *loading)
Definition savegame3.c:2809
char2order
static enum unit_orders char2order(char order)
Definition savegame3.c:708
unquote_block
static int unquote_block(const char *const quoted_, void *dest, int dest_length)
Definition savegame3.c:916
sg_save_map_tiles_extras
static void sg_save_map_tiles_extras(struct savedata *saving)
Definition savegame3.c:2999
sg_save_map_worked
static void sg_save_map_worked(struct savedata *saving)
Definition savegame3.c:3458
ACTIVITY_OLD_POLLUTION_SG3
#define ACTIVITY_OLD_POLLUTION_SG3
Definition savegame3.c:151
sg_save_players
static void sg_save_players(struct savedata *saving)
Definition savegame3.c:4071
LOAD_MAP_CHAR
#define LOAD_MAP_CHAR(ch, ptile, SET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:219
sg_save_player_cities
static void sg_save_player_cities(struct savedata *saving, struct player *plr)
Definition savegame3.c:5562
sg_load_player_city_citizens
static void sg_load_player_city_citizens(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr)
Definition savegame3.c:5514
sg_load_player_cities
static void sg_load_player_cities(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4948
sg_load_map_tiles
static void sg_load_map_tiles(struct loaddata *loading)
Definition savegame3.c:2899
sg_load_player_unit
static bool sg_load_player_unit(struct loaddata *loading, struct player *plr, struct unit *punit, int orders_max_length, const char *unitstr)
Definition savegame3.c:6031
activity2char
static char activity2char(int activity)
Definition savegame3.c:821
savedata_new
static struct savedata * savedata_new(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:677
sg_load_savefile
static void sg_load_savefile(struct loaddata *loading)
Definition savegame3.c:1334
char2activity
static enum unit_activity char2activity(char activity)
Definition savegame3.c:872
unit_ordering_calc
static void unit_ordering_calc(void)
Definition savegame3.c:1048
sg_load_settings
static void sg_load_settings(struct loaddata *loading)
Definition savegame3.c:2659
sg_load_player_units
static void sg_load_player_units(struct loaddata *loading, struct player *plr)
Definition savegame3.c:5962
terrain2char
static char terrain2char(const struct terrain *pterrain)
Definition savegame3.c:1248
sg_save_random
static void sg_save_random(struct savedata *saving)
Definition savegame3.c:2430
sg_save_map_startpos
static void sg_save_map_startpos(struct savedata *saving)
Definition savegame3.c:3112
sg_load_researches
static void sg_load_researches(struct loaddata *loading)
Definition savegame3.c:7450
sg_load_map_worked
static void sg_load_map_worked(struct loaddata *loading)
Definition savegame3.c:3414
SAVE_MAP_CHAR
#define SAVE_MAP_CHAR(ptile, GET_XY_CHAR, secfile, secpath,...)
Definition savegame3.c:172
sg_save_savefile_options
static void sg_save_savefile_options(struct savedata *saving, const char *option)
Definition savegame3.c:2039
sg_load_random
static void sg_load_random(struct loaddata *loading)
Definition savegame3.c:2389
sg_save_savefile
static void sg_save_savefile(struct savedata *saving)
Definition savegame3.c:1773
sg_load_player_units_transport
static void sg_load_player_units_transport(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6515
sg_load_history
static void sg_load_history(struct loaddata *loading)
Definition savegame3.c:7775
sg_save_treaties
static void sg_save_treaties(struct savedata *saving)
Definition savegame3.c:7761
sg_save_map_owner
static void sg_save_map_owner(struct savedata *saving)
Definition savegame3.c:3288
sg_save_researches
static void sg_save_researches(struct savedata *saving)
Definition savegame3.c:7556
savegame3_save_real
static void savegame3_save_real(struct section_file *file, const char *save_reason, bool scenario)
Definition savegame3.c:525
TOKEN_SIZE
#define TOKEN_SIZE
Definition savegame3.c:276
sg_load_script
static void sg_load_script(struct loaddata *loading)
Definition savegame3.c:2468
sg_load_scenario
static void sg_load_scenario(struct loaddata *loading)
Definition savegame3.c:2494
sg_load_game
static void sg_load_game(struct loaddata *loading)
Definition savegame3.c:2086
savedata_destroy
static void savedata_destroy(struct savedata *saving)
Definition savegame3.c:696
sg_load_player_main
static void sg_load_player_main(struct loaddata *loading, struct player *plr)
Definition savegame3.c:4132
order2char
static char order2char(enum unit_orders order)
Definition savegame3.c:735
sg_load_treaties
static void sg_load_treaties(struct loaddata *loading)
Definition savegame3.c:7651
sg_save_scenario
static void sg_save_scenario(struct savedata *saving)
Definition savegame3.c:2582
sg_extras_set_bv
static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1131
PART_SIZE
#define PART_SIZE
sg_save_player_units
static void sg_save_player_units(struct savedata *saving, struct player *plr)
Definition savegame3.c:6568
sg_save_ruledata
static void sg_save_ruledata(struct savedata *saving)
Definition savegame3.c:2239
sg_extras_get_dbv
static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, const int *idx)
Definition savegame3.c:1163
technology_load
static Tech_type_id technology_load(struct section_file *file, const char *path, int plrno)
Definition savegame3.c:1261
sg_save_player_vision
static void sg_save_player_vision(struct savedata *saving, struct player *plr)
Definition savegame3.c:7286
char2dir
static enum direction8 char2dir(char dir)
Definition savegame3.c:759
ACTIVITY_LAST_SAVEGAME3
#define ACTIVITY_LAST_SAVEGAME3
Definition savegame3.c:153
sg_load_player_city
static bool sg_load_player_city(struct loaddata *loading, struct player *plr, struct city *pcity, const char *citystr, int wlist_max_length, int routes_max)
Definition savegame3.c:5067
char2terrain
static struct terrain * char2terrain(char ch)
Definition savegame3.c:1225
sg_save_sanitycheck
static void sg_save_sanitycheck(struct savedata *saving)
Definition savegame3.c:8058
sg_load_mapimg
static void sg_load_mapimg(struct loaddata *loading)
Definition savegame3.c:7820
sg_load_player_attributes
static void sg_load_player_attributes(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6824
sg_save_player_attributes
static void sg_save_player_attributes(struct savedata *saving, struct player *plr)
Definition savegame3.c:6904
sg_load_ruledata
static void sg_load_ruledata(struct loaddata *loading)
Definition savegame3.c:2062
sg_save_map
static void sg_save_map(struct savedata *saving)
Definition savegame3.c:2859
sg_load_player_vision
static void sg_load_player_vision(struct loaddata *loading, struct player *plr)
Definition savegame3.c:6987
sg_save_map_tiles
static void sg_save_map_tiles(struct savedata *saving)
Definition savegame3.c:2939
worklist_load
static void worklist_load(struct section_file *file, int wlist_max_length, struct worklist *pwl, const char *path,...)
Definition savegame3.c:964
sg_save_mapimg
static void sg_save_mapimg(struct savedata *saving)
Definition savegame3.c:7860
savefile_options_default
static const char savefile_options_default[]
Definition savegame3.c:278
dir2char
static char dir2char(enum direction8 dir)
Definition savegame3.c:788
sg_load_player_vision_city
static bool sg_load_player_vision_city(struct loaddata *loading, struct player *plr, struct vision_site *pdcity, const char *citystr)
Definition savegame3.c:7175
sg_load_counters
static void sg_load_counters(struct loaddata *loading)
Definition savegame3.c:2697
sg_load_map_startpos
static void sg_load_map_startpos(struct loaddata *loading)
Definition savegame3.c:3025
loaddata_destroy
static void loaddata_destroy(struct loaddata *loading)
Definition savegame3.c:621
sg_load_players
static void sg_load_players(struct loaddata *loading)
Definition savegame3.c:3876
PART_ADJUST
#define PART_ADJUST
technology_save
static void technology_save(struct section_file *file, const char *path, int plrno, Tech_type_id tech)
Definition savegame3.c:1297
sg_save_event_cache
static void sg_save_event_cache(struct savedata *saving)
Definition savegame3.c:7631
sg_load_map_tiles_extras
static void sg_load_map_tiles_extras(struct loaddata *loading)
Definition savegame3.c:2967
treaty_save
static void treaty_save(struct Treaty *ptr, void *data_in)
Definition savegame3.c:7734
sg_load_sanitycheck
static void sg_load_sanitycheck(struct loaddata *loading)
Definition savegame3.c:7885
sg_load_event_cache
static void sg_load_event_cache(struct loaddata *loading)
Definition savegame3.c:7620
savegame3_load
void savegame3_load(struct section_file *file)
Definition savegame3.c:456
sg_extras_set_dbv
static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx)
Definition savegame3.c:1098
sg_save_game
static void sg_save_game(struct savedata *saving)
Definition savegame3.c:2259
sg_save_player_main
static void sg_save_player_main(struct savedata *saving, struct player *plr)
Definition savegame3.c:4622
sg_save_script
static void sg_save_script(struct savedata *saving)
Definition savegame3.c:2479
sg_save_settings
static void sg_save_settings(struct savedata *saving)
Definition savegame3.c:2675
sg_save_map_known
static void sg_save_map_known(struct savedata *saving)
Definition savegame3.c:3553
savegame3.h
score.h
script_server_state_save
void script_server_state_save(struct section_file *file)
Definition script_server.c:399
script_server_state_load
void script_server_state_load(struct section_file *file)
Definition script_server.c:387
script_server.h
settings_game_load
void settings_game_load(struct section_file *file, const char *section)
Definition settings.c:4939
settings_game_save
void settings_game_save(struct section_file *file, const char *section)
Definition settings.c:4851
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
settings.h
sex_by_name
sex_t sex_by_name(const char *name)
Definition sex.c:27
sex_rule_name
const char * sex_rule_name(sex_t kind)
Definition sex.c:43
sex.h
SEX_FEMALE
@ SEX_FEMALE
Definition sex.h:22
SEX_MALE
@ SEX_MALE
Definition sex.h:23
fileinfoname
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1101
str_to_int
bool str_to_int(const char *str, int *pint)
Definition shared.c:517
get_scenario_dirs
const struct strvec * get_scenario_dirs(void)
Definition shared.c:978
is_base64url
bool is_base64url(const char *s)
Definition shared.c:318
scanin
char scanin(const char **buf, char *delimiters, char *dest, int size)
Definition shared.c:1919
randomize_base64url_string
void randomize_base64url_string(char *s, size_t n)
Definition shared.c:339
shared.h
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
MAX_LEN_PATH
#define MAX_LEN_PATH
Definition shared.h:32
spaceship_calc_derived
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
spacerace.h
spaceship_init
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
NUM_SS_STRUCTURALS
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
SSHIP_LAUNCHED
@ SSHIP_LAUNCHED
Definition spaceship.h:85
SSHIP_NONE
@ SSHIP_NONE
Definition spaceship.h:84
specialist_by_rule_name
struct specialist * specialist_by_rule_name(const char *name)
Definition specialist.c:112
specialist_by_number
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:100
specialist_index
Specialist_type_id specialist_index(const struct specialist *sp)
Definition specialist.c:82
specialist_rule_name
const char * specialist_rule_name(const struct specialist *sp)
Definition specialist.c:146
specialist_count
Specialist_type_id specialist_count(void)
Definition specialist.c:71
specialist.h
specialist_type_iterate_end
#define specialist_type_iterate_end
Definition specialist.h:79
specialist_type_iterate
#define specialist_type_iterate(sp)
Definition specialist.h:73
DEFAULT_SPECIALIST
#define DEFAULT_SPECIALIST
Definition specialist.h:43
size
size_t size
Definition specvec.h:72
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
server_game_init
void server_game_init(bool keep_ruleset_value)
Definition srv_main.c:3462
aifill
const char * aifill(int amount)
Definition srv_main.c:2464
game_was_started
bool game_was_started(void)
Definition srv_main.c:349
identity_number_reserve
void identity_number_reserve(int id)
Definition srv_main.c:1994
srvarg
struct server_arguments srvarg
Definition srv_main.c:176
init_game_seed
void init_game_seed(void)
Definition srv_main.c:203
update_nations_with_startpos
void update_nations_with_startpos(void)
Definition srv_main.c:2269
server_state
enum server_states server_state(void)
Definition srv_main.c:333
server_game_free
void server_game_free(void)
Definition srv_main.c:3486
srv_main.h
stdinhand.h
RANDOM_STATE
Definition rand.h:50
RANDOM_STATE::x
int x
Definition rand.h:52
RANDOM_STATE::v
RANDOM_TYPE v[56]
Definition rand.h:51
RANDOM_STATE::k
int k
Definition rand.h:52
RANDOM_STATE::is_init
bool is_init
Definition rand.h:53
RANDOM_STATE::j
int j
Definition rand.h:52
Treaty
Definition diptreaty.h:78
Treaty::plr0
struct player * plr0
Definition diptreaty.h:79
Treaty::accept0
bool accept0
Definition diptreaty.h:80
Treaty::accept1
bool accept1
Definition diptreaty.h:80
Treaty::clauses
struct clause_list * clauses
Definition diptreaty.h:81
Treaty::plr1
struct player * plr1
Definition diptreaty.h:79
achievement
Definition achievements.h:26
achievement::first
struct player * first
Definition achievements.h:34
action
Definition actions.h:360
adv_data::wonder_city
int wonder_city
Definition advdata.h:55
advance
Definition tech.h:124
ai_trait::val
int val
Definition traits.h:38
ai_trait::mod
int mod
Definition traits.h:39
attribute_block_s::data
void * data
Definition player.h:219
attribute_block_s::length
int length
Definition player.h:220
built_status::turn
int turn
Definition city.h:246
city
Definition city.h:320
city::task_reqs
struct worker_task_list * task_reqs
Definition city.h:412
city::turn_last_built
int turn_last_built
Definition city.h:387
city::wlcb
enum city_wl_cancel_behavior wlcb
Definition city.h:404
city::food_stock
int food_stock
Definition city.h:367
city::built
struct built_status built[B_LAST]
Definition city.h:394
city::original
struct player * original
Definition city.h:324
city::history
int history
Definition city.h:410
city::counter_values
int * counter_values
Definition city.h:408
city::did_sell
bool did_sell
Definition city.h:380
city::id
int id
Definition city.h:326
city::last_turns_shield_surplus
int last_turns_shield_surplus
Definition city.h:392
city::disbanded_shields
int disbanded_shields
Definition city.h:391
city::turn_plague
int turn_plague
Definition city.h:374
city::city_options
bv_city_options city_options
Definition city.h:403
city::was_happy
bool was_happy
Definition city.h:381
city::acquire_t
enum city_acquire_type acquire_t
Definition city.h:329
city::turn_founded
int turn_founded
Definition city.h:386
city::airlift
int airlift
Definition city.h:378
city::caravan_shields
int caravan_shields
Definition city.h:390
city::did_buy
bool did_buy
Definition city.h:379
city::routes
struct trade_route_list * routes
Definition city.h:344
city::anarchy
int anarchy
Definition city.h:384
city::worklist
struct worklist worklist
Definition city.h:401
city::production
struct universal production
Definition city.h:396
city::orders
struct unit_order * orders
Definition city.h:422
city::rally_point
struct city::@16 rally_point
city::adv
struct adv_city * adv
Definition city.h:452
city::vigilant
bool vigilant
Definition city.h:421
city::steal
int steal
Definition city.h:414
city::before_change_shields
int before_change_shields
Definition city.h:389
city::style
int style
Definition city.h:327
city::had_famine
bool had_famine
Definition city.h:382
city::length
size_t length
Definition city.h:417
city::synced
bool synced
Definition city.h:448
city::specialists
citizens specialists[SP_MAX]
Definition city.h:336
city::tile
struct tile * tile
Definition city.h:322
city::shield_stock
int shield_stock
Definition city.h:368
city::vision
struct vision * vision
Definition city.h:455
city::server
struct city::@17::@19 server
city::cm_parameter
struct cm_parameter * cm_parameter
Definition city.h:425
city::changed_from
struct universal changed_from
Definition city.h:399
city::units_supported
struct unit_list * units_supported
Definition city.h:406
city::persistent
bool persistent
Definition city.h:419
city::rapture
int rapture
Definition city.h:385
civ_game::multiresearch
bool multiresearch
Definition game.h:163
civ_game::last_updated_year
bool last_updated_year
Definition game.h:236
civ_game::turn_change_time
float turn_change_time
Definition game.h:218
civ_game::vision_reveal_tiles
bool vision_reveal_tiles
Definition game.h:200
civ_game::scenario_desc
struct packet_scenario_description scenario_desc
Definition game.h:88
civ_game::save_private_map
bool save_private_map
Definition game.h:261
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
civ_game::fogofwar_old
bool fogofwar_old
Definition game.h:234
civ_game::save_options
struct civ_game::@31::@35::@37 save_options
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::timeoutcounter
int timeoutcounter
Definition game.h:207
civ_game::rulesetdir
char rulesetdir[MAX_LEN_NAME]
Definition game.h:238
civ_game::additional_phase_seconds
int additional_phase_seconds
Definition game.h:212
civ_game::luadata
struct section_file * luadata
Definition game.h:246
civ_game::scoreturn
int scoreturn
Definition game.h:225
civ_game::seed
randseed seed
Definition game.h:227
civ_game::dbid
int dbid
Definition game.h:247
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civ_game::timeoutint
int timeoutint
Definition game.h:203
civ_game::phase_timer
struct timer * phase_timer
Definition game.h:211
civ_game::revealmap
unsigned revealmap
Definition game.h:177
civ_game::orig_game_version
char orig_game_version[MAX_LEN_NAME]
Definition game.h:221
civ_game::save_known
bool save_known
Definition game.h:258
civ_game::foggedborders
bool foggedborders
Definition game.h:147
civ_game::server
struct civ_game::@31::@35 server
civ_game::ruleset_capabilities
char * ruleset_capabilities
Definition game.h:86
civ_game::timeoutincmult
int timeoutincmult
Definition game.h:205
civ_game::timeoutinc
int timeoutinc
Definition game.h:204
civ_game::phase_mode_stored
int phase_mode_stored
Definition game.h:216
civ_game::max_players
int max_players
Definition game.h:156
civ_game::save_starts
bool save_starts
Definition game.h:260
civ_game::timeoutintinc
int timeoutintinc
Definition game.h:206
civ_map
Definition map_types.h:71
civ_map::xsize
int xsize
Definition map_types.h:78
civ_map::seed
randseed seed
Definition map_types.h:92
civ_map::ysize
int ysize
Definition map_types.h:78
civ_map::have_resources
bool have_resources
Definition map_types.h:108
civ_map::server
struct civ_map::@42::@44 server
civ_map::have_huts
bool have_huts
Definition map_types.h:107
civ_map::generator
enum map_generator generator
Definition map_types.h:98
cm_parameter
Definition cm.h:40
cm_parameter::allow_disorder
bool allow_disorder
Definition cm.h:44
cm_parameter::factor
int factor[O_LAST]
Definition cm.h:47
cm_parameter::max_growth
bool max_growth
Definition cm.h:42
cm_parameter::allow_specialists
bool allow_specialists
Definition cm.h:45
cm_parameter::require_happy
bool require_happy
Definition cm.h:43
cm_parameter::minimal_surplus
int minimal_surplus[O_LAST]
Definition cm.h:41
cm_parameter::happy_factor
int happy_factor
Definition cm.h:48
counter
Definition counters.h:27
data_in
Definition dataio_raw.h:30
dbv
Definition bitvector.h:32
entry
Definition registry_ini.c:193
extra_type
Definition extras.h:88
government
Definition government.h:52
government::changed_to_times
int changed_to_times
Definition government.h:60
history_report
Definition report.h:26
history_report::turn
int turn
Definition report.h:27
impr_type
Definition improvement.h:50
loaddata
Definition savecompat.h:47
loaddata::file
struct section_file * file
Definition savecompat.h:48
multiplier_value::value
int value
Definition player.h:239
multiplier_value::target
int target
Definition player.h:241
multiplier_value::changed
int changed
Definition player.h:243
multiplier
Definition multipliers.h:31
multiplier::start
int start
Definition multipliers.h:35
multiplier::step
int step
Definition multipliers.h:37
multiplier::def
int def
Definition multipliers.h:38
multiplier::stop
int stop
Definition multipliers.h:36
nation_style
Definition style.h:22
nation_type
Definition nation.h:98
option
Definition options.c:478
packet_game_info::coolinglevel
int coolinglevel
Definition packets_gen.h:147
packet_game_info::globalwarming
int globalwarming
Definition packets_gen.h:164
packet_game_info::nuclearwinter
int nuclearwinter
Definition packets_gen.h:205
packet_game_info::citizen_nationality
bool citizen_nationality
Definition packets_gen.h:140
packet_game_info::year_0_hack
bool year_0_hack
Definition packets_gen.h:244
packet_game_info::great_wonder_owners
int great_wonder_owners[B_LAST]
Definition packets_gen.h:175
packet_game_info::cooling
int cooling
Definition packets_gen.h:146
packet_game_info::global_advances
bool global_advances[A_LAST]
Definition packets_gen.h:162
packet_game_info::is_new_game
bool is_new_game
Definition packets_gen.h:186
packet_game_info::warminglevel
int warminglevel
Definition packets_gen.h:242
packet_game_info::skill_level
enum ai_level skill_level
Definition packets_gen.h:222
packet_game_info::phase_mode
enum phase_mode_type phase_mode
Definition packets_gen.h:207
packet_game_info::illness_on
bool illness_on
Definition packets_gen.h:181
packet_game_info::heating
int heating
Definition packets_gen.h:178
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_game_info::year
int year
Definition packets_gen.h:243
packet_game_info::phase
int phase
Definition packets_gen.h:206
packet_game_info::fogofwar
bool fogofwar
Definition packets_gen.h:150
packet_ruleset_control::num_extra_types
int num_extra_types
Definition packets_gen.h:1454
packet_ruleset_control::version
char version[MAX_LEN_NAME]
Definition packets_gen.h:1476
packet_ruleset_control::num_tech_types
int num_tech_types
Definition packets_gen.h:1453
packet_ruleset_control::alt_dir
char alt_dir[MAX_LEN_NAME]
Definition packets_gen.h:1477
packet_ruleset_control::num_specialist_types
int num_specialist_types
Definition packets_gen.h:1468
packet_scenario_description::description
char description[MAX_LEN_CONTENT]
Definition packets_gen.h:1621
packet_scenario_info::lake_flooding
bool lake_flooding
Definition packets_gen.h:1611
packet_scenario_info::req_caps
char req_caps[257]
Definition packets_gen.h:1617
packet_scenario_info::datafile
char datafile[MAX_LEN_NAME]
Definition packets_gen.h:1615
packet_scenario_info::have_resources
bool have_resources
Definition packets_gen.h:1616
packet_scenario_info::is_scenario
bool is_scenario
Definition packets_gen.h:1604
packet_scenario_info::ruleset_locked
bool ruleset_locked
Definition packets_gen.h:1614
packet_scenario_info::allow_ai_type_fallback
bool allow_ai_type_fallback
Definition packets_gen.h:1613
packet_scenario_info::players
bool players
Definition packets_gen.h:1607
packet_scenario_info::authors
char authors[MAX_LEN_PACKET/3]
Definition packets_gen.h:1606
packet_scenario_info::name
char name[256]
Definition packets_gen.h:1605
packet_scenario_info::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1610
packet_scenario_info::handmade
bool handmade
Definition packets_gen.h:1612
packet_scenario_info::startpos_nations
bool startpos_nations
Definition packets_gen.h:1608
packet_scenario_info::save_random
bool save_random
Definition packets_gen.h:1609
part
Definition goto.c:52
player_ai::skill_level
enum ai_level skill_level
Definition player.h:114
player_ai::traits
struct ai_trait * traits
Definition player.h:124
player_ai::barbarian_type
enum barbarian_type barbarian_type
Definition player.h:120
player_ai::science_cost
int science_cost
Definition player.h:117
player_ai::love
int love[MAX_NUM_PLAYER_SLOTS]
Definition player.h:122
player_ai::expand
int expand
Definition player.h:116
player_ai::fuzzy
int fuzzy
Definition player.h:115
player_diplstate
Definition player.h:196
player_diplstate::type
enum diplstate_type type
Definition player.h:197
player_economic::luxury
int luxury
Definition player.h:64
player_economic::science
int science
Definition player.h:63
player_economic::tax
int tax
Definition player.h:62
player_economic::infra_points
int infra_points
Definition player.h:65
player_economic::gold
int gold
Definition player.h:61
player_score::units_killed
int units_killed
Definition player.h:103
player_score::landarea
int landarea
Definition player.h:92
player_score::mfg
int mfg
Definition player.h:100
player_score::population
int population
Definition player.h:94
player_score::pollution
int pollution
Definition player.h:97
player_score::wonders
int wonders
Definition player.h:89
player_score::settledarea
int settledarea
Definition player.h:93
player_score::units_used
int units_used
Definition player.h:106
player_score::specialists
int specialists[SP_MAX]
Definition player.h:88
player_score::units_lost
int units_lost
Definition player.h:104
player_score::angry
int angry
Definition player.h:87
player_score::techout
int techout
Definition player.h:91
player_score::game
int game
Definition player.h:108
player_score::units
int units
Definition player.h:96
player_score::units_built
int units_built
Definition player.h:102
player_score::content
int content
Definition player.h:85
player_score::happy
int happy
Definition player.h:84
player_score::spaceship
int spaceship
Definition player.h:101
player_score::culture
int culture
Definition player.h:107
player_score::unhappy
int unhappy
Definition player.h:86
player_score::cities
int cities
Definition player.h:95
player_score::bnp
int bnp
Definition player.h:99
player_score::literacy
int literacy
Definition player.h:98
player_score::techs
int techs
Definition player.h:90
player_spaceship
Definition spaceship.h:94
player_tile
Definition maphand.h:30
player_tile::extras_owner
struct player * extras_owner
Definition maphand.h:35
player_tile::last_updated
short last_updated
Definition maphand.h:44
player_tile::owner
struct player * owner
Definition maphand.h:34
player_tile::resource
struct extra_type * resource
Definition maphand.h:32
player
Definition player.h:247
player::cities
struct city_list * cities
Definition player.h:279
player::bulbs_last_turn
int bulbs_last_turn
Definition player.h:349
player::ai_common
struct player_ai ai_common
Definition player.h:286
player::flags
bv_plr_flags flags
Definition player.h:290
player::is_male
bool is_male
Definition player.h:255
player::wonders
int wonders[B_LAST]
Definition player.h:303
player::unassigned_ranked
bool unassigned_ranked
Definition player.h:253
player::target_government
struct government * target_government
Definition player.h:257
player::autoselect_weight
int autoselect_weight
Definition player.h:297
player::username
char username[MAX_LEN_NAME]
Definition player.h:250
player::revolution_finishes
int revolution_finishes
Definition player.h:271
player::nturns_idle
int nturns_idle
Definition player.h:263
player::government
struct government * government
Definition player.h:256
player::team
struct team * team
Definition player.h:259
player::turns_alive
int turns_alive
Definition player.h:264
player::ai
const struct ai_type * ai
Definition player.h:287
player::units
struct unit_list * units
Definition player.h:280
player::ranked_username
char ranked_username[MAX_LEN_NAME]
Definition player.h:252
player::huts
int huts
Definition player.h:347
player::is_alive
bool is_alive
Definition player.h:266
player::real_embassy
bv_player real_embassy
Definition player.h:275
player::economic
struct player_economic economic
Definition player.h:282
player::spaceship
struct player_spaceship spaceship
Definition player.h:284
player::attribute_block
struct attribute_block_s attribute_block
Definition player.h:305
player::score
struct player_score score
Definition player.h:281
player::multipliers
struct multiplier_value multipliers[MAX_NUM_MULTIPLIERS]
Definition player.h:312
player::nation
struct nation_type * nation
Definition player.h:258
player::style
struct nation_style * style
Definition player.h:277
player::border_vision
bool border_vision
Definition player.h:325
player::phase_done
bool phase_done
Definition player.h:261
player::adv
struct adv_data * adv
Definition player.h:332
player::server
struct player::@70::@72 server
player::history
int history
Definition player.h:314
player::orig_username
char orig_username[MAX_LEN_NAME]
Definition player.h:345
player::last_war_action
int last_war_action
Definition player.h:268
player::rgb
struct rgbcolor * rgb
Definition player.h:310
player::unassigned_user
bool unassigned_user
Definition player.h:251
research
Definition research.h:39
rgbcolor
Definition rgbcolor.h:33
savedata
Definition savegame3.c:264
savedata::save_reason
const char * save_reason
Definition savegame3.c:269
savedata::file
struct section_file * file
Definition savegame3.c:265
savedata::scenario
bool scenario
Definition savegame3.c:270
savedata::save_players
bool save_players
Definition savegame3.c:273
savedata::secfile_options
char secfile_options[512]
Definition savegame3.c:266
section_file
Definition section_file.h:36
server_arguments::metaserver_addr
char metaserver_addr[256]
Definition srv_main.h:29
server_arguments::serverid
char serverid[256]
Definition srv_main.h:49
server
Definition servers.h:29
startpos
Definition map.c:41
strvec
Definition string_vector.c:29
team_slot
Definition team.c:31
team
Definition team.c:40
terrain
Definition terrain.h:182
terrain::identifier
char identifier
Definition terrain.h:191
tile
Definition tile.h:50
tile::index
int index
Definition tile.h:51
tile::units
struct unit_list * units
Definition tile.h:58
tile::infra_turns
int infra_turns
Definition tile.h:62
tile::placing
struct extra_type * placing
Definition tile.h:61
tile::claimer
struct tile * claimer
Definition tile.h:64
timer
Definition timing.c:81
trade_route
Definition traderoutes.h:83
trade_route::dir
enum route_direction dir
Definition traderoutes.h:86
trade_route::partner
int partner
Definition traderoutes.h:84
treaty_cb_data
Definition savegame3.c:7726
treaty_cb_data::tidx
int tidx
Definition savegame3.c:7727
treaty_cb_data::file
struct section_file * file
Definition savegame3.c:7728
unit_order
Definition unit.h:92
unit_order::activity
enum unit_activity activity
Definition unit.h:94
unit_order::order
enum unit_orders order
Definition unit.h:93
unit_order::action
int action
Definition unit.h:100
unit_order::dir
enum direction8 dir
Definition unit.h:102
unit_order::target
int target
Definition unit.h:97
unit_order::sub_target
int sub_target
Definition unit.h:98
unit_type
Definition unittype.h:500
unit
Definition unit.h:138
unit::length
int length
Definition unit.h:195
unit::upkeep
int upkeep[O_LAST]
Definition unit.h:148
unit::has_orders
bool has_orders
Definition unit.h:193
unit::orders
struct unit::@80 orders
unit::action_decision_want
enum action_decision action_decision_want
Definition unit.h:202
unit::battlegroup
int battlegroup
Definition unit.h:191
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::ord_city
int ord_city
Definition unit.h:242
unit::moved
bool moved
Definition unit.h:173
unit::ord_map
int ord_map
Definition unit.h:241
unit::index
int index
Definition unit.h:195
unit::vision
struct vision * vision
Definition unit.h:244
unit::vigilant
bool vigilant
Definition unit.h:197
unit::hp
int hp
Definition unit.h:151
unit::fuel
int fuel
Definition unit.h:153
unit::changed_from_target
struct extra_type * changed_from_target
Definition unit.h:170
unit::current_form_turn
int current_form_turn
Definition unit.h:208
unit::stay
bool stay
Definition unit.h:205
unit::facing
enum direction8 facing
Definition unit.h:142
unit::server
struct unit::@81::@84 server
unit::activity_target
struct extra_type * activity_target
Definition unit.h:164
unit::activity_count
int activity_count
Definition unit.h:162
unit::list
struct unit_order * list
Definition unit.h:198
unit::changed_from
enum unit_activity changed_from
Definition unit.h:168
unit::nationality
struct player * nationality
Definition unit.h:144
unit::repeat
bool repeat
Definition unit.h:196
unit::homecity
int homecity
Definition unit.h:146
unit::paradropped
bool paradropped
Definition unit.h:174
unit::done_moving
bool done_moving
Definition unit.h:181
unit::birth_turn
int birth_turn
Definition unit.h:207
unit::carrying
struct goods_type * carrying
Definition unit.h:186
unit::goto_tile
struct tile * goto_tile
Definition unit.h:155
unit::action_decision_tile
struct tile * action_decision_tile
Definition unit.h:203
unit::veteran
int veteran
Definition unit.h:152
unit::changed_from_count
int changed_from_count
Definition unit.h:169
unit::ssa_controller
enum server_side_agent ssa_controller
Definition unit.h:172
universal
Definition fc_types.h:901
universal::kind
enum universals_n kind
Definition fc_types.h:903
universal::value
universals_u value
Definition fc_types.h:902
vision_site
Definition vision.h:109
worker_task
Definition workertask.h:21
worklist
Definition worklist.h:28
world::map
struct civ_map map
Definition world_object.h:38
city_style
int city_style(struct city *pcity)
Definition style.c:241
style_by_rule_name
struct nation_style * style_by_rule_name(const char *name)
Definition style.c:117
style_by_number
struct nation_style * style_by_number(int id)
Definition style.c:88
style_rule_name
const char * style_rule_name(const struct nation_style *pstyle)
Definition style.c:108
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
fc_strcasecmp
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
fc_vsnprintf
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:900
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
RETURN_VALUE_AFTER_EXIT
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:146
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
sz_strlcat
#define sz_strlcat(dest, src)
Definition support.h:190
team_index
int team_index(const struct team *pteam)
Definition team.c:383
team_slot_by_number
struct team_slot * team_slot_by_number(int team_id)
Definition team.c:175
team_add_player
bool team_add_player(struct player *pplayer, struct team *pteam)
Definition team.c:467
team_new
struct team * team_new(struct team_slot *tslot)
Definition team.c:317
team_members
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
advance_by_number
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
is_future_tech
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
valid_advance_by_number
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
advance_index
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
advance_by_rule_name
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
advance_number
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
A_FUTURE
#define A_FUTURE
Definition tech.h:46
advance_index_iterate_end
#define advance_index_iterate_end
Definition tech.h:248
A_FIRST
#define A_FIRST
Definition tech.h:44
A_NONE
#define A_NONE
Definition tech.h:43
advance_iterate
#define advance_iterate(_p)
Definition tech.h:275
A_UNSET
#define A_UNSET
Definition tech.h:48
advance_iterate_end
#define advance_iterate_end
Definition tech.h:276
A_UNKNOWN
#define A_UNKNOWN
Definition tech.h:49
A_LAST
#define A_LAST
Definition tech.h:45
advance_index_iterate
#define advance_index_iterate(_start, _index)
Definition tech.h:244
init_tech
void init_tech(struct research *research, bool update)
Definition techtools.c:1093
techtools.h
terrain_by_rule_name
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:186
terrain_identifier
char terrain_identifier(const struct terrain *pterrain)
Definition terrain.c:126
terrain_rule_name
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:247
terrain_has_resource
bool terrain_has_resource(const struct terrain *pterrain, const struct extra_type *presource)
Definition terrain.c:255
terrain_type_iterate
#define terrain_type_iterate(_p)
Definition terrain.h:373
T_UNKNOWN
#define T_UNKNOWN
Definition terrain.h:57
TERRAIN_UNKNOWN_IDENTIFIER
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:195
terrain_type_iterate_end
#define terrain_type_iterate_end
Definition terrain.h:379
tile_set_label
bool tile_set_label(struct tile *ptile, const char *label)
Definition tile.c:1095
tile_set_resource
void tile_set_resource(struct tile *ptile, struct extra_type *presource)
Definition tile.c:349
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_set_worked
void tile_set_worked(struct tile *ptile, struct city *pcity)
Definition tile.c:106
tile_index
#define tile_index(_pt_)
Definition tile.h:88
tile_worked
#define tile_worked(_tile)
Definition tile.h:114
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:110
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:43
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
tile_owner
#define tile_owner(_tile)
Definition tile.h:96
timer_destroy
void timer_destroy(struct timer *t)
Definition timing.c:208
timer_start
void timer_start(struct timer *t)
Definition timing.c:264
timer_stop
void timer_stop(struct timer *t)
Definition timing.c:308
timer_new
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
timer_read_seconds
double timer_read_seconds(struct timer *t)
Definition timing.c:384
timing.h
TIMER_DEBUG
#define TIMER_DEBUG
Definition timing.h:61
TIMER_CPU
@ TIMER_CPU
Definition timing.h:41
city_num_trade_routes
int city_num_trade_routes(const struct city *pcity)
Definition traderoutes.c:383
goods_by_rule_name
struct goods_type * goods_by_rule_name(const char *name)
Definition traderoutes.c:631
goods_rule_name
const char * goods_rule_name(struct goods_type *pgood)
Definition traderoutes.c:622
goods_by_number
struct goods_type * goods_by_number(Goods_type_id id)
Definition traderoutes.c:604
trade_routes_iterate_end
#define trade_routes_iterate_end
Definition traderoutes.h:134
trade_routes_iterate
#define trade_routes_iterate(c, proute)
Definition traderoutes.h:130
universals_u::building
const struct impr_type * building
Definition fc_types.h:717
free_unit_orders
void free_unit_orders(struct unit *punit)
Definition unit.c:1765
unit_transport_load
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2366
set_unit_activity
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1085
unit_nationality
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1242
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2437
can_unit_continue_current_activity
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:838
set_unit_activity_targeted
void set_unit_activity_targeted(struct unit *punit, enum unit_activity new_activity, struct extra_type *new_target)
Definition unit.c:1102
unit_virtual_create
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1620
unit_order_list_is_sane
bool unit_order_list_is_sane(const struct civ_map *nmap, int length, const struct unit_order *orders)
Definition unit.c:2645
unit_virtual_destroy
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1725
unit_tile_set
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1252
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:390
BATTLEGROUP_NONE
#define BATTLEGROUP_NONE
Definition unit.h:190
unit_orders
unit_orders
Definition unit.h:37
ORDER_ACTION_MOVE
@ ORDER_ACTION_MOVE
Definition unit.h:45
ORDER_ACTIVITY
@ ORDER_ACTIVITY
Definition unit.h:41
ORDER_FULL_MP
@ ORDER_FULL_MP
Definition unit.h:43
ORDER_MOVE
@ ORDER_MOVE
Definition unit.h:39
ORDER_LAST
@ ORDER_LAST
Definition unit.h:49
ORDER_PERFORM_ACTION
@ ORDER_PERFORM_ACTION
Definition unit.h:47
unit_owner
#define unit_owner(_pu)
Definition unit.h:389
unit_list_sort_ord_map
void unit_list_sort_ord_map(struct unit_list *punitlist)
Definition unitlist.c:73
unit_list_sort_ord_city
void unit_list_sort_ord_city(struct unit_list *punitlist)
Definition unitlist.c:85
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_safe
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_list_iterate_safe_end
#define unit_list_iterate_safe_end
Definition unitlist.h:61
resolve_unit_stacks
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1398
unit_refresh_vision
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4838
bounce_unit
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1225
unit_activity_needs_target_from_client
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1062
unittools.h
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
utype_upkeep_cost
int utype_upkeep_cost(const struct unit_type *ut, struct player *pplayer, Output_type_id otype)
Definition unittype.c:132
unit_type_by_rule_name
struct unit_type * unit_type_by_rule_name(const char *name)
Definition unittype.c:1767
unit_rule_name
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
utype_veteran_levels
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2613
utype_index
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
unit_type_iterate
#define unit_type_iterate(_p)
Definition unittype.h:852
U_LAST
#define U_LAST
Definition unittype.h:40
unit_type_iterate_end
#define unit_type_iterate_end
Definition unittype.h:859
freeciv_datafile_version
const char * freeciv_datafile_version(void)
Definition version.c:186
version.h
vision_site_size_set
void vision_site_size_set(struct vision_site *psite, citizens size)
Definition vision.c:165
vision_site_size_get
citizens vision_site_size_get(const struct vision_site *psite)
Definition vision.c:155
vision_new
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
vision_reveal_tiles
bool vision_reveal_tiles(struct vision *vision, bool reveal_tiles)
Definition vision.c:62
vision_site_new
struct vision_site * vision_site_new(int identity, struct tile *location, struct player *owner)
Definition vision.c:86
vision_site_destroy
void vision_site_destroy(struct vision_site *psite)
Definition vision.c:74
vision_site_owner
#define vision_site_owner(v)
Definition vision.h:128
worker_task_is_sane
bool worker_task_is_sane(struct worker_task *ptask)
Definition workertask.c:40
worker_task_list_iterate
#define worker_task_list_iterate(tasklist, ptask)
Definition workertask.h:33
worker_task_list_iterate_end
#define worker_task_list_iterate_end
Definition workertask.h:35
worklist_init
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
MAX_LEN_WORKLIST
#define MAX_LEN_WORKLIST
Definition worklist.h:24