Freeciv-3.3: /fast/freeciv/nightly/main/server/savegame/savegame3.c Source File

Freeciv-3.3

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