853
1155
/* Owner and ownership source are stored as plain numbers */
854
1156
if (has_capability("new_owner_map", savefile_options)) {
857
for (y = 0; y < map.ysize; y++) {
859
secfile_lookup_str_default(file, NULL, "map.owner%03d", y);
862
if (buffer == NULL) {
863
die("Savegame corrupt - map line %d not found.", y);
865
for (x = 0; x < map.xsize; x++) {
866
char token[TOKEN_SIZE];
868
struct tile *ptile = native_pos_to_tile(x, y);
870
scanin(&ptr, ",", token, sizeof(token));
871
if (token[0] == '\0') {
872
die("Savegame corrupt - map size not correct.");
874
if (strcmp(token, "-") == 0) {
875
tile_set_owner(ptile, NULL);
877
if (sscanf(token, "%d", &number)) {
878
tile_set_owner(ptile, get_player(number));
880
die("Savegame corrupt - got map owner %s in (%d, %d).",
886
for (y = 0; y < map.ysize; y++) {
1158
struct player *owner = NULL;
1159
struct tile *claimer = NULL;
1161
for (y = 0; y < map.ysize; y++) {
1163
secfile_lookup_str_default(file, NULL, "map.owner%03d", y);
888
secfile_lookup_str_default(file, NULL, "map.source%03d", y);
1165
secfile_lookup_str_default(file, NULL, "map.source%03d", y);
1166
char *ptr1 = buffer1;
889
1167
char *ptr2 = buffer2;
1169
if (buffer1 == NULL) {
1170
die("Savegame corrupt - map line %d not found.", y);
891
1172
if (buffer2 == NULL) {
892
1173
die("Savegame corrupt - map line %d not found.", y);
894
1175
for (x = 0; x < map.xsize; x++) {
1176
char token1[TOKEN_SIZE];
895
1177
char token2[TOKEN_SIZE];
897
1179
struct tile *ptile = native_pos_to_tile(x, y);
1181
scanin(&ptr1, ",", token1, sizeof(token1));
899
1182
scanin(&ptr2, ",", token2, sizeof(token2));
900
if (token2[0] == '\0') {
1183
if (token1[0] == '\0' || token2[0] == '\0') {
901
1184
die("Savegame corrupt - map size not correct.");
1186
if (strcmp(token1, "-") == 0) {
1189
if (sscanf(token1, "%d", &number)) {
1190
owner = player_by_number(number);
1192
die("Savegame corrupt - got map owner %s in (%d, %d).",
903
1196
if (strcmp(token2, "-") == 0) {
904
ptile->owner_source = NULL;
906
1199
if (sscanf(token2, "%d", &number)) {
907
ptile->owner_source = index_to_tile(number);
1200
claimer = index_to_tile(number);
909
1202
die("Savegame corrupt - got map source %s in (%d, %d).",
1207
map_claim_ownership(ptile, owner, claimer);
1212
if (has_capability("bases", savefile_options)) {
1213
char zeroline[map.xsize+1];
1216
/* This is needed when new bases has been added to ruleset, and
1217
* thus game.control.num_base_types is greater than, when game was saved. */
1218
for (i = 0; i < map.xsize; i++) {
1223
bases_halfbyte_iterate(j, num_bases_types) {
1224
char buf[16]; /* enough for sprintf() below */
1225
sprintf(buf, "map.b%02d_%%03d", j);
1227
LOAD_MAP_DATA(ch, nat_y, ptile,
1228
secfile_lookup_str_default(file, zeroline, buf, nat_y),
1229
set_savegame_bases(&ptile->bases, ch, base_order + 4 * j));
1230
} bases_halfbyte_iterate_end;
917
1233
if (secfile_lookup_bool_default(file, TRUE, "game.save_known")) {
918
1234
int known[MAP_INDEX_SIZE];
920
1236
/* get 4-bit segments of the first half of the 32-bit "known" field */
921
1237
LOAD_MAP_DATA(ch, nat_y, ptile,
922
1238
secfile_lookup_str(file, "map.a%03d", nat_y),
923
known[ptile->index] = ascii_hex2bin(ch, 0));
1239
known[tile_index(ptile)] = ascii_hex2bin(ch, 0));
924
1240
LOAD_MAP_DATA(ch, nat_y, ptile,
925
1241
secfile_lookup_str(file, "map.b%03d", nat_y),
926
known[ptile->index] |= ascii_hex2bin(ch, 1));
1242
known[tile_index(ptile)] |= ascii_hex2bin(ch, 1));
927
1243
LOAD_MAP_DATA(ch, nat_y, ptile,
928
1244
secfile_lookup_str(file, "map.c%03d", nat_y),
929
known[ptile->index] |= ascii_hex2bin(ch, 2));
1245
known[tile_index(ptile)] |= ascii_hex2bin(ch, 2));
930
1246
LOAD_MAP_DATA(ch, nat_y, ptile,
931
1247
secfile_lookup_str(file, "map.d%03d", nat_y),
932
known[ptile->index] |= ascii_hex2bin(ch, 3));
1248
known[tile_index(ptile)] |= ascii_hex2bin(ch, 3));
934
1250
if (has_capability("known32fix", savefile_options)) {
935
1251
/* get 4-bit segments of the second half of the 32-bit "known" field */
936
1252
LOAD_MAP_DATA(ch, nat_y, ptile,
937
1253
secfile_lookup_str(file, "map.e%03d", nat_y),
938
known[ptile->index] |= ascii_hex2bin(ch, 4));
1254
known[tile_index(ptile)] |= ascii_hex2bin(ch, 4));
939
1255
LOAD_MAP_DATA(ch, nat_y, ptile,
940
1256
secfile_lookup_str(file, "map.g%03d", nat_y),
941
known[ptile->index] |= ascii_hex2bin(ch, 5));
1257
known[tile_index(ptile)] |= ascii_hex2bin(ch, 5));
942
1258
LOAD_MAP_DATA(ch, nat_y, ptile,
943
1259
secfile_lookup_str(file, "map.h%03d", nat_y),
944
known[ptile->index] |= ascii_hex2bin(ch, 6));
1260
known[tile_index(ptile)] |= ascii_hex2bin(ch, 6));
945
1261
LOAD_MAP_DATA(ch, nat_y, ptile,
946
1262
secfile_lookup_str(file, "map.i%03d", nat_y),
947
known[ptile->index] |= ascii_hex2bin(ch, 7));
1263
known[tile_index(ptile)] |= ascii_hex2bin(ch, 7));
950
1266
/* HACK: we read the known data from hex into a 32-bit integer, and
951
1267
* now we convert it to bv_player. */
952
1268
whole_map_iterate(ptile) {
953
1269
BV_CLR_ALL(ptile->tile_known);
954
players_iterate(pplayer) {
955
if (known[ptile->index] & (1u << pplayer->player_no)) {
956
BV_SET(ptile->tile_known, pplayer->player_no);
958
} players_iterate_end;
1270
player_slots_iterate(pslot) {
1271
if (known[tile_index(ptile)] & (1u << player_index(pslot))) {
1272
map_set_known(ptile, pslot);
1274
} player_slots_iterate_end;
959
1275
} whole_map_iterate_end;
963
map.have_resources = TRUE;
1277
map.server.have_resources = TRUE;
966
1280
/***************************************************************
2225
2535
spaceship_calc_derived(ship);
2540
/****************************************************************************
2542
****************************************************************************/
2543
static void player_load_cities(struct player *plr, int plrno,
2544
struct section_file *file,
2545
char *savefile_options,
2546
char **improvement_order,
2547
int improvement_order_size)
2549
char named[MAX_LEN_NAME];
2550
struct player *past;
2556
int ncities = secfile_lookup_int(file, "player%d.ncities", plrno);
2229
2558
plr->cities = city_list_new();
2230
ncities=secfile_lookup_int(file, "player%d.ncities", plrno);
2231
2560
if (!plr->is_alive && ncities > 0) {
2561
freelog(LOG_ERROR, "player%d.ncities=%d for dead player!",
2232
2564
ncities = 0; /* Some old savegames may be buggy. */
2235
2567
for (i = 0; i < ncities; i++) { /* read the cities */
2239
2568
int citizens = 0;
2569
int nat_y = secfile_lookup_int(file, "player%d.c%d.y", plrno, i);
2240
2570
int nat_x = secfile_lookup_int(file, "player%d.c%d.x", plrno, i);
2241
int nat_y = secfile_lookup_int(file, "player%d.c%d.y", plrno, i);
2242
struct tile *ptile = native_pos_to_tile(nat_x, nat_y);
2244
pcity = create_city_virtual(plr, ptile,
2245
secfile_lookup_str(file, "player%d.c%d.name", plrno, i));
2246
ptile->owner_source = pcity->tile;
2247
tile_set_owner(ptile, plr);
2249
pcity->id=secfile_lookup_int(file, "player%d.c%d.id", plrno, i);
2250
alloc_id(pcity->id);
2571
struct tile *pcenter = native_pos_to_tile(nat_x, nat_y);
2574
if (NULL == pcenter) {
2575
freelog(LOG_FATAL, "player%d.c%d invalid tile (%d,%d)",
2581
if (NULL != tile_city(pcenter)) {
2582
freelog(LOG_FATAL, "player%d.c%d duplicate city (%d,%d)",
2588
/* lookup name out of order */
2589
my_snprintf(named, sizeof(named), "player%d.c%d.name", plrno, i);
2590
/* instead of dying, use name string for damaged name */
2591
name = secfile_lookup_str_default(file, named, "%s", named);
2592
/* copied into city->name */
2593
pcity = create_city_virtual(plr, pcenter, name);
2595
pcity->id = secfile_lookup_int(file, "player%d.c%d.id", plrno, i);
2596
identity_number_reserve(pcity->id);
2251
2597
idex_register_city(pcity);
2253
id = secfile_lookup_int_default(file, -1,
2599
id = secfile_lookup_int_default(file, plrno,
2254
2600
"player%d.c%d.original", plrno, i);
2255
if (id >= 0 && id < game.info.nplayers) {
2256
pcity->original = get_player(id);
2258
pcity->original = get_player(plrno);
2601
past = player_by_number(id);
2603
pcity->original = past;
2261
pcity->size=secfile_lookup_int(file, "player%d.c%d.size", plrno, i);
2606
tile_set_owner(pcenter, plr, pcenter); /* for city_owner(), just in case? */
2607
/* no city_choose_build_default(), values loaded below! */
2263
pcity->steal=secfile_lookup_int(file, "player%d.c%d.steal", plrno, i);
2609
pcity->size = secfile_lookup_int(file, "player%d.c%d.size", plrno, i);
2265
2611
specialist_type_iterate(sp) {
2267
pcity->specialists[sp]
2268
= secfile_lookup_int(file, "player%d.c%d.n%s", plrno, i,
2269
get_specialist(sp)->name);
2613
pcity->specialists[sp] =
2614
secfile_lookup_int(file, "player%d.c%d.n%s", plrno, i,
2615
specialist_rule_name(specialist_by_number(sp)));
2270
2616
} specialist_type_iterate_end;
2272
for (j = 0; j < NUM_TRADEROUTES; j++)
2273
pcity->trade[j]=secfile_lookup_int(file, "player%d.c%d.traderoute%d",
2276
pcity->food_stock = secfile_lookup_int(file, "player%d.c%d.food_stock",
2278
pcity->shield_stock = secfile_lookup_int(file,
2279
"player%d.c%d.shield_stock",
2281
pcity->anarchy = secfile_lookup_int(file, "player%d.c%d.anarchy",
2283
pcity->rapture = secfile_lookup_int_default(file, 0,
2284
"player%d.c%d.rapture",
2286
pcity->was_happy = secfile_lookup_bool(file,
2287
"player%d.c%d.was_happy",
2289
pcity->production.is_unit =
2290
secfile_lookup_bool(file,
2291
"player%d.c%d.is_building_unit", plrno, i);
2292
name = secfile_lookup_str_default(file, NULL,
2293
"player%d.c%d.currently_building_name",
2295
if (pcity->production.is_unit) {
2297
id = secfile_lookup_int(file, "player%d.c%d.currently_building",
2299
name = old_unit_type_name(id);
2301
pcity->production.value = find_unit_type_by_rule_name(name)->index;
2304
id = secfile_lookup_int(file, "player%d.c%d.currently_building",
2306
name = old_impr_type_name(id);
2308
pcity->production.value = find_improvement_by_rule_name(name);
2618
for (j = 0; j < NUM_TRADE_ROUTES; j++) {
2620
secfile_lookup_int(file, "player%d.c%d.traderoute%d", plrno, i, j);
2624
secfile_lookup_int(file, "player%d.c%d.food_stock", plrno, i);
2625
pcity->shield_stock =
2626
secfile_lookup_int(file, "player%d.c%d.shield_stock", plrno, i);
2629
secfile_lookup_int_default(file, 0, "player%d.c%d.airlift", plrno,i);
2631
secfile_lookup_bool_default(file, FALSE, "player%d.c%d.was_happy",
2633
pcity->turn_plague =
2634
secfile_lookup_int_default(file, 0, "player%d.c%d.turn_plague",
2638
secfile_lookup_int(file, "player%d.c%d.anarchy", plrno, i);
2640
secfile_lookup_int_default(file, 0, "player%d.c%d.rapture",
2643
secfile_lookup_int_default(file, 0, "player%d.c%d.steal",
2646
/* before did_buy for undocumented hack */
2647
pcity->turn_founded =
2648
secfile_lookup_int_default(file, -2, "player%d.c%d.turn_founded",
2650
j = secfile_lookup_int(file, "player%d.c%d.did_buy", plrno, i);
2651
pcity->did_buy = (j != 0);
2652
if (j == -1 && pcity->turn_founded == -2) {
2653
/* undocumented hack */
2654
pcity->turn_founded = game.info.turn;
2657
secfile_lookup_bool_default(file, FALSE, "player%d.c%d.did_sell", plrno,i);
2311
2659
if (has_capability("turn_last_built", savefile_options)) {
2312
pcity->turn_last_built = secfile_lookup_int(file,
2313
"player%d.c%d.turn_last_built", plrno, i);
2660
pcity->turn_last_built =
2661
secfile_lookup_int(file, "player%d.c%d.turn_last_built", plrno, i);
2315
2663
/* Before, turn_last_built was stored as a year. There is no easy
2316
2664
* way to convert this into a turn value. */
2317
2665
pcity->turn_last_built = 0;
2319
pcity->changed_from.is_unit =
2320
secfile_lookup_bool_default(file, pcity->production.is_unit,
2321
"player%d.c%d.changed_from_is_unit",
2668
kind = secfile_lookup_str_default(file, NULL,
2669
"player%d.c%d.currently_building_kind",
2672
/* before 2.2.0 unit production was indicated by flag. */
2673
bool is_unit = secfile_lookup_bool_default(file, FALSE,
2674
"player%d.c%d.is_building_unit",
2676
kind = universal_kind_name(is_unit ? VUT_UTYPE : VUT_IMPROVEMENT);
2679
name = secfile_lookup_str_default(file, NULL,
2680
"player%d.c%d.currently_building_name",
2683
/* before 1.15.0 production was saved by id. */
2684
int id = secfile_lookup_int_default(file, -1,
2685
"player%d.c%d.currently_building",
2687
switch (pcity->production.kind) {
2689
name = old_unit_type_name(id);
2692
"player%d.c%d.currently_building: unknown unit (%d)",
2697
case VUT_IMPROVEMENT:
2698
name = old_impr_type_name(id);
2701
"player%d.c%d.currently_building: unknown improvement (%d)",
2707
freelog(LOG_FATAL, "player%d.c%d.currently_building: version mismatch.",
2712
pcity->production = universal_by_rule_name(kind, name);
2713
if (VUT_LAST == pcity->production.kind) {
2714
freelog(LOG_FATAL, "player%d.c%d.currently_building: unknown \"%s\" \"%s\".",
2715
plrno, i, kind, name);
2719
kind = secfile_lookup_str_default(file, NULL,
2720
"player%d.c%d.changed_from_kind",
2723
/* before 2.2.0 unit production was indicated by flag. */
2724
bool is_unit = secfile_lookup_bool_default(file, FALSE,
2725
"player%d.c%d.changed_from_is_unit",
2727
kind = universal_kind_name(is_unit ? VUT_UTYPE : VUT_IMPROVEMENT);
2323
2730
name = secfile_lookup_str_default(file, NULL,
2324
2731
"player%d.c%d.changed_from_name",
2326
if (pcity->changed_from.is_unit) {
2328
id = secfile_lookup_int(file, "player%d.c%d.changed_from_id",
2330
name = old_unit_type_name(id);
2332
pcity->changed_from.value = find_unit_type_by_rule_name(name)->index;
2335
id = secfile_lookup_int(file, "player%d.c%d.changed_from_id",
2337
name = old_impr_type_name(id);
2339
pcity->changed_from.value = find_improvement_by_rule_name(name);
2342
pcity->before_change_shields=
2734
/* before 1.15.0 production was saved by id. */
2735
int id = secfile_lookup_int_default(file, -1,
2736
"player%d.c%d.changed_from_id",
2738
switch (pcity->production.kind) {
2740
name = old_unit_type_name(id);
2743
"player%d.c%d.changed_from_id: unknown unit (%d)",
2748
case VUT_IMPROVEMENT:
2749
name = old_impr_type_name(id);
2752
"player%d.c%d.changed_from_id: unknown improvement (%d)",
2758
freelog(LOG_FATAL, "player%d.c%d.changed_from_id: version mismatch.",
2763
pcity->changed_from = universal_by_rule_name(kind, name);
2764
if (VUT_LAST == pcity->changed_from.kind) {
2765
freelog(LOG_FATAL, "player%d.c%d.changed_from: unknown \"%s\" \"%s\".",
2766
plrno, i, kind, name);
2770
pcity->before_change_shields =
2343
2771
secfile_lookup_int_default(file, pcity->shield_stock,
2344
2772
"player%d.c%d.before_change_shields", plrno, i);
2345
pcity->disbanded_shields=
2773
pcity->caravan_shields =
2774
secfile_lookup_int_default(file, 0,
2775
"player%d.c%d.caravan_shields", plrno, i);
2776
pcity->disbanded_shields =
2346
2777
secfile_lookup_int_default(file, 0,
2347
2778
"player%d.c%d.disbanded_shields", plrno, i);
2348
pcity->caravan_shields=
2349
secfile_lookup_int_default(file, 0,
2350
"player%d.c%d.caravan_shields", plrno, i);
2351
2779
pcity->last_turns_shield_surplus =
2352
2780
secfile_lookup_int_default(file, 0,
2353
2781
"player%d.c%d.last_turns_shield_surplus",
2356
pcity->synced = FALSE; /* must re-sync with clients */
2358
pcity->turn_founded =
2359
secfile_lookup_int_default(file, -2, "player%d.c%d.turn_founded",
2362
j = secfile_lookup_int(file, "player%d.c%d.did_buy", plrno, i);
2363
pcity->did_buy = (j != 0);
2364
if (j == -1 && pcity->turn_founded == -2) {
2365
pcity->turn_founded = game.info.turn;
2369
secfile_lookup_bool_default(file, FALSE, "player%d.c%d.did_sell", plrno,i);
2371
pcity->airlift = secfile_lookup_bool_default(file, FALSE,
2372
"player%d.c%d.airlift", plrno,i);
2374
/* New city-options form as of freeciv 2.1. Old (<= 2.0) city options
2375
* are lost on upgrade. */
2376
BV_CLR_ALL(pcity->city_options);
2377
for (j = 0; j < CITYO_LAST; j++) {
2378
if (secfile_lookup_bool_default(file, FALSE,
2379
"player%d.c%d.option%d",
2381
BV_SET(pcity->city_options, j);
2784
pcity->server.synced = FALSE; /* must re-sync with clients */
2385
2786
/* Fix for old buggy savegames. */
2386
2787
if (!has_capability("known32fix", savefile_options)
2387
2788
&& plrno >= 16) {
2388
map_city_radius_iterate(pcity->tile, tile1) {
2789
city_tile_iterate(pcenter, tile1) {
2389
2790
map_set_known(tile1, plr);
2390
} map_city_radius_iterate_end;
2791
} city_tile_iterate_end;
2393
/* adding the cities contribution to fog-of-war */
2394
pcity->server.vision = vision_new(city_owner(pcity), pcity->tile, FALSE);
2395
city_refresh_vision(pcity);
2397
2794
pcity->units_supported = unit_list_new();
2399
/* Initialize pcity->city_map[][], using set_worker_city() so that
2400
ptile->worked gets initialized correctly. The pre-initialisation
2401
to C_TILE_EMPTY is necessary because set_worker_city() accesses
2402
the existing value to possibly adjust ptile->worked, so need to
2403
initialize a non-worked value so ptile->worked (possibly already
2404
set from neighbouring city) does not get unset for C_TILE_EMPTY
2405
or C_TILE_UNAVAILABLE here. -- dwp
2407
p=secfile_lookup_str(file, "player%d.c%d.workers", plrno, i);
2408
for(y=0; y<CITY_MAP_SIZE; y++) {
2409
for(x=0; x<CITY_MAP_SIZE; x++) {
2410
bool valid = is_valid_city_coords(x, y);
2411
pcity->city_map[x][y] = valid ? C_TILE_EMPTY : C_TILE_UNAVAILABLE;
2415
/* oops, inconsistent savegame; minimal fix: */
2416
freelog(LOG_VERBOSE, "Invalid workers '%c' for %s (%d,%d), "
2417
"ignoring", *p, city_name(pcity), x, y);
2796
/* Update pcity->city_map[][] and ptile->worked directly.
2797
Initialized to C_TILE_UNUSABLE (0) by create_city_virtual().
2798
Ensure ptile->worked (possibly already set from neighbouring
2799
city) does not get unset by conflicting values. Principally for
2800
repair_city_worker() below.
2802
city_freeze_workers(pcity);
2804
p = secfile_lookup_str(file, "player%d.c%d.workers", plrno, i);
2806
if (strlen(p) != CITY_MAP_SIZE * CITY_MAP_SIZE) {
2807
/* FIXME: somehow need to rearrange */
2808
freelog(LOG_ERROR, "player%d.c%d.workers"
2809
" length %lu not equal city map size %lu, needs rearranging!",
2811
(unsigned long)strlen(p),
2812
(unsigned long)(CITY_MAP_SIZE * CITY_MAP_SIZE));
2815
for(y = 0; y < CITY_MAP_SIZE; y++) {
2816
struct city *pwork = NULL;
2819
for(x = 0; x < CITY_MAP_SIZE; x++) {
2820
struct tile *ptile = is_valid_city_coords(x, y)
2821
? city_map_to_tile(pcenter, x, y)
2826
/* too short, will yield very odd results! */
2830
if (NULL == ptile) {
2831
freelog(LOG_WORKER, "player%d.c%d.workers"
2832
" {%d,%d} '%c' not valid for (%d,%d) \"%s\"[%d], ignoring",
2835
TILE_XY(pcenter), city_name(pcity), pcity->size);
2836
} else if (NULL != (pwork = tile_worked(ptile))) {
2837
freelog(LOG_WORKER, "player%d.c%d.workers"
2838
" {%d,%d} '%c' conflict at (%d,%d)"
2839
" for (%d,%d) \"%s\"[%d]"
2840
" with (%d,%d) \"%s\"[%d],"
2841
" converting to unavailable",
2845
TILE_XY(pcenter), city_name(pcity), pcity->size,
2846
TILE_XY(city_tile(pwork)), city_name(pwork), pwork->size);
2847
pcity->city_map[x][y] = C_TILE_UNAVAILABLE;
2419
set_worker_city(pcity, x, y,
2420
NULL != city_map_to_map(pcity, x, y)
2421
? C_TILE_EMPTY : C_TILE_UNAVAILABLE);
2849
pcity->city_map[x][y] = C_TILE_EMPTY;
2423
} else if (*p=='1') {
2426
/* oops, inconsistent savegame; minimal fix: */
2427
freelog(LOG_VERBOSE, "Invalid workers '%c' for %s (%d,%d), "
2428
"ignoring", *p, city_name(pcity), x, y);
2429
} else if (NULL == (ptile = city_map_to_map(pcity, x, y))
2431
/* oops, inconsistent savegame; minimal fix: */
2432
freelog(LOG_VERBOSE, "Inconsistent worked for %s (%d,%d), "
2433
"converting to specialist", city_name(pcity), x, y);
2854
if (NULL == ptile) {
2855
freelog(LOG_WORKER, "player%d.c%d.workers"
2856
" {%d,%d} '%c' not valid for (%d,%d) \"%s\"[%d], ignoring",
2859
TILE_XY(pcenter), city_name(pcity), pcity->size);
2860
} else if (NULL != (pwork = tile_worked(ptile))) {
2861
freelog(LOG_WORKER, "player%d.c%d.workers"
2862
" {%d,%d} '%c' conflict at (%d,%d)"
2863
" for (%d,%d) \"%s\"[%d]"
2864
" with (%d,%d) \"%s\"[%d],"
2865
" converting to default specialist",
2869
TILE_XY(pcenter), city_name(pcity), pcity->size,
2870
TILE_XY(city_tile(pwork)), city_name(pwork), pwork->size);
2872
pcity->city_map[x][y] = C_TILE_UNAVAILABLE;
2434
2873
pcity->specialists[DEFAULT_SPECIALIST]++;
2435
set_worker_city(pcity, x, y, C_TILE_UNAVAILABLE);
2438
set_worker_city(pcity, x, y, C_TILE_WORKER);
2441
} else if (*p == '2') {
2443
set_worker_city(pcity, x, y, C_TILE_UNAVAILABLE);
2445
assert(pcity->city_map[x][y] == C_TILE_UNAVAILABLE);
2447
freelog(LOG_VERBOSE, "Invalid workers '%c' for %s (%d,%d), "
2448
"ignoring", *p, city_name(pcity), x, y);
2874
auto_arrange_workers(pcity);
2877
pcity->city_map[x][y] = C_TILE_WORKER;
2878
tile_set_worked(ptile, pcity);
2883
case S_TILE_UNAVAILABLE:
2884
if (NULL == ptile) {
2885
/* before 2.2.0 same as C_TILE_UNUSABLE */
2887
pcity->city_map[x][y] = C_TILE_UNAVAILABLE;
2891
case S_TILE_UNKNOWN:
2892
if (NULL == ptile) {
2893
/* already set C_TILE_UNUSABLE */
2895
freelog(LOG_WORKER, "player%d.c%d.workers"
2896
" {%d,%d} '%c' not valid at (%d,%d)"
2897
" for (%d,%d) \"%s\"[%d],"
2898
" converting to unavailable",
2902
TILE_XY(pcenter), city_name(pcity), pcity->size);
2903
pcity->city_map[x][y] = C_TILE_UNAVAILABLE;
2908
freelog(LOG_WORKER, "player%d.c%d.workers"
2909
" {%d,%d} '%c' not valid for (%d,%d) \"%s\"[%d], ignoring",
2912
TILE_XY(pcenter), city_name(pcity), pcity->size);
2453
/* center tile worker isn't counted in city size */
2919
if (tile_worked(pcenter) != pcity) {
2920
struct city *pwork = tile_worked(pcenter);
2922
if (NULL != pwork) {
2925
freelog(LOG_ERROR, "player%d.c%d.workers"
2926
" city center is worked by (%d,%d) \"%s\"[%d],"
2927
" repairing (%d,%d) \"%s\"[%d]",
2929
TILE_XY(city_tile(pwork)), city_name(pwork), pwork->size,
2930
TILE_XY(pcenter), city_name(pcity), pcity->size);
2932
city_tile_to_city_map(&city_x, &city_y, city_tile(pwork), pcenter);
2933
pwork->city_map[city_x][city_y] = C_TILE_UNAVAILABLE;
2934
pwork->specialists[DEFAULT_SPECIALIST]++;
2935
auto_arrange_workers(pwork);
2937
freelog(LOG_ERROR, "player%d.c%d.workers"
2938
" city center is empty,"
2939
" repairing (%d,%d) \"%s\"[%d]",
2941
TILE_XY(pcenter), city_name(pcity), pcity->size);
2944
pcity->city_map[CITY_MAP_SIZE/2][CITY_MAP_SIZE/2] = C_TILE_WORKER;
2945
tile_set_worked(pcenter, pcity); /* repair */
2947
city_repair_size(pcity, -1);
2457
if (citizens != pcity->size) {
2458
freelog(LOG_ERROR, "player_load()"
2459
" %d citizens not equal %d city size in \"%s\".",
2950
k = pcity->size + FREE_WORKED_TILES - citizens;
2952
freelog(LOG_ERROR, "player%d.c%d.workers"
2953
" %d citizens not equal %d + [size],"
2954
" repairing (%d,%d) \"%s\"[%d]",
2956
citizens, FREE_WORKED_TILES,
2957
TILE_XY(pcenter), city_name(pcity), pcity->size);
2959
city_repair_size(pcity, k);
2465
2962
/* Initialise list of improvements with City- and Building-wide
2466
2963
equiv_ranges */
2467
for (k = 0; k < ARRAY_SIZE(pcity->improvements); k++) {
2468
pcity->improvements[k] = I_NONE;
2964
for (k = 0; k < ARRAY_SIZE(pcity->built); k++) {
2965
pcity->built[k].turn = I_NEVER;
2968
/* For new savegames using the improvement_order[] list, any unknown
2969
* improvements are ignored. Older games are more strictly enforced,
2970
* as an invalid index is probably indication of corruption.
2471
2972
p = secfile_lookup_str_default(file, NULL,
2472
2973
"player%d.c%d.improvements_new",
2679
3261
map_get_player_tile(ptile, plr)->last_updated |=
2680
3262
ascii_hex2bin(ch, 3));
2684
i = secfile_lookup_int(file, "player%d.total_ncities", plrno);
2685
for (j = 0; j < i; j++) {
2690
struct vision_base *pdcity = fc_calloc(1, sizeof(*pdcity));
2692
pdcity->identity = secfile_lookup_int(file, "player%d.dc%d.id", plrno, j);
2693
if (VISION_BASE_RUIN >= pdcity->identity) {
2694
freelog(LOG_ERROR, "[player%d] dc%d has invalid id (%d); skipping.",
2695
plrno, j, pdcity->identity);
2700
nat_x = secfile_lookup_int(file, "player%d.dc%d.x", plrno, j);
2701
nat_y = secfile_lookup_int(file, "player%d.dc%d.y", plrno, j);
2702
ptile = native_pos_to_tile(nat_x, nat_y);
2703
pdcity->location = ptile;
2705
sz_strlcpy(pdcity->name, secfile_lookup_str(file, "player%d.dc%d.name", plrno, j));
2706
pdcity->size = secfile_lookup_int(file, "player%d.dc%d.size", plrno, j);
2707
pdcity->occupied = secfile_lookup_bool_default(file, FALSE,
2708
"player%d.dc%d.occupied", plrno, j);
2709
pdcity->walls = secfile_lookup_bool_default(file, FALSE,
2710
"player%d.dc%d.walls", plrno, j);
2711
pdcity->happy = secfile_lookup_bool_default(file, FALSE,
2712
"player%d.dc%d.happy", plrno, j);
2713
pdcity->unhappy = secfile_lookup_bool_default(file, FALSE,
2714
"player%d.dc%d.unhappy", plrno, j);
2716
id = secfile_lookup_int(file, "player%d.dc%d.owner", plrno, j);
2717
pdcity->owner = get_player(id);
2718
if (NULL == vision_owner(pdcity)) {
2719
freelog(LOG_ERROR, "[player%d] dc%d has invalid owner (%d); skipping.",
2725
/* Initialise list of improvements */
2726
BV_CLR_ALL(pdcity->improvements);
2728
p = secfile_lookup_str_default(file, NULL,
2729
"player%d.dc%d.improvements", plrno, j);
2733
for (k = 0; k < improvement_order_size && p[k]; k++) {
2735
id = find_improvement_by_rule_name(improvement_order[k]);
2737
BV_SET(pdcity->improvements, id);
2743
map_get_player_tile(ptile, plr)->vision_source = pdcity;
2744
alloc_id(pdcity->identity);
3264
for (i = 0; i < total_ncities; i++) {
3265
/* similar to create_vision_site() */
3266
struct vision_site *pdcity = create_vision_site(0, NULL, NULL);
3268
nat_y = secfile_lookup_int(file, "player%d.dc%d.y", plrno, i);
3269
nat_x = secfile_lookup_int(file, "player%d.dc%d.x", plrno, i);
3270
pdcity->location = native_pos_to_tile(nat_x, nat_y);
3271
if (NULL == pdcity->location) {
3272
freelog(LOG_ERROR, "player%d.dc%d invalid tile (%d,%d)",
3279
pdcity->identity = secfile_lookup_int(file, "player%d.dc%d.id", plrno, i);
3280
if (IDENTITY_NUMBER_ZERO >= pdcity->identity) {
3281
freelog(LOG_ERROR, "player%d.dc%d has invalid id (%d); skipping.",
3282
plrno, i, pdcity->identity);
3287
id = secfile_lookup_int(file, "player%d.dc%d.owner", plrno, i);
3289
/* Earlier versions redundantly saved the dummy for their own cities.
3290
* Since 2.2.0, map_claim_ownership() rebuilds them at city load time.
3292
freelog(LOG_VERBOSE, "player%d.dc%d has same owner (%d); skipping.",
3298
pdcity->owner = player_by_number(id);
3299
if (NULL == vision_owner(pdcity)) {
3300
freelog(LOG_ERROR, "player%d.dc%d has invalid owner (%d); skipping.",
3306
pdcity->size = secfile_lookup_int(file, "player%d.dc%d.size", plrno, i);
3307
pdcity->occupied = secfile_lookup_bool_default(file, FALSE,
3308
"player%d.dc%d.occupied", plrno, i);
3309
pdcity->walls = secfile_lookup_bool_default(file, FALSE,
3310
"player%d.dc%d.walls", plrno, i);
3311
pdcity->happy = secfile_lookup_bool_default(file, FALSE,
3312
"player%d.dc%d.happy", plrno, i);
3313
pdcity->unhappy = secfile_lookup_bool_default(file, FALSE,
3314
"player%d.dc%d.unhappy", plrno, i);
3316
/* Initialise list of improvements */
3317
BV_CLR_ALL(pdcity->improvements);
3319
p = secfile_lookup_str_default(file, NULL,
3320
"player%d.dc%d.improvements", plrno, i);
3324
for (k = 0; k < improvement_order_size && p[k]; k++) {
3326
struct impr_type *pimprove =
3327
find_improvement_by_rule_name(improvement_order[k]);
3329
BV_SET(pdcity->improvements, improvement_index(pimprove));
3334
sz_strlcpy(pdcity->name, secfile_lookup_str(file, "player%d.dc%d.name", plrno, i));
3336
change_playertile_site(map_get_player_tile(pdcity->location, plr),
3338
identity_number_reserve(pdcity->identity);
2748
/* This shouldn't be neccesary if the savegame was consistent, but there
2749
is a bug in some pre-1.11 savegames. Anyway, it can't hurt */
3341
/* Repair inconsistent player maps. There was a bug in some pre-1.11
3342
savegames, and possibly other versions, and border support changed
3343
from time to time. Anyway, it shouldn't hurt. */
2750
3344
whole_map_iterate(ptile) {
2751
3345
if (map_is_known_and_seen(ptile, plr, V_MAIN)) {
3346
struct city *pcity = tile_city(ptile);
2752
3348
update_player_tile_knowledge(plr, ptile);
2753
3349
reality_check_city(plr, ptile);
2754
if (tile_get_city(ptile)) {
2755
update_dumb_city(plr, tile_get_city(ptile));
3351
if (NULL != pcity) {
3352
update_dumb_city(plr, pcity);
2758
3355
} whole_map_iterate_end;
2761
3357
/* We have an old savegame or fog of war was turned off; the
2762
3358
players private knowledge is set to be what he could see
2763
3359
without fog of war */
2764
3360
whole_map_iterate(ptile) {
2765
3361
if (map_is_known(ptile, plr)) {
2766
struct city *pcity = tile_get_city(ptile);
3362
struct city *pcity = tile_city(ptile);
2767
3364
update_player_tile_last_seen(plr, ptile);
2768
3365
update_player_tile_knowledge(plr, ptile);
3367
if (NULL != pcity) {
2770
3368
update_dumb_city(plr, pcity);
2772
3371
} whole_map_iterate_end;
2776
/***************************************************************
3375
/****************************************************************************
2778
***************************************************************/
2779
static void player_save(struct player *plr, int plrno,
2780
struct section_file *file)
3377
****************************************************************************/
3378
static void player_save_main(struct player *plr, int plrno,
3379
struct section_file *file)
2783
3382
char invs[A_LAST+1];
2784
3383
struct player_spaceship *ship = &plr->spaceship;
2785
3384
struct ai_data *ai = ai_data_get(plr);
2786
int wlist_max_length = 0;
2788
3386
secfile_insert_str(file, player_name(plr), "player%d.name", plrno);
2789
3387
secfile_insert_str(file, plr->username, "player%d.username", plrno);
3135
3758
secfile_insert_int(file, pcity->shield_stock, "player%d.c%d.shield_stock",
3761
secfile_insert_int(file, pcity->airlift, "player%d.c%d.airlift",
3763
secfile_insert_bool(file, pcity->was_happy, "player%d.c%d.was_happy",
3765
secfile_insert_int(file, pcity->turn_plague, "player%d.c%d.turn_plague",
3768
secfile_insert_int(file, pcity->anarchy, "player%d.c%d.anarchy", plrno,i);
3769
secfile_insert_int(file, pcity->rapture, "player%d.c%d.rapture", plrno,i);
3770
secfile_insert_int(file, pcity->steal, "player%d.c%d.steal", plrno, i);
3772
secfile_insert_int(file, pcity->turn_founded,
3773
"player%d.c%d.turn_founded", plrno, i);
3774
if (pcity->turn_founded == game.info.turn) {
3775
j = -1; /* undocumented hack */
3777
assert(pcity->did_buy == TRUE || pcity->did_buy == FALSE);
3778
j = pcity->did_buy ? 1 : 0;
3780
secfile_insert_int(file, j, "player%d.c%d.did_buy", plrno, i);
3781
secfile_insert_bool(file, pcity->did_sell, "player%d.c%d.did_sell", plrno,i);
3137
3782
secfile_insert_int(file, pcity->turn_last_built,
3138
3783
"player%d.c%d.turn_last_built", plrno, i);
3139
secfile_insert_bool(file, pcity->changed_from.is_unit,
3140
"player%d.c%d.changed_from_is_unit", plrno, i);
3141
if (pcity->changed_from.is_unit) {
3142
struct unit_type *punittype = utype_by_number(pcity->changed_from.value);
3144
secfile_insert_int(file, old_unit_type_id(punittype),
3145
"player%d.c%d.changed_from_id", plrno, i);
3146
secfile_insert_str(file, utype_rule_name(punittype),
3147
"player%d.c%d.changed_from_name", plrno, i);
3149
secfile_insert_int(file, old_impr_type_id(pcity->changed_from.value),
3150
"player%d.c%d.changed_from_id", plrno, i);
3151
secfile_insert_str(file, improvement_rule_name(
3152
pcity->changed_from.value),
3153
"player%d.c%d.changed_from_name", plrno, i);
3785
/* for visual debugging, variable length strings together here */
3786
secfile_insert_str(file, city_name(pcity), "player%d.c%d.name", plrno, i);
3788
/* before 2.2.0 unit production was indicated by flag. */
3789
secfile_insert_str(file, universal_type_rule_name(&pcity->production),
3790
"player%d.c%d.currently_building_kind", plrno, i);
3791
secfile_insert_str(file, universal_rule_name(&pcity->production),
3792
"player%d.c%d.currently_building_name", plrno, i);
3794
/* before 2.2.0 unit production was indicated by flag. */
3795
secfile_insert_str(file, universal_type_rule_name(&pcity->changed_from),
3796
"player%d.c%d.changed_from_kind", plrno, i);
3797
secfile_insert_str(file, universal_rule_name(&pcity->changed_from),
3798
"player%d.c%d.changed_from_name", plrno, i);
3156
3800
secfile_insert_int(file, pcity->before_change_shields,
3157
3801
"player%d.c%d.before_change_shields", plrno, i);
3802
secfile_insert_int(file, pcity->caravan_shields,
3803
"player%d.c%d.caravan_shields", plrno, i);
3158
3804
secfile_insert_int(file, pcity->disbanded_shields,
3159
3805
"player%d.c%d.disbanded_shields", plrno, i);
3160
secfile_insert_int(file, pcity->caravan_shields,
3161
"player%d.c%d.caravan_shields", plrno, i);
3162
3806
secfile_insert_int(file, pcity->last_turns_shield_surplus,
3163
3807
"player%d.c%d.last_turns_shield_surplus", plrno, i);
3165
secfile_insert_int(file, pcity->anarchy, "player%d.c%d.anarchy", plrno,i);
3166
secfile_insert_int(file, pcity->rapture, "player%d.c%d.rapture", plrno,i);
3167
secfile_insert_bool(file, pcity->was_happy, "player%d.c%d.was_happy", plrno,i);
3168
if (pcity->turn_founded == game.info.turn) {
3171
assert(pcity->did_buy == TRUE || pcity->did_buy == FALSE);
3172
j = pcity->did_buy ? 1 : 0;
3174
secfile_insert_int(file, j, "player%d.c%d.did_buy", plrno, i);
3175
secfile_insert_int(file, pcity->turn_founded,
3176
"player%d.c%d.turn_founded", plrno, i);
3177
secfile_insert_bool(file, pcity->did_sell, "player%d.c%d.did_sell", plrno,i);
3178
secfile_insert_bool(file, pcity->airlift, "player%d.c%d.airlift", plrno,i);
3180
/* New options format as of Freeciv 2.1. */
3181
for (j = 0; j < CITYO_LAST; j++) {
3182
secfile_insert_bool(file, BV_ISSET(pcity->city_options, j),
3183
"player%d.c%d.option%d", plrno, i, j);
3809
/* The saved city_map[][] uses a specific ordering. The defined
3810
iterators index outward from the center, and cannot be used here.
3811
After 2.2.0, use the (more reliable) main map itself for saving.
3187
3814
for(y=0; y<CITY_MAP_SIZE; y++) {
3188
3815
for(x=0; x<CITY_MAP_SIZE; x++) {
3189
switch (get_worker_city(pcity, x, y)) {
3191
citymap_buf[j++] = '0';
3194
citymap_buf[j++] = '1';
3196
case C_TILE_UNAVAILABLE:
3197
citymap_buf[j++] = '2';
3200
citymap_buf[j++] = '?';
3816
struct tile *ptile = is_valid_city_coords(x, y)
3817
? city_map_to_tile(pcenter, x, y)
3820
if (NULL == ptile) {
3821
citymap_buf[j++] = S_TILE_UNKNOWN;
3822
} else if (tile_worked(ptile) == pcity) {
3823
/* is currently worked, but actually may be unavailable */
3824
citymap_buf[j++] = S_TILE_WORKER;
3825
} else if (city_can_work_tile(pcity, ptile)) {
3826
citymap_buf[j++] = S_TILE_EMPTY;
3828
citymap_buf[j++] = S_TILE_UNAVAILABLE;
3206
3832
citymap_buf[j]='\0';
3207
3833
assert(j < ARRAY_SIZE(citymap_buf));
3208
3834
secfile_insert_str(file, citymap_buf, "player%d.c%d.workers", plrno, i);
3210
secfile_insert_bool(file, pcity->production.is_unit,
3211
"player%d.c%d.is_building_unit", plrno, i);
3212
if (pcity->production.is_unit) {
3213
struct unit_type *punittype = utype_by_number(pcity->production.value);
3214
secfile_insert_int(file, old_unit_type_id(punittype),
3215
"player%d.c%d.currently_building", plrno, i);
3216
secfile_insert_str(file, utype_rule_name(punittype),
3217
"player%d.c%d.currently_building_name", plrno, i);
3219
secfile_insert_int(file, old_impr_type_id(pcity->production.value),
3220
"player%d.c%d.currently_building", plrno, i);
3221
secfile_insert_str(file, improvement_rule_name(
3222
pcity->production.value),
3223
"player%d.c%d.currently_building_name", plrno, i);
3226
/* 1.14 servers depend on improvement order in ruleset. Here we
3227
* are trying to simulate 1.14.1 default order
3229
init_old_improvement_bitvector(impr_buf);
3230
impr_type_iterate(id) {
3231
if (pcity->improvements[id] != I_NONE) {
3232
add_improvement_into_old_bitvector(impr_buf, id);
3234
} impr_type_iterate_end;
3235
assert(strlen(impr_buf) < sizeof(impr_buf));
3236
secfile_insert_str(file, impr_buf, "player%d.c%d.improvements", plrno, i);
3238
/* Save improvement list as bitvector. Note that improvement order
3836
/* Save improvement list as bytevector. Note that improvement order
3239
3837
* is saved in savefile.improvement_order.
3241
impr_type_iterate(id) {
3242
impr_buf[id] = (pcity->improvements[id] != I_NONE) ? '1' : '0';
3243
} impr_type_iterate_end;
3244
impr_buf[game.control.num_impr_types] = '\0';
3839
improvement_iterate(pimprove) {
3840
impr_buf[improvement_index(pimprove)] =
3841
(pcity->built[improvement_index(pimprove)].turn <= I_NEVER)
3843
} improvement_iterate_end;
3844
impr_buf[improvement_count()] = '\0';
3245
3845
assert(strlen(impr_buf) < sizeof(impr_buf));
3246
3846
secfile_insert_str(file, impr_buf,
3247
3847
"player%d.c%d.improvements_new", plrno, i);
3249
3849
worklist_save(file, &pcity->worklist, wlist_max_length,
3250
3850
"player%d.c%d", plrno, i);
3852
/* after 2.1.0 new options format. Old options are lost on upgrade. */
3853
for (j = 0; j < CITYO_LAST; j++) {
3854
secfile_insert_bool(file, BV_ISSET(pcity->city_options, j),
3855
"player%d.c%d.option%d", plrno, i, j);
3252
3858
/* FIXME: remove this when the urgency is properly recalculated. */
3253
secfile_insert_int(file, pcity->ai.urgency,
3859
secfile_insert_int(file, pcity->ai->urgency,
3254
3860
"player%d.c%d.ai.urgency", plrno, i);
3256
3862
/* avoid myrand recalculations on subsequent reload. */
3257
secfile_insert_int(file, pcity->ai.next_recalc,
3863
secfile_insert_int(file, pcity->ai->building_turn,
3258
3864
"player%d.c%d.ai.building_turn", plrno, i);
3865
secfile_insert_int(file, pcity->ai->building_wait,
3866
"player%d.c%d.ai.building_wait", plrno, i);
3260
3868
/* avoid myrand and expensive recalculations on subsequent reload. */
3261
secfile_insert_int(file, pcity->ai.next_founder_want_recalc,
3869
secfile_insert_int(file, pcity->ai->founder_turn,
3262
3870
"player%d.c%d.ai.founder_turn", plrno, i);
3263
secfile_insert_int(file, pcity->ai.founder_want,
3871
secfile_insert_int(file, pcity->ai->founder_want,
3264
3872
"player%d.c%d.ai.founder_want", plrno, i);
3265
secfile_insert_bool(file, pcity->ai.founder_boat,
3873
secfile_insert_bool(file, pcity->ai->founder_boat,
3266
3874
"player%d.c%d.ai.founder_boat", plrno, i);
3268
city_list_iterate_end;
3270
/********** Put the players private map **********/
3271
/* Otherwise the player can see all, and there's no reason to save the private map. */
3272
if (game.info.fogofwar
3273
&& game.save_options.save_private_map) {
3275
/* put the terrain type */
3276
SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_t%03d", plrno,
3277
terrain2char(map_get_player_tile
3278
(ptile, plr)->terrain));
3279
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_res%03d", plrno,
3280
resource_to_identifier(map_get_player_tile(ptile, plr)->resource));
3282
special_halfbyte_iterate(j) {
3283
char buf[32]; /* enough for sprintf() below */
3284
enum tile_special_type mod[4];
3287
for (l = 0; l < 4; l++) {
3288
mod[l] = MIN(4 * j + l, S_LAST);
3875
} city_list_iterate_end;
3878
/****************************************************************************
3879
Save the private vision map for fog of war
3880
****************************************************************************/
3881
static void player_save_vision(struct player *plr, int plrno,
3882
struct section_file *file)
3884
char impr_buf[MAX_NUM_ITEMS + 1];
3887
if (!game.info.fogofwar || !game.server.save_options.save_private_map) {
3888
/* The player can see all, there's no reason to save the private map. */
3892
/* put the terrain type */
3893
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_t%03d", plrno,
3894
terrain2char(map_get_player_tile
3895
(ptile, plr)->terrain));
3896
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_res%03d", plrno,
3897
resource_to_identifier(map_get_player_tile(ptile, plr)->resource));
3899
if (game.server.foggedborders) {
3900
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_owner%03d", plrno,
3901
player_to_identier(map_get_player_tile(ptile, plr)->owner));
3904
special_halfbyte_iterate(j) {
3905
char buf[32]; /* enough for sprintf() below */
3906
enum tile_special_type mod[4];
3909
for (l = 0; l < 4; l++) {
3910
mod[l] = MIN(4 * j + l, S_LAST);
3912
sprintf (buf, "player%%d.map_spe%02d_%%03d", j);
3913
SAVE_PLAYER_MAP_DATA(ptile, file, buf, plrno,
3914
get_savegame_special(map_get_player_tile(ptile, plr)->special, mod));
3915
} special_halfbyte_iterate_end;
3917
bases_halfbyte_iterate(j, game.control.num_base_types) {
3918
char buf[32]; /* enough for sprintf() below */
3922
for (l = 0; l < 4; l++) {
3923
if (4 * j + 1 > game.control.num_base_types) {
3290
sprintf (buf, "player%%d.map_spe%02d_%%03d", j);
3291
SAVE_PLAYER_MAP_DATA(ptile, file, buf, plrno,
3292
get_savegame_special(map_get_player_tile(ptile, plr)->special, mod));
3293
} special_halfbyte_iterate_end;
3295
/* put 4-bit segments of 16-bit "updated" field */
3296
SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_ua%03d", plrno,
3297
bin2ascii_hex(map_get_player_tile
3298
(ptile, plr)->last_updated, 0));
3299
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_ub%03d", plrno,
3300
bin2ascii_hex(map_get_player_tile
3301
(ptile, plr)->last_updated, 1));
3302
SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_uc%03d", plrno,
3303
bin2ascii_hex(map_get_player_tile
3304
(ptile, plr)->last_updated, 2));
3305
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_ud%03d", plrno,
3306
bin2ascii_hex(map_get_player_tile
3307
(ptile, plr)->last_updated, 3));
3310
struct vision_base *pdcity;
3311
char impr_buf[MAX_NUM_ITEMS + 1];
3315
whole_map_iterate(ptile) {
3316
if (NULL != (pdcity = map_get_player_base(ptile, plr))
3317
&& VISION_BASE_RUIN < pdcity->identity) {
3318
secfile_insert_int(file, pdcity->identity, "player%d.dc%d.id",
3320
secfile_insert_int(file, ptile->nat_x,
3321
"player%d.dc%d.x", plrno, i);
3322
secfile_insert_int(file, ptile->nat_y,
3323
"player%d.dc%d.y", plrno, i);
3324
secfile_insert_str(file, pdcity->name, "player%d.dc%d.name",
3326
secfile_insert_int(file, pdcity->size, "player%d.dc%d.size",
3328
secfile_insert_bool(file, FALSE,
3329
"player%d.dc%d.has_walls", plrno, i);
3330
secfile_insert_bool(file, pdcity->occupied,
3331
"player%d.dc%d.occupied", plrno, i);
3332
secfile_insert_bool(file, pdcity->walls,
3333
"player%d.dc%d.walls", plrno, i);
3334
secfile_insert_bool(file, pdcity->happy,
3335
"player%d.dc%d.happy", plrno, i);
3336
secfile_insert_bool(file, pdcity->unhappy,
3337
"player%d.dc%d.unhappy", plrno, i);
3338
secfile_insert_int(file, vision_owner(pdcity)->player_no,
3339
"player%d.dc%d.owner", plrno, i);
3341
/* Save improvement list as bitvector. Note that improvement order
3342
* is saved in savefile.improvement_order.
3344
impr_type_iterate(id) {
3345
impr_buf[id] = BV_ISSET(pdcity->improvements, id) ? '1' : '0';
3346
} impr_type_iterate_end;
3347
impr_buf[game.control.num_impr_types] = '\0';
3348
assert(strlen(impr_buf) < sizeof(impr_buf));
3349
secfile_insert_str(file, impr_buf,
3350
"player%d.dc%d.improvements", plrno, i);
3354
} whole_map_iterate_end;
3356
secfile_insert_int(file, i, "player%d.total_ncities", plrno);
3929
sprintf (buf, "player%%d.map_b%02d_%%03d", j);
3930
SAVE_PLAYER_MAP_DATA(ptile, file, buf, plrno,
3931
get_savegame_bases(map_get_player_tile(ptile, plr)->bases, mod));
3932
} bases_halfbyte_iterate_end;
3934
/* put 4-bit segments of 16-bit "updated" field */
3935
SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_ua%03d", plrno,
3936
bin2ascii_hex(map_get_player_tile
3937
(ptile, plr)->last_updated, 0));
3938
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_ub%03d", plrno,
3939
bin2ascii_hex(map_get_player_tile
3940
(ptile, plr)->last_updated, 1));
3941
SAVE_PLAYER_MAP_DATA(ptile, file,"player%d.map_uc%03d", plrno,
3942
bin2ascii_hex(map_get_player_tile
3943
(ptile, plr)->last_updated, 2));
3944
SAVE_PLAYER_MAP_DATA(ptile, file, "player%d.map_ud%03d", plrno,
3945
bin2ascii_hex(map_get_player_tile
3946
(ptile, plr)->last_updated, 3));
3948
whole_map_iterate(ptile) {
3949
struct vision_site *pdcity = map_get_player_city(ptile, plr);
3951
if (NULL != pdcity && plr != vision_owner(pdcity)) {
3952
secfile_insert_int(file, ptile->nat_y,
3953
"player%d.dc%d.y", plrno, i);
3954
secfile_insert_int(file, ptile->nat_x,
3955
"player%d.dc%d.x", plrno, i);
3956
secfile_insert_int(file, pdcity->identity,
3957
"player%d.dc%d.id", plrno, i);
3958
secfile_insert_int(file, player_number(vision_owner(pdcity)),
3959
"player%d.dc%d.owner", plrno, i);
3961
secfile_insert_int(file, pdcity->size,
3962
"player%d.dc%d.size", plrno, i);
3963
secfile_insert_bool(file, pdcity->occupied,
3964
"player%d.dc%d.occupied", plrno, i);
3965
secfile_insert_bool(file, pdcity->walls,
3966
"player%d.dc%d.walls", plrno, i);
3967
secfile_insert_bool(file, pdcity->happy,
3968
"player%d.dc%d.happy", plrno, i);
3969
secfile_insert_bool(file, pdcity->unhappy,
3970
"player%d.dc%d.unhappy", plrno, i);
3972
/* Save improvement list as bitvector. Note that improvement order
3973
* is saved in savefile.improvement_order.
3975
assert(improvement_count() < sizeof(impr_buf));
3976
improvement_iterate(pimprove) {
3977
impr_buf[improvement_index(pimprove)] =
3978
BV_ISSET(pdcity->improvements, improvement_index(pimprove))
3980
} improvement_iterate_end;
3981
impr_buf[improvement_count()] = '\0';
3982
secfile_insert_str(file, impr_buf,
3983
"player%d.dc%d.improvements", plrno, i);
3985
secfile_insert_str(file, pdcity->name,
3986
"player%d.dc%d.name", plrno, i);
3990
} whole_map_iterate_end;
3992
secfile_insert_int(file, i, "player%d.total_ncities", plrno);
3995
/****************************************************************************
3997
****************************************************************************/
3998
static void player_save_attributes(struct player *plr, int plrno,
3999
struct section_file *file)
3359
4001
/* This is a big heap of opaque data from the client. Although the binary
3360
4002
* format is not user editable, keep the lines short enough for debugging,
3361
4003
* and hope that data compression will keep the file a reasonable size.
4295
5174
/* Save specials order */
4296
5175
modname = fc_calloc(S_LAST, sizeof(*modname));
4297
5177
tile_special_type_iterate(j) {
4298
5178
modname[j] = special_rule_name(j);
4299
5179
} tile_special_type_iterate_end;
5181
/* Obsoleted entries */
5182
modname[S_OLD_FORTRESS] = "Obsolete";
5183
modname[S_OLD_AIRBASE] = "Obsolete";
4300
5185
secfile_insert_str_vec(file, modname, S_LAST,
4301
5186
"savefile.specials");
5190
secfile_insert_int(file, game.control.num_base_types, "savefile.num_bases");
5191
if (game.control.num_base_types > 0) {
5192
const char **modname;
5195
/* Save bases order */
5196
modname = fc_calloc(game.control.num_base_types, sizeof(*modname));
5198
base_type_iterate(pbase) {
5199
modname[i++] = base_rule_name(pbase);
5200
} base_type_iterate_end;
5202
secfile_insert_str_vec(file, modname, game.control.num_base_types,
5210
secfile_insert_str(file, game.scenario.name, "scenario.name");
5211
secfile_insert_str(file, game.scenario.description,
5212
"scenario.description");
5213
secfile_insert_bool(file, game.scenario.players, "scenario.save_players");
5217
version = MAJOR_VERSION *10000 + MINOR_VERSION *100 + PATCH_VERSION;
5218
secfile_insert_int(file, version, "game.version");
5220
/* Game state: once the game is no longer a new game (ie, has been
5221
* started the first time), it should always be considered a running
5222
* game for savegame purposes:
5224
if (scenario && !game.scenario.players) {
5225
srv_state = S_S_INITIAL;
5227
srv_state = game.info.is_new_game ? server_state() : S_S_RUNNING;
5230
/* new in 2.2: save server state as string; see srv_main.h */
5231
secfile_insert_str(file, server_states_name(srv_state),
5232
"game.server_state");
5234
secfile_insert_str(file, get_meta_patches_string(), "game.metapatches");
5235
secfile_insert_bool(file, game.server.meta_info.user_message_set,
5236
"game.user_metamessage");
5237
user_message = get_user_meta_message_string();
5238
if (user_message != NULL) {
5239
secfile_insert_str(file, user_message, "game.metamessage");
5241
secfile_insert_str(file, meta_addr_port(), "game.metaserver");
5242
secfile_insert_str(file, srvarg.serverid, "game.serverid");
4306
5244
secfile_insert_int(file, game.info.gold, "game.gold");
4307
5245
secfile_insert_int(file, game.info.tech, "game.tech");
4308
5246
secfile_insert_int(file, game.info.skill_level, "game.skill_level");
4309
5247
secfile_insert_int(file, game.info.timeout, "game.timeout");
4310
secfile_insert_int(file, game.timeoutint, "game.timeoutint");
4311
secfile_insert_int(file, game.timeoutintinc, "game.timeoutintinc");
4312
secfile_insert_int(file, game.timeoutinc, "game.timeoutinc");
4313
secfile_insert_int(file, game.timeoutincmult, "game.timeoutincmult");
4314
secfile_insert_int(file, game.timeoutcounter, "game.timeoutcounter");
4315
secfile_insert_int(file, game.timeoutaddenemymove,
4316
"game.info.timeoutaddenemymove");
4317
secfile_insert_int(file, game.info.end_year, "game.end_year");
5248
secfile_insert_int(file, game.server.timeoutint, "game.timeoutint");
5249
secfile_insert_int(file, game.server.timeoutintinc, "game.timeoutintinc");
5250
secfile_insert_int(file, game.server.timeoutinc, "game.timeoutinc");
5251
secfile_insert_int(file, game.server.timeoutincmult, "game.timeoutincmult");
5252
secfile_insert_int(file, game.server.timeoutcounter, "game.timeoutcounter");
5254
secfile_insert_int(file, game.info.end_turn, "game.end_turn");
4318
5255
secfile_insert_int(file, game.info.year, "game.year");
4319
5256
secfile_insert_int(file, game.info.turn, "game.turn");
4320
secfile_insert_bool(file, game.info.simultaneous_phases,
4321
"game.simultaneous_phases_now");
4322
secfile_insert_bool(file, game.simultaneous_phases_stored,
4323
"game.simultaneous_phases_stored");
5257
secfile_insert_bool(file, game.info.year_0_hack, "game.year_0_hack");
5258
secfile_insert_int(file, game.info.phase_mode,
5260
secfile_insert_int(file, game.server.phase_mode_stored,
5261
"game.phase_mode_stored");
4324
5262
secfile_insert_int(file, game.info.min_players, "game.min_players");
4325
5263
secfile_insert_int(file, game.info.max_players, "game.max_players");
4326
secfile_insert_int(file, game.info.nplayers, "game.nplayers");
4327
5264
secfile_insert_int(file, game.info.heating, "game.heating");
4328
5265
secfile_insert_int(file, game.info.globalwarming, "game.globalwarming");
4329
5266
secfile_insert_int(file, game.info.warminglevel, "game.warminglevel");
4345
5281
secfile_insert_int(file, game.info.foodbox, "game.box_food");
4346
5282
secfile_insert_int(file, game.info.shieldbox, "game.box_shield");
4347
5283
secfile_insert_int(file, game.info.sciencebox, "game.box_science");
4349
/* These values are for compatibility with 2.0 and previous servers. */
4350
secfile_insert_int(file, game.info.sciencebox / 5, "game.researchcost");
4351
secfile_insert_int(file, game.info.foodbox / 10, "game.foodbox");
4353
5285
secfile_insert_int(file, game.info.techpenalty, "game.techpenalty");
4354
5286
secfile_insert_int(file, game.info.razechance, "game.razechance");
4356
5288
/* Write civstyle for compatibility with old servers */
4357
5289
secfile_insert_int(file, 2, "game.civstyle");
4358
5290
secfile_insert_int(file, game.info.save_nturns, "game.save_nturns");
4359
secfile_insert_str(file, game.save_name, "game.save_name");
5291
secfile_insert_str(file, game.server.save_name, "game.save_name");
4360
5292
secfile_insert_int(file, game.info.save_compress_level,
4361
5293
"game.save_compress_level");
5294
secfile_insert_int(file, game.info.save_compress_type,
5295
"game.save_compress_type");
4362
5296
secfile_insert_int(file, game.info.aifill, "game.aifill");
4363
secfile_insert_bool(file, game.scorelog, "game.scorelog");
4364
secfile_insert_int(file, game.scoreturn, "game.scoreturn");
4365
secfile_insert_str(file, game.id, "game.id");
5297
secfile_insert_bool(file, game.server.scorelog, "game.scorelog");
5298
secfile_insert_int(file, game.server.scoreturn, "game.scoreturn");
5299
secfile_insert_str(file, server.game_identifier, "game.id");
4366
5301
secfile_insert_bool(file, game.info.fogofwar, "game.fogofwar");
5302
secfile_insert_bool(file, game.server.foggedborders, "game.foggedborders");
4367
5303
secfile_insert_bool(file, game.info.spacerace, "game.spacerace");
5304
secfile_insert_bool(file, game.info.endspaceship, "game.endspaceship");
4368
5305
secfile_insert_bool(file, game.info.auto_ai_toggle, "game.auto_ai_toggle");
4369
5306
secfile_insert_int(file, game.info.diplchance, "game.diplchance");
4370
5307
secfile_insert_int(file, game.info.aqueductloss, "game.aqueductloss");
4371
5308
secfile_insert_int(file, game.info.killcitizen, "game.killcitizen");
5309
secfile_insert_bool(file, game.info.savepalace, "game.savepalace");
4372
5310
secfile_insert_bool(file, game.info.turnblock, "game.turnblock");
4373
secfile_insert_bool(file, game.info.savepalace, "game.savepalace");
4374
5311
secfile_insert_bool(file, game.info.fixedlength, "game.fixedlength");
4375
5312
secfile_insert_int(file, game.info.barbarianrate, "game.barbarians");
4376
5313
secfile_insert_int(file, game.info.onsetbarbarian, "game.onsetbarbs");
4377
5314
secfile_insert_int(file, game.info.revolution_length, "game.revolen");
4378
5315
secfile_insert_int(file, game.info.occupychance, "game.occupychance");
4379
5316
secfile_insert_bool(file, game.info.autoattack, "game.autoattack");
4380
secfile_insert_str(file, game.demography, "game.demography");
4381
secfile_insert_str(file, game.allow_take, "game.allow_take");
5317
secfile_insert_str(file, game.server.demography, "game.demography");
5318
secfile_insert_str(file, game.server.allow_take, "game.allow_take");
4382
5319
secfile_insert_int(file, game.info.borders, "game.borders");
4383
5320
secfile_insert_bool(file, game.info.happyborders, "game.happyborders");
4384
5321
secfile_insert_int(file, game.info.diplomacy, "game.diplomacy");
4385
5322
secfile_insert_int(file, game.info.allowed_city_names, "game.allowed_city_names");
4387
/* old (1.14.1) servers need to have these server variables. The values
4388
* don't matter, though. */
4389
secfile_insert_int(file, 2, "game.settlers");
4390
secfile_insert_int(file, 1, "game.explorer");
4391
secfile_insert_int(file, 30, "map.mountains");
4392
secfile_insert_int(file, 35, "map.grass");
4393
secfile_insert_int(file, 5, "map.swampsize");
4394
secfile_insert_int(file, 5, "map.deserts");
4395
secfile_insert_int(file, 5, "map.riverlength");
4396
secfile_insert_int(file, 20, "map.forestsize");
5323
secfile_insert_bool(file, game.info.migration,
5325
secfile_insert_int(file, game.info.mgr_turninterval,
5326
"game.mgr_turninterval");
5327
secfile_insert_bool(file, game.info.mgr_foodneeded,
5328
"game.mgr_foodneeded");
5329
secfile_insert_int(file, game.info.mgr_distance,
5330
"game.mgr_distance");
5331
secfile_insert_int(file, game.info.mgr_nationchance,
5332
"game.mgr_nationchance");
5333
secfile_insert_int(file, game.info.mgr_worldchance,
5334
"game.mgr_worldchance");
5335
secfile_insert_int(file, game.server.event_cache.turns,
5336
"game.event_cache.turns");
5337
secfile_insert_int(file, game.server.event_cache.max_size,
5338
"game.event_cache.max_size");
5339
secfile_insert_bool(file, game.server.event_cache.chat,
5340
"game.event_cache.chat");
5341
secfile_insert_bool(file, game.server.event_cache.info,
5342
"game.event_cache.info");
4399
5345
/* Now always save these, so the server options reflect the
4400
5346
* actual values used at the start of the game.
4401
5347
* The first two used to be saved as "map.xsize" and "map.ysize"
4402
5348
* when S_S_INITIAL, but I'm standardizing on width,height --dwp
4404
5350
secfile_insert_int(file, map.topology_id, "map.topology_id");
4405
secfile_insert_int(file, map.size, "map.size");
5351
secfile_insert_int(file, map.server.size, "map.size");
4406
5352
secfile_insert_int(file, map.xsize, "map.width");
4407
5353
secfile_insert_int(file, map.ysize, "map.height");
4408
5354
secfile_insert_str(file, game.info.start_units, "game.start_units");
4409
5355
secfile_insert_int(file, game.info.dispersion, "game.dispersion");
4410
secfile_insert_int(file, map.seed, "map.seed");
4411
secfile_insert_int(file, map.landpercent, "map.landpercent");
4412
secfile_insert_int(file, map.riches, "map.riches");
4413
secfile_insert_int(file, map.wetness, "map.wetness");
4414
secfile_insert_int(file, map.steepness, "map.steepness");
4415
secfile_insert_int(file, map.huts, "map.huts");
4416
secfile_insert_int(file, map.generator, "map.generator");
4417
secfile_insert_int(file, map.startpos, "map.startpos");
4418
secfile_insert_bool(file, map.have_huts, "map.have_huts");
4419
secfile_insert_int(file, map.temperature, "map.temperature");
4420
secfile_insert_bool(file, map.alltemperate, "map.alltemperate");
4421
secfile_insert_bool(file, map.tinyisles, "map.tinyisles");
4422
secfile_insert_bool(file, map.separatepoles, "map.separatepoles");
5356
secfile_insert_int(file, map.server.seed, "map.seed");
5357
secfile_insert_int(file, map.server.landpercent, "map.landpercent");
5358
secfile_insert_int(file, map.server.riches, "map.riches");
5359
secfile_insert_int(file, map.server.wetness, "map.wetness");
5360
secfile_insert_int(file, map.server.steepness, "map.steepness");
5361
secfile_insert_int(file, map.server.huts, "map.huts");
5362
secfile_insert_int(file, scenario ? 0 : map.server.generator,
5364
secfile_insert_int(file, map.server.startpos, "map.startpos");
5365
secfile_insert_bool(file, map.server.have_huts, "map.have_huts");
5366
secfile_insert_int(file, map.server.temperature, "map.temperature");
5367
secfile_insert_bool(file, map.server.alltemperate, "map.alltemperate");
5368
secfile_insert_bool(file, map.server.tinyisles, "map.tinyisles");
5369
secfile_insert_bool(file, map.server.separatepoles, "map.separatepoles");
4425
secfile_insert_int(file, game.seed, "game.randseed");
5372
secfile_insert_int(file, game.server.seed, "game.randseed");
4427
if (myrand_is_init() && game.save_options.save_random) {
5374
if (myrand_is_init() && game.server.save_options.save_random) {
4428
5375
RANDOM_STATE rstate = get_myrand_state();
4429
5376
secfile_insert_int(file, 1, "game.save_random");
4430
5377
assert(rstate.is_init);