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