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