Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/savegame/savegame3.c Source File

Freeciv-3.1

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