From e6eb53c86430d5ac123051800540941e319794a1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 19 Aug 2015 19:43:47 +0200 Subject: [PATCH 1/5] save the faction.max_spelllevel in the data file, do not recalculate it each time. when recalculating it, include spellbook to determine max-level (dead mages may have pushed the level up). --- src/buildno.h | 2 +- src/kernel/save.c | 49 +++++++++++++++++++++++++++++++------------- src/kernel/version.h | 3 ++- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/buildno.h b/src/buildno.h index a8118b327..a0d2bfde8 100644 --- a/src/buildno.h +++ b/src/buildno.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 5 -#define VERSION_BUILD 4 +#define VERSION_BUILD 5 diff --git a/src/kernel/save.c b/src/kernel/save.c index 114126b0c..9f6021b65 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1165,6 +1165,9 @@ faction *readfaction(struct gamedata * data) } READ_INT(data->store, &f->subscription); + if (data->version >= SPELL_LEVEL_VERSION) { + READ_INT(data->store, &f->max_spelllevel); + } if (alliances || data->version >= OWNER_2_VERSION) { int allianceid; READ_INT(data->store, &allianceid); @@ -1294,6 +1297,9 @@ void writefaction(struct gamedata *data, const faction * f) write_faction_reference(f, data->store); WRITE_INT(data->store, f->subscription); +#if RELEASE_VERSION >= SPELL_LEVEL_VERSION + WRITE_INT(data->store, f->max_spelllevel); +#endif if (f->alliance) { WRITE_INT(data->store, f->alliance->id); if (f->alliance->flags & ALF_NON_ALLIED) { @@ -1348,6 +1354,14 @@ void writefaction(struct gamedata *data, const faction * f) write_spellbook(f->spellbook, data->store); } +static int cb_sb_maxlevel(spellbook_entry *sbe, void *cbdata) { + faction *f = (faction *)cbdata; + if (sbe->level > f->max_spelllevel) { + f->max_spelllevel = sbe->level; + } + return 0; +} + int readgame(const char *filename, int backup) { int n, p, nread; @@ -1648,26 +1662,33 @@ int readgame(const char *filename, int backup) } else { for (u = f->units; u; u = u->nextF) { - sc_mage *mage = get_mage(u); - if (mage) { - faction *f = u->faction; - int skl = effskill(u, SK_MAGIC); - if (f->magiegebiet == M_GRAY) { - log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]); - f->magiegebiet = mage->magietyp; - } - if (f->max_spelllevel < skl) { - f->max_spelllevel = skl; - } - if (mage->spellcount < 0) { - mage->spellcount = 0; + if (global.data_version < SPELL_LEVEL_VERSION) { + sc_mage *mage = get_mage(u); + if (mage) { + faction *f = u->faction; + int skl = effskill(u, SK_MAGIC); + if (f->magiegebiet == M_GRAY) { + log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]); + f->magiegebiet = mage->magietyp; + } + if (f->max_spelllevel < skl) { + f->max_spelllevel = skl; + } + if (mage->spellcount < 0) { + mage->spellcount = 0; + } } } if (u->number > 0) { f->alive = true; - break; + if (global.data_version >= SPELL_LEVEL_VERSION) { + break; + } } } + if (global.data_version < SPELL_LEVEL_VERSION) { + spellbook_foreach(f->spellbook, cb_sb_maxlevel, f); + } } } if (loadplane || maxregions >= 0) { diff --git a/src/kernel/version.h b/src/kernel/version.h index 430628157..a32cfbe96 100644 --- a/src/kernel/version.h +++ b/src/kernel/version.h @@ -30,8 +30,9 @@ #define AUTO_RACENAME_VERSION 345 /* NPC units with name==NULL will automatically get their race for a name */ #define JSON_REPORT_VERSION 346 /* bit 3 in f->options flags the json report */ #define EXPLICIT_CURSE_ISNEW_VERSION 347 /* CURSE_ISNEW is not reset in read/write, but in age() */ +#define SPELL_LEVEL_VERSION 348 /* f->max_spelllevel gets stored, not calculated */ -#define RELEASE_VERSION EXPLICIT_CURSE_ISNEW_VERSION /* current datafile */ +#define RELEASE_VERSION SPELL_LEVEL_VERSION /* current datafile */ #define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ From ff38d8bf4c18d2705ad9320408f2cd2864a42044 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 20 Aug 2015 12:10:34 +0200 Subject: [PATCH 2/5] I don't think it's good to call update_spells before the turn. one should only have the spells that are in the previous week's report. a few comments wouldn't hurt. --- src/laws.c | 1 - src/magic.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/laws.c b/src/laws.c index b867b9f14..9a62ac53f 100755 --- a/src/laws.c +++ b/src/laws.c @@ -4531,7 +4531,6 @@ void processorders(void) init_processor(); init = 1; } - update_spells(); process(); /*************************************************/ diff --git a/src/magic.c b/src/magic.c index 72fe72a25..9ad9e0ad9 100644 --- a/src/magic.c +++ b/src/magic.c @@ -464,11 +464,13 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells spellno = rng_int() % maxspell; sbe = commonspells[spellno]; if (sbe->level > f->max_spelllevel) { + // not going to pick it in this round, move it to the end for later commonspells[spellno] = commonspells[--maxspell]; commonspells[maxspell] = sbe; sbe = 0; } else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { + // already have this spell, remove it from the list of candidates commonspells[spellno] = commonspells[--numspells]; if (maxspell > numspells) { maxspell = numspells; From 8716e5fdc5f67b7c83d9098866edd6cd6801ceac Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 20 Aug 2015 12:13:09 +0200 Subject: [PATCH 3/5] repair spellbooks that broke in E3 and E4 (temporary measure, remember to remove this code). --- conf/e3/config.xml | 1 + conf/e4/config.xml | 1 + src/CMakeLists.txt | 1 + src/kernel/save.c | 6 ++++ src/repair.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ src/repair.h | 14 ++++++++ 6 files changed, 109 insertions(+) create mode 100644 src/repair.c create mode 100644 src/repair.h diff --git a/conf/e3/config.xml b/conf/e3/config.xml index e0669c527..4ddf8ab21 100644 --- a/conf/e3/config.xml +++ b/conf/e3/config.xml @@ -100,6 +100,7 @@ + diff --git a/conf/e4/config.xml b/conf/e4/config.xml index 1924ff2c9..99ddbdf1d 100644 --- a/conf/e4/config.xml +++ b/conf/e4/config.xml @@ -101,6 +101,7 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34cb0987b..d17552712 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ ENDIF() set (ERESSEA_SRC move.c + repair.c spells.c battle.c alchemy.c diff --git a/src/kernel/save.c b/src/kernel/save.c index 9f6021b65..418f55864 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -48,6 +48,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "unit.h" #include "lighthouse.h" #include "version.h" +#include "repair.h" /* attributes includes */ #include @@ -1695,6 +1696,11 @@ int readgame(const char *filename, int backup) remove_empty_factions(); } log_printf(stdout, "Done loading turn %d.\n", turn); + + n = get_param_int(global.parameters, "fix.spells", -1); + if (n>=turn) { + repair_spells("spells.txt"); + } return 0; } diff --git a/src/repair.c b/src/repair.c new file mode 100644 index 000000000..b02b0a005 --- /dev/null +++ b/src/repair.c @@ -0,0 +1,86 @@ +#include +#include + +#include "repair.h" +#include +#include + +#include +#include + +#include + +#include +#include + +static void write_spellbook_states(FILE *F) { + faction *f; + for (f = factions; f; f = f->next) { + spellbook *sb = f->spellbook; + int len = sb ? ql_length(sb->spells) : 0; + fprintf(F, "%s %d %d\n", itoa36(f->no), f->subscription, len); + } +} + +static void limit_spellbook(faction *f, int num) { + spellbook *sb = f->spellbook; + int len = sb ? ql_length(sb->spells) : 0; + if (len < num) { + log_error("limit_spellbook: spellbook is shorter than expected, %d < %d", len, num); + } + // delete spells backwards from the end: + while (len > num) { + ql_delete(&sb->spells, len--); + } +} + +void repair_spells(const char *filename) { + FILE *F = fopen(filename, "r"); + if (F) { + char id[32]; + int numspells, sub; + faction *f; + while (fscanf(F, "%s %d %d", id, &sub, &numspells) != EOF) { + int no = atoi36(id); + + f = findfaction(no); + if (!f) { + for (f = factions; f; f = f->next) { + if (f->subscription == sub) { + break; + } + } + if (f) { + log_info("repair_spells: faction %s renamed to %s, located by subscription %d", id, itoa36(f->no), sub); + } + else { + log_warning("repair_spells: cannot fix faction %s, no such subscription: %d (%d spells)", id, sub, numspells); + continue; + } + } + if (f->subscription != sub) { + log_warning("repair_spells: subscription mismatch for faction %s, %d!=%d (%d spells)", id, f->subscription, sub, numspells); + } + else { + limit_spellbook(f, numspells); + fset(f, FFL_MARK); + } + } + for (f = factions; f; f = f->next) { + if (!fval(f, FFL_MARK)) { + numspells = ql_length(f->spellbook->spells); + log_warning("repair_spells: faction %s did not get a spellbook fix (%d spells at level)", itoa36(f->no), numspells, f->max_spelllevel); + } + freset(f, FFL_MARK); + } + } + else { + F = fopen(filename, "w"); + if (!F) { + perror("repair_spells"); + abort(); + } + write_spellbook_state(F); + } + fclose(F); +} diff --git a/src/repair.h b/src/repair.h new file mode 100644 index 000000000..cf20fb1be --- /dev/null +++ b/src/repair.h @@ -0,0 +1,14 @@ + +#ifndef H_REPAIR +#define H_REPAIR + +#ifdef __cplusplus +extern "C" { +#endif + + void repair_spells(const char *filename); // one-time reduction of E3/E4 spellbooks (called at the end of readgame) + +#ifdef __cplusplus +} +#endif +#endif From 469701a6ff8f93a0294040f70e326ef725945110 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 20 Aug 2015 12:56:33 +0200 Subject: [PATCH 4/5] fix linux build --- src/repair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repair.c b/src/repair.c index b02b0a005..665f250ae 100644 --- a/src/repair.c +++ b/src/repair.c @@ -80,7 +80,7 @@ void repair_spells(const char *filename) { perror("repair_spells"); abort(); } - write_spellbook_state(F); + write_spellbook_states(F); } fclose(F); } From 1641e6ef8926bead355750e3436c3374043dc5ec Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 20 Aug 2015 15:09:38 +0200 Subject: [PATCH 5/5] remove spellbook repair code, we are done --- conf/e3/config.xml | 1 - conf/e4/config.xml | 1 - src/CMakeLists.txt | 1 - src/kernel/save.c | 5 --- src/repair.c | 86 ---------------------------------------------- src/repair.h | 14 -------- 6 files changed, 108 deletions(-) delete mode 100644 src/repair.c delete mode 100644 src/repair.h diff --git a/conf/e3/config.xml b/conf/e3/config.xml index 4ddf8ab21..e0669c527 100644 --- a/conf/e3/config.xml +++ b/conf/e3/config.xml @@ -100,7 +100,6 @@ - diff --git a/conf/e4/config.xml b/conf/e4/config.xml index 99ddbdf1d..1924ff2c9 100644 --- a/conf/e4/config.xml +++ b/conf/e4/config.xml @@ -101,7 +101,6 @@ - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d17552712..34cb0987b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,6 @@ ENDIF() set (ERESSEA_SRC move.c - repair.c spells.c battle.c alchemy.c diff --git a/src/kernel/save.c b/src/kernel/save.c index 418f55864..0c7608ea5 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -48,7 +48,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "unit.h" #include "lighthouse.h" #include "version.h" -#include "repair.h" /* attributes includes */ #include @@ -1697,10 +1696,6 @@ int readgame(const char *filename, int backup) } log_printf(stdout, "Done loading turn %d.\n", turn); - n = get_param_int(global.parameters, "fix.spells", -1); - if (n>=turn) { - repair_spells("spells.txt"); - } return 0; } diff --git a/src/repair.c b/src/repair.c deleted file mode 100644 index 665f250ae..000000000 --- a/src/repair.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include "repair.h" -#include -#include - -#include -#include - -#include - -#include -#include - -static void write_spellbook_states(FILE *F) { - faction *f; - for (f = factions; f; f = f->next) { - spellbook *sb = f->spellbook; - int len = sb ? ql_length(sb->spells) : 0; - fprintf(F, "%s %d %d\n", itoa36(f->no), f->subscription, len); - } -} - -static void limit_spellbook(faction *f, int num) { - spellbook *sb = f->spellbook; - int len = sb ? ql_length(sb->spells) : 0; - if (len < num) { - log_error("limit_spellbook: spellbook is shorter than expected, %d < %d", len, num); - } - // delete spells backwards from the end: - while (len > num) { - ql_delete(&sb->spells, len--); - } -} - -void repair_spells(const char *filename) { - FILE *F = fopen(filename, "r"); - if (F) { - char id[32]; - int numspells, sub; - faction *f; - while (fscanf(F, "%s %d %d", id, &sub, &numspells) != EOF) { - int no = atoi36(id); - - f = findfaction(no); - if (!f) { - for (f = factions; f; f = f->next) { - if (f->subscription == sub) { - break; - } - } - if (f) { - log_info("repair_spells: faction %s renamed to %s, located by subscription %d", id, itoa36(f->no), sub); - } - else { - log_warning("repair_spells: cannot fix faction %s, no such subscription: %d (%d spells)", id, sub, numspells); - continue; - } - } - if (f->subscription != sub) { - log_warning("repair_spells: subscription mismatch for faction %s, %d!=%d (%d spells)", id, f->subscription, sub, numspells); - } - else { - limit_spellbook(f, numspells); - fset(f, FFL_MARK); - } - } - for (f = factions; f; f = f->next) { - if (!fval(f, FFL_MARK)) { - numspells = ql_length(f->spellbook->spells); - log_warning("repair_spells: faction %s did not get a spellbook fix (%d spells at level)", itoa36(f->no), numspells, f->max_spelllevel); - } - freset(f, FFL_MARK); - } - } - else { - F = fopen(filename, "w"); - if (!F) { - perror("repair_spells"); - abort(); - } - write_spellbook_states(F); - } - fclose(F); -} diff --git a/src/repair.h b/src/repair.h deleted file mode 100644 index cf20fb1be..000000000 --- a/src/repair.h +++ /dev/null @@ -1,14 +0,0 @@ - -#ifndef H_REPAIR -#define H_REPAIR - -#ifdef __cplusplus -extern "C" { -#endif - - void repair_spells(const char *filename); // one-time reduction of E3/E4 spellbooks (called at the end of readgame) - -#ifdef __cplusplus -} -#endif -#endif