[Freeciv-Dev] (PR#9456) Improvements' lists in savegames
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: |
undisclosed-recipients: ; |
Subject: |
[Freeciv-Dev] (PR#9456) Improvements' lists in savegames |
From: |
"Mateusz Stefek" <mstefek@xxxxxxxxx> |
Date: |
Wed, 21 Jul 2004 00:17:00 -0700 |
Reply-to: |
rt@xxxxxxxxxxx |
<URL: http://rt.freeciv.org/Ticket/Display.html?id=9456 >
With this patch savegames(city.improvements and destroyed_wonders)
don't depend on improvement order in ruleset.
I changed my mind and implemented it with secfile_insert_str_vec().
I hope it's acceptable that secfile_insert_str_vec() implementation is
a little tricky, this is really harmless.
--
mateusz
Tylko w freeciv: h
Tylko w freeciv/server: k.gz
diff -ur -Xdiff_ignore freeorig/server/savegame.c freeciv/server/savegame.c
--- freeorig/server/savegame.c 2004-07-19 09:34:46.000000000 +0200
+++ freeciv/server/savegame.c 2004-07-20 15:42:09.000000000 +0200
@@ -176,7 +176,7 @@
#define SAVEFILE_OPTIONS "startoptions spacerace2 rulesets" \
" diplchance_percent worklists2 map_editor known32fix turn " \
"attributes watchtower rulesetdir client_worklists orders " \
-"startunits turn_last_built"
+"startunits turn_last_built improvement_order"
static const char hex_chars[] = "0123456789abcdef";
static const char terrain_chars[] = "adfghjm prstu";
@@ -732,6 +732,36 @@
return old_impr_types[id];
}
+/*****************************************************************
+ Insert improvement into old-style bitvector
+ Improvement lists in cities and destroyed_wonders are saved
+ that way. New bitvectors does not depend on ruleset order.
+ However, we want to create savegames which can be read by
+ 1.14.x and earlier servers.
+*****************************************************************/
+static void add_improvement_into_old_bitvector(char* bitvector,
+ Impr_Type_id id)
+{
+ int old_id;
+ old_id = old_impr_type_id(id);
+ if (old_id < 0 || old_id >= ARRAY_SIZE(old_impr_types)) {
+ return;
+ }
+ bitvector[old_id] = '1';
+}
+
+/*************************************************************
+ Fill old-style improvement bitvector with '0' s
+*************************************************************/
+static void init_old_improvement_bitvector(char* bitvector)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(old_impr_types); i++) {
+ bitvector[i] = '0';
+ }
+ bitvector[ARRAY_SIZE(old_impr_types)] = '\0';
+}
+
/***************************************************************
Load the worklist elements specified by path, given the arguments
plrno and wlinx, into the worklist pointed to by pwl.
@@ -1060,7 +1090,9 @@
...
***************************************************************/
static void player_load(struct player *plr, int plrno,
- struct section_file *file)
+ struct section_file *file,
+ char** improvement_order,
+ int improvement_order_size)
{
int i, j, x, y, ncities, c_s;
const char *p;
@@ -1340,7 +1372,7 @@
int nat_y = secfile_lookup_int(file, "player%d.c%d.y", plrno, i);
int map_x, map_y;
const char* name;
- int id;
+ int id, k;
native_to_map_pos(&map_x, &map_y, nat_x, nat_y);
pcity = create_city_virtual(plr, map_x, map_y,
@@ -1524,18 +1556,35 @@
}
}
- p=secfile_lookup_str(file, "player%d.c%d.improvements", plrno, i);
-
/* Initialise list of improvements with City- and Building-wide
equiv_ranges */
improvement_status_init(pcity->improvements,
ARRAY_SIZE(pcity->improvements));
- impr_type_iterate(x) {
- if (*p != '\0' && *p++=='1') {
- city_add_improvement(pcity,x);
+ p = secfile_lookup_str_default(file, NULL, "player%d.c%d.improvements_new",
+ plrno, i);
+ if (!p) {
+ /* old savegames */
+ p = secfile_lookup_str(file, "player%d.c%d.improvements", plrno, i);
+ for (k = 0; *p; k++, p++) {
+ if (*p == '1') {
+ name = old_impr_type_name(k);
+ id = find_improvement_by_name_orig(name);
+ if (id != -1) {
+ city_add_improvement(pcity, id);
+ }
+ }
}
- } impr_type_iterate_end;
+ } else {
+ for (k = 0; *p && k < improvement_order_size; k++, p++) {
+ if (*p == '1') {
+ id = find_improvement_by_name_orig(improvement_order[k]);
+ if (id != -1) {
+ city_add_improvement(pcity, id);
+ }
+ }
+ }
+ }
init_worklist(&pcity->worklist);
if (has_capability("worklists2", savefile_options)) {
@@ -2116,11 +2165,25 @@
"player%d.c%d.currently_building_name", plrno, i);
}
+ /* 1.14 servers depend on improvement order in ruleset. Here we
+ * are trying to simulate 1.14.1 default order
+ */
+ init_old_improvement_bitvector(buf);
+ impr_type_iterate(id) {
+ if (pcity->improvements[id] != I_NONE) {
+ add_improvement_into_old_bitvector(buf, id);
+ }
+ } impr_type_iterate_end;
+ secfile_insert_str(file, buf, "player%d.c%d.improvements", plrno, i);
+
+ /* Save improvement list as bitvector. Note that improvement order
+ * is saved in savefile.improvement_order.
+ */
impr_type_iterate(id) {
buf[id] = (pcity->improvements[id] != I_NONE) ? '1' : '0';
} impr_type_iterate_end;
buf[game.num_impr_types] = '\0';
- secfile_insert_str(file, buf, "player%d.c%d.improvements", plrno, i);
+ secfile_insert_str(file, buf, "player%d.c%d.improvements_new", plrno, i);
worklist_save(file, "player%d.c%d", plrno, i, &pcity->worklist);
@@ -2333,16 +2396,23 @@
***************************************************************/
void game_load(struct section_file *file)
{
- int i;
+ int i, k, id;
enum server_states tmp_server_state;
char *savefile_options;
const char *string;
+ char** improvement_order = NULL;
+ int improvement_order_size = 0;
+ const char* name;
game.version = secfile_lookup_int_default(file, 0, "game.version");
tmp_server_state = (enum server_states)
secfile_lookup_int_default(file, RUN_GAME_STATE, "game.server_state");
savefile_options = secfile_lookup_str(file, "savefile.options");
+ if (has_capability("improvement_order", savefile_options)) {
+ improvement_order = secfile_lookup_str_vec(file, &improvement_order_size,
+ "savefile.improvement_order");
+ }
/* we require at least version 1.9.0 */
if (10900 > game.version) {
@@ -2677,23 +2747,39 @@
if (!game.is_new_game) {
/* destroyed wonders: */
- string = secfile_lookup_str_default(file, "", "game.destroyed_wonders");
- impr_type_iterate(i) {
- if (string[i] == '\0') {
- goto out;
+ string = secfile_lookup_str_default(file, NULL,
+ "game.destroyed_wonders_new");
+ if (!string) {
+ /* old savegames */
+ string = secfile_lookup_str_default(file, "",
+ "game.destroyed_wonders");
+ for (k = 0; *string; k++, string++) {
+ if (*string == '1') {
+ name = old_impr_type_name(k);
+ id = find_improvement_by_name_orig(name);
+ if (id != -1) {
+ game.global_wonders[id] = -1;
+ }
+ }
}
- if (string[i] == '1') {
- game.global_wonders[i] = -1; /* destroyed! */
+ } else {
+ for (k = 0; *string && k < improvement_order_size; k++, string++) {
+ if (*string == '1') {
+ id = find_improvement_by_name_orig(improvement_order[k]);
+ if (id != -1) {
+ game.global_wonders[id] = -1;
+ }
+ }
}
- } impr_type_iterate_end;
- out:
+ }
/* This is done after continents are assigned, but before effects
* are added. */
allot_island_improvs();
for(i=0; i<game.nplayers; i++) {
- player_load(&game.players[i], i, file);
+ player_load(&game.players[i], i, file, improvement_order,
+ improvement_order_size);
}
cities_iterate(pcity) {
@@ -2831,7 +2917,19 @@
}
}
secfile_insert_str(file, options, "savefile.options");
-
+ /* Save improvement order in savegame, so we are not dependent on
+ * ruleset order.
+ * If the game isn't started improvements aren't loaded
+ * so we can not save the order.
+ */
+ if (game.num_impr_types > 0) {
+ const char* buf[game.num_impr_types];
+ impr_type_iterate(id) {
+ buf[id] = get_improvement_name_orig(id);
+ } impr_type_iterate_end;
+ secfile_insert_str_vec(file, buf, game.num_impr_types,
+ "savefile.improvement_order");
+ }
secfile_insert_int(file, game.gold, "game.gold");
secfile_insert_int(file, game.tech, "game.tech");
secfile_insert_int(file, game.skill_level, "game.skill_level");
@@ -2952,17 +3050,31 @@
secfile_insert_bool(file, game.save_options.save_players,
"game.save_players");
if (game.save_options.save_players) {
- /* destroyed wonders: */
- impr_type_iterate(i) {
- if (is_wonder(i) && game.global_wonders[i]!=0
- && !find_city_by_id(game.global_wonders[i])) {
- temp[i] = '1';
+ /* 1.14 servers depend on improvement order in ruleset. Here we
+ * are trying to simulate 1.14.1 default order
+ */
+ init_old_improvement_bitvector(temp);
+ impr_type_iterate(id) {
+ if (is_wonder(id) && game.global_wonders[id]!=0
+ && !find_city_by_id(game.global_wonders[id])) {
+ add_improvement_into_old_bitvector(temp, id);
+ }
+ } impr_type_iterate_end;
+ secfile_insert_str(file, temp, "game.destroyed_wonders");
+
+ /* Save destroyed wonders as bitvector. Note that improvement order
+ * is saved in savefile.improvement_order
+ */
+ impr_type_iterate(id) {
+ if (is_wonder(id) && game.global_wonders[id]!=0
+ && !find_city_by_id(game.global_wonders[id])) {
+ temp[id] = '1';
} else {
- temp[i] = '0';
+ temp[id] = '0';
}
} impr_type_iterate_end;
temp[game.num_impr_types] = '\0';
- secfile_insert_str(file, temp, "game.destroyed_wonders");
+ secfile_insert_str(file, temp, "game.destroyed_wonders_new");
calc_unit_ordering();
diff -ur -Xdiff_ignore freeorig/utility/registry.c freeciv/utility/registry.c
--- freeorig/utility/registry.c 2004-06-26 01:43:01.000000000 +0200
+++ freeciv/utility/registry.c 2004-07-21 08:54:53.000000000 +0200
@@ -174,13 +174,16 @@
#define SPECVEC_TAG astring
#include "specvec.h"
-/* An 'entry' is a single value, either a string or integer;
- * Whether string or int is determined by whether svalue is NULL.
+/* An 'entry' is a string, integer or string vector;
+ * Whether it is string or int or string vector is determined by whether
+ * svalue/vec_values is NULL.
*/
struct entry {
char *name; /* name, not including section prefix */
int ivalue; /* value if integer */
char *svalue; /* value if string (in sbuffer) */
+ char **vec_values; /* string vector values */
+ int dim; /* vector's size */
int used; /* number of times entry looked up */
char *comment; /* comment, may be NULL */
};
@@ -634,6 +637,7 @@
struct genlist_link *ent_iter, *save_iter, *col_iter;
struct entry *pentry, *col_pentry;
+ int i;
if (!fs)
return FALSE;
@@ -745,11 +749,19 @@
if(!pentry) break;
}
if(!pentry) break;
-
- if(pentry->svalue)
+
+ if (pentry->vec_values) {
+ fz_fprintf(fs, "%s=\"%s\"", pentry->name,
+ moutstr(pentry->vec_values[0]));
+ for (i = 1; i < pentry->dim; i++) {
+ fz_fprintf(fs, ", \"%s\"", moutstr(pentry->vec_values[i]));
+ }
+ } else if (pentry->svalue) {
fz_fprintf(fs, "%s=\"%s\"", pentry->name, moutstr(pentry->svalue));
- else
+ } else {
fz_fprintf(fs, "%s=%d", pentry->name, pentry->ivalue);
+ }
+
if (pentry->comment) {
fz_fprintf(fs, " # %s\n", pentry->comment);
} else {
@@ -852,6 +864,8 @@
pentry->ivalue=val;
pentry->svalue = NULL;
+ pentry->vec_values = NULL;
+ pentry->dim = 0;
pentry->comment = NULL;
}
@@ -874,6 +888,8 @@
pentry->ivalue = val;
pentry->svalue = NULL;
+ pentry->vec_values = NULL;
+ pentry->dim = 0;
pentry->comment = sbuf_strdup(my_section_file->sb, comment);
}
@@ -901,6 +917,8 @@
pentry->ivalue = val ? 1 : 0;
pentry->svalue = NULL;
+ pentry->vec_values = NULL;
+ pentry->dim = 0;
pentry->comment = NULL;
}
@@ -920,6 +938,8 @@
pentry = section_file_insert_internal(my_section_file, buf);
pentry->svalue = sbuf_strdup(my_section_file->sb, sval);
+ pentry->vec_values = NULL;
+ pentry->dim = 0;
pentry->comment = NULL;
}
@@ -940,10 +960,46 @@
pentry = section_file_insert_internal(my_section_file, buf);
pentry->svalue = sbuf_strdup(my_section_file->sb, sval);
+ pentry->vec_values = NULL;
+ pentry->dim = 0;
pentry->comment = sbuf_strdup(my_section_file->sb, comment);
}
/**************************************************************************
+ Insert string vector into section_file. It will be writen out as:
+ name = "value1", "value2", "value3"
+ This function is little tricky, because values inserted here can't
+ be recovered by secfile_lookup_str_vec. Luckily we never use section_file
+ for both reading and writing.
+**************************************************************************/
+void secfile_insert_str_vec(struct section_file *my_section_file,
+ const char **values, int dim,
+ const char *path, ...)
+{
+ struct entry *pentry;
+ char buf[MAX_LEN_BUFFER];
+ int i;
+ va_list ap;
+
+ va_start(ap, path);
+ my_vsnprintf(buf, sizeof(buf), path, ap);
+ va_end(ap);
+
+ assert(dim > 0);
+
+ pentry = section_file_insert_internal(my_section_file, buf);
+ pentry->dim = dim;
+ pentry->vec_values = sbuf_malloc(my_section_file->sb,
+ sizeof(char*) * dim);
+ for (i = 0; i < dim; i++) {
+ pentry->vec_values[i] = sbuf_strdup(my_section_file->sb, values[i]);
+ }
+
+ pentry->svalue = NULL;
+ pentry->comment = NULL;
+}
+
+/**************************************************************************
...
**************************************************************************/
int secfile_lookup_int(struct section_file *my_section_file,
diff -ur -Xdiff_ignore freeorig/utility/registry.h freeciv/utility/registry.h
--- freeorig/utility/registry.h 2004-04-16 19:08:27.000000000 +0200
+++ freeciv/utility/registry.h 2004-07-17 11:40:29.000000000 +0200
@@ -60,7 +60,10 @@
char *sval, const char *const comment,
const char *path, ...)
fc__attribute((format (printf, 4, 5)));
-
+void secfile_insert_str_vec(struct section_file *my_section_file,
+ const char **values, int dim,
+ const char *path, ...)
+ fc__attribute((format (printf, 4, 5)));
bool section_file_lookup(struct section_file *my_section_file,
const char *path, ...)
fc__attribute((format (printf, 2, 3)));
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#9456) Improvements' lists in savegames,
Mateusz Stefek <=
|
|