diff --git a/clibs b/clibs
index f91ef37f0..27c8b3202 160000
--- a/clibs
+++ b/clibs
@@ -1 +1 @@
-Subproject commit f91ef37f08c5244bf616f1836c0aa9caaf36805c
+Subproject commit 27c8b3202b52766465743c3324fc0b52c5ba4b11
diff --git a/cmake b/cmake
index f1fb3943a..d88983c7f 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit f1fb3943ace59994d90d71a891b80033dc2700a2
+Subproject commit d88983c7ff4bc3a4884a7c3f74e8190bac5eab23
diff --git a/conf/e2/config.json b/conf/e2/config.json
index ca157f501..f9f9b2df0 100644
--- a/conf/e2/config.json
+++ b/conf/e2/config.json
@@ -8,6 +8,8 @@
"jsreport"
],
"settings": {
+ "game.name" : "Eressea",
+ "game.id" : 2,
"orders.default": "work",
"NewbieImmunity": 8,
"modules.wormholes": true,
diff --git a/conf/e3/config.json b/conf/e3/config.json
index fd533070e..8783055b8 100644
--- a/conf/e3/config.json
+++ b/conf/e3/config.json
@@ -25,6 +25,8 @@
"jsreport"
],
"settings": {
+ "game.name" : "Eressea",
+ "game.id" : 3,
"orders.default": "work",
"database.gameid": 7,
"NewbieImmunity": 4,
diff --git a/conf/e4/catalog.xml b/conf/e4/catalog.xml
deleted file mode 100644
index 9987e72c8..000000000
--- a/conf/e4/catalog.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/conf/e4/config.json b/conf/e4/config.json
deleted file mode 100644
index 91961258a..000000000
--- a/conf/e4/config.json
+++ /dev/null
@@ -1,93 +0,0 @@
-{
- "include": [
- "keywords.json",
- "prefixes.json",
- "e3/terrains.json"
- ],
- "disabled": [
- "herbalism",
- "alchemy",
- "entertainment",
- "espionage",
- "perception",
- "stealth",
- "taxation",
- "trade",
- "besiege",
- "steal",
- "buy",
- "teach",
- "sabotage",
- "spy",
- "tax",
- "entertain",
- "sell",
- "jsreport"
- ],
- "settings": {
- "orders.default": "work",
- "database.gameid": 7,
- "NewbieImmunity": 4,
- "modules.astralspace": false,
- "modules.wormholes": false,
- "modules.markets": true,
- "magic.regeneration": 0.75,
- "magic.power": 0.5,
- "resource.factor": 0.25,
- "skills.cost.tactics": 500,
- "entertain.base": 0,
- "entertain.perlevel": 20,
- "nmr.timeout": 5,
- "nmr.removenewbie": 0,
- "GiveRestriction": 3,
- "hunger.long": false,
- "hunger.damage": "1d9+9",
- "hunger.demons.skill": true,
- "hunger.demons.peasant_tolerance": true,
- "init_spells": 0,
- "recruit.allow_merge": true,
- "study.expensivemigrants": true,
- "study.speedup": 2,
- "study.produceexp": 12,
- "world.era": 3,
- "rules.reserve.twophase": true,
- "rules.owners.force_leave": false,
- "rules.transfermen": false,
- "stealth.faction.other": false,
- "rules.stealth.anon_battle": false,
- "rules.check_overload": false,
- "rules.combat.goblinbonus": 3,
- "rules.alliances": true,
- "rules.combat.herospeed": 3,
- "rules.combat.demon_vampire": 5,
- "rules.combat.skill_bonus": 0,
- "rules.combat.nat_armor": 1,
- "rules.items.loot_divisor": 2,
- "rules.items.give_divisor": 2,
- "rules.move.owner_leave": true,
- "rules.region_owners": true,
- "rules.cavalry.skill": 2,
- "rules.cavalry.mode": 1,
- "rules.magic.multipotion": true,
- "rules.magic.wol_effect": 5,
- "rules.magic.factionlist": true,
- "rules.magic.wol_type": 2,
- "rules.blessed_harvest.flags": 1,
- "rules.magic.elfpower": true,
- "rules.magic.playerschools": "gwyrrd illaun draig cerddor",
- "rules.build.other_buildings": true,
- "rules.economy.taxation": 1,
- "rules.food.flags": 2,
- "rules.economy.roqf": 5,
- "rules.economy.herbrot": 0,
- "rules.region_owner_pay_building": "market harbour lighthouse",
- "rules.dwarf_castles": true,
- "rules.limit.faction": 250,
- "rules.grow.formula": 1,
- "rules.tactics.formula": 1,
- "rules.help.mask": "fight guard money give",
- "movement.shipspeed.skillbonus": 6,
- "alliance.auto": "fight",
- "alliance.restricted": "fight"
- }
-}
diff --git a/conf/e4/config.xml b/conf/e4/config.xml
deleted file mode 100644
index f9ede1a27..000000000
--- a/conf/e4/config.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/s/build b/s/build
index 01acc1ae2..4ee259573 100755
--- a/s/build
+++ b/s/build
@@ -1,8 +1,5 @@
#!/bin/sh
-ROOT=`pwd`
-while [ ! -d $ROOT/.git ]; do
- ROOT=`dirname $ROOT`
-done
+ROOT=$(git rev-parse --show-toplevel)
[ -z "$BUILD" ] && BUILD=Debug
if [ -z "$JOBS" ] ; then
@@ -35,7 +32,13 @@ fi
echo "build eressea"
cd $ROOT/$BUILD
+BRANCH=$(git status -s -b | head -1 | cut -d\ -f 2 | sed 's/\..*//')
+if [ "$BRANCH"=="master" ] ; then
VERSION=$(git describe --match 'v*.*.*' --tags | sed 's/^v//')
cmake -DERESSEA_VERSION="$VERSION" ..
+else
+REV=$(git rev-parse --short HEAD)
+cmake -DERESSEA_BUILDNO="$REV" ..
+fi
make $MAKEOPTS && make test
cd $OLDPWD
diff --git a/s/cmake-init b/s/cmake-init
index 84a1d9cdb..1ce7eccd3 100755
--- a/s/cmake-init
+++ b/s/cmake-init
@@ -1,13 +1,6 @@
#!/bin/sh
-ROOT=$(pwd)
-while [ ! -d $ROOT/.git ]; do
- ROOT=$(dirname $ROOT)
- if [ "$ROOT" == "/" ; then
- echo "could not find root, are you in the git repository?"
- exit
- fi
-done
+ROOT=$(git rev-parse --show-toplevel)
[ -z $BUILD ] && BUILD=Debug
[ -z "$CC" ] && [ ! -z `which clang` ] && CC="clang"
[ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc"
diff --git a/s/runtests b/s/runtests
index e0e20b5c7..e42640de1 100755
--- a/s/runtests
+++ b/s/runtests
@@ -1,11 +1,7 @@
#!/bin/bash
set -e
-ROOT=$(pwd)
-while [ ! -d $ROOT/.git ]; do
- ROOT=$(dirname $ROOT)
-done
-
+ROOT=$(git rev-parse --show-toplevel)
[ -z $BUILD ] && BUILD=Debug ; export BUILD
if [ ! -e $ROOT/$BUILD ]; then
@@ -19,7 +15,6 @@ cd $ROOT
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests.lua
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e2.lua
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e3.lua
-$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e4.lua
rm -rf data reports orders.txt score score.alliances datum turn
cd $OLDWPD
diff --git a/s/upgrade b/s/upgrade
new file mode 100755
index 000000000..9d9d5a313
--- /dev/null
+++ b/s/upgrade
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+
+ROOT=`pwd`
+while [ ! -d $ROOT/.git ]; do
+ ROOT=`dirname $ROOT`
+done
+
+cd $ROOT
+git pull
+git submodule update
+s/build
+s/runtests
+s/install
diff --git a/scripts/eressea/e4/init.lua b/scripts/eressea/e4/init.lua
deleted file mode 100644
index 32c0b8498..000000000
--- a/scripts/eressea/e4/init.lua
+++ /dev/null
@@ -1,11 +0,0 @@
-require 'eressea.e3.rules'
-require 'eressea.spells'
-
-eressea.log.debug("rules for game E4")
-
-return {
- require('eressea'),
- -- require('eressea.markets'),
- require('eressea.frost'),
- require('eressea.ents')
-}
diff --git a/scripts/run-tests-e4.lua b/scripts/run-tests-e4.lua
deleted file mode 100644
index f827baec0..000000000
--- a/scripts/run-tests-e4.lua
+++ /dev/null
@@ -1,23 +0,0 @@
--- Tests that work in E3. With game config of E3.
--- Tests are under scripts/test/e3 and all files must be in scripts/test/e3/init.lua
-
-path = 'scripts'
-if config.install then
- path = config.install .. '/' .. path
- package.path = package.path .. ';' .. config.install .. '/lunit/?.lua'
- --needed to find lunit if not run form eressea root. Needs right [lua] install setting in eressea.ini (point to eressea root from the start folder)
-end
-package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua'
-
-config.rules = 'e4'
-
-require 'eressea'
-require 'eressea.path'
-require 'eressea.xmlconf'
-require 'tests.e3'
-require 'lunit'
-
-eressea.settings.set("rules.alliances", "0")
-rules = require('eressea.' .. config.rules)
-result = lunit.main()
-return result.errors + result.failed
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 39d290560..a65cb8912 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,6 +15,11 @@ set_source_files_properties(kernel/version.c PROPERTIES
COMPILE_DEFINITIONS ERESSEA_VERSION="${ERESSEA_VERSION}")
ENDIF()
+IF(DEFINED ERESSEA_BUILDNO)
+set_source_files_properties(kernel/version.c PROPERTIES
+COMPILE_DEFINITIONS ERESSEA_BUILDNO="${ERESSEA_BUILDNO}")
+ENDIF()
+
IF (CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=unused-but-set-variable")
ENDIF()
diff --git a/src/battle.c b/src/battle.c
index 4105cf73f..ad613a69f 100644
--- a/src/battle.c
+++ b/src/battle.c
@@ -1858,10 +1858,13 @@ static void do_combatspell(troop at)
static void do_extra_spell(troop at, const att * a)
{
- const spell *sp = a->data.sp;
+ const spell *sp = spellref_get(a->data.sp);
- if (sp->cast == NULL) {
- log_error("spell '%s' has no function.\n", sp->sname);
+ if (!sp) {
+ log_error("no such spell: '%s'", a->data.sp->name);
+ }
+ else if (sp->cast == NULL) {
+ log_error("spell '%s' has no function.", sp->sname);
}
else {
assert(a->level > 0);
diff --git a/src/creport.c b/src/creport.c
index 106f34545..345aaf0bc 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -718,6 +718,7 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel)
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= maxlevel) {
+ // TODO: no need to deref spref here, spref->name == sp->sname
spell * sp = sbe->sp;
const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale));
if (!header) {
diff --git a/src/kernel/config.c b/src/kernel/config.c
index 83d0808da..ca23a5bc9 100644
--- a/src/kernel/config.c
+++ b/src/kernel/config.c
@@ -749,13 +749,18 @@ void config_set_from(const dictionary *d)
key[slen] = '.';
iniparser_getseckeys(d, sec, keys);
for (k=0;k!=nkeys;++k) {
- const char *val;
+ const char *val, *orig;
size_t klen = strlen(keys[k]);
assert(klen+slen+1sp = NULL;
+ ls->spref = spellref_create(NULL, name);
ls->level = level;
- ls->name = strdup(name);
selist_push(&eq->spells, ls);
}
}
@@ -162,12 +160,8 @@ void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask)
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
lazy_spell *sbe = (lazy_spell *)selist_get(ql, qi);
- if (!sbe->sp) {
- sbe->sp = find_spell(sbe->name);
- free(sbe->name);
- sbe->name = NULL;
- }
- unit_add_spell(u, mage, sbe->sp, sbe->level);
+ spell *sp = spellref_get(sbe->spref);
+ unit_add_spell(u, mage, sp, sbe->level);
}
}
}
@@ -238,7 +232,7 @@ void equip_items(struct item **items, const struct equipment *eq)
void free_ls(void *arg) {
lazy_spell *ls = (lazy_spell*)arg;
- free(ls->name);
+ spellref_free(ls->spref);
free(ls);
}
diff --git a/src/kernel/race.c b/src/kernel/race.c
index a78a9e340..1bdba8a1b 100644
--- a/src/kernel/race.c
+++ b/src/kernel/race.c
@@ -32,6 +32,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "region.h"
#include "ship.h"
#include "skill.h"
+#include "spell.h"
#include "terrain.h"
#include "unit.h"
@@ -181,7 +182,13 @@ void racelist_insert(struct race_list **rl, const struct race *r)
void free_races(void) {
while (races) {
+ int i;
race * rc = races->next;
+
+ for (i = 0; races->attack[i].type!=AT_NONE; ++i) {
+ spellref_free(races->attack[i].data.sp);
+ }
+ spellref_free(races->precombatspell);
free_params(&races->parameters);
free(xrefs);
xrefs = 0;
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 6673676bd..19b7b7ad3 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -45,6 +45,7 @@ extern "C" {
struct param;
struct spell;
+ struct spellref;
struct locale;
extern int num_races;
@@ -104,7 +105,7 @@ extern "C" {
int type;
union {
const char *dice;
- const struct spell *sp;
+ struct spellref *sp;
} data;
int flags;
int level;
@@ -137,7 +138,7 @@ extern "C" {
int at_bonus; /* Ver�ndert den Angriffsskill (default: 0) */
int df_bonus; /* Ver�ndert den Verteidigungskill (default: 0) */
struct param *parameters; // additional properties, for an example see natural_armor
- const struct spell *precombatspell;
+ struct spellref *precombatspell;
signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */
int flags;
int battle_flags;
diff --git a/src/kernel/save.c b/src/kernel/save.c
index ac236d5bf..8ec797e68 100644
--- a/src/kernel/save.c
+++ b/src/kernel/save.c
@@ -1633,14 +1633,7 @@ int read_game(gamedata *data) {
READ_INT(store, &gameid);
if (gameid != game_id()) {
- int c;
log_warning("game mismatch: datafile contains game %d, but config is for %d", gameid, game_id());
- printf("WARNING: invalid game id. any key to continue, Ctrl-C to stop\n");
- c = getchar();
- if (c == EOF) {
- log_error("aborting.");
- abort();
- }
}
}
else {
diff --git a/src/kernel/spell.c b/src/kernel/spell.c
index 5415c4a0e..212b0a7d2 100644
--- a/src/kernel/spell.c
+++ b/src/kernel/spell.c
@@ -145,3 +145,39 @@ spell *find_spellbyid(unsigned int id)
log_warning("cannot find spell by id: %u\n", id);
return NULL;
}
+
+struct spellref *spellref_create(spell *sp, const char *name)
+{
+ spellref *spref = malloc(sizeof(spellref));
+
+ if (sp) {
+ spref->sp = sp;
+ spref->name = strdup(sp->sname);
+ }
+ else if (name) {
+ spref->name = strdup(name);
+ spref->sp = NULL;
+ }
+ return spref;
+}
+
+void spellref_free(spellref *spref)
+{
+ if (spref) {
+ free(spref->name);
+ free(spref);
+ }
+}
+
+struct spell *spellref_get(struct spellref *spref)
+{
+ if (!spref->sp) {
+ assert(spref->name);
+ spref->sp = find_spell(spref->name);
+ if (spref->sp) {
+ free(spref->name);
+ spref->name = NULL;
+ }
+ }
+ return spref->sp;
+}
diff --git a/src/kernel/spell.h b/src/kernel/spell.h
index f74fda6e2..e7592f082 100644
--- a/src/kernel/spell.h
+++ b/src/kernel/spell.h
@@ -45,6 +45,15 @@ extern "C" {
fumble_f fumble;
} spell;
+ typedef struct spellref {
+ char * name;
+ struct spell *sp;
+ } spellref;
+
+ struct spellref *spellref_create(struct spell *sp, const char *name);
+ void spellref_free(struct spellref *spref);
+ struct spell *spellref_get(struct spellref *spref);
+
int sp_antimagiczone(struct castorder *co);
struct spell * create_spell(const char * name, unsigned int id);
@@ -61,7 +70,7 @@ extern "C" {
}
#endif
#endif
-/* ------------------------------------------------------------- *//* Erläuterungen zu den Spruchdefinitionen
+/* ------------------------------------------------------------- *//* Erl�uterungen zu den Spruchdefinitionen
*
* Spruchstukturdefinition:
* spell{
@@ -79,35 +88,35 @@ extern "C" {
* id:
* SPL_NOSPELL muss der letzte Spruch in der Liste spelldaten sein,
* denn nicht auf die Reihenfolge in der Liste sondern auf die id wird
- * geprüft
+ * gepr�ft
*
* sptyp:
* besondere Spruchtypen und Flags
* (Regionszauber, Kampfzauber, Farcastbar, Stufe variable, ..)
*
* rank:
- * gibt die Priorität und damit die Reihenfolge an, in der der Spruch
+ * gibt die Priorit�t und damit die Reihenfolge an, in der der Spruch
* gezaubert wird.
- * 1: Aura übertragen
+ * 1: Aura �bertragen
* 2: Antimagie
- * 3: Magierverändernde Sprüche (Magic Boost, ..)
+ * 3: Magierver�ndernde Spr�che (Magic Boost, ..)
* 4: Monster erschaffen
* 5: Standartlevel
* 7: Teleport
*
- * Komponenten[Anzahl mögl. Items][Art:Anzahl:Kostentyp]
+ * Komponenten[Anzahl m�gl. Items][Art:Anzahl:Kostentyp]
*
* R_AURA:
- * Grundkosten für einen Zauber. Soviel Mp müssen mindestens investiert
- * werden, um den Spruch zu wirken. Zusätzliche Mp können unterschiedliche
+ * Grundkosten f�r einen Zauber. Soviel Mp m�ssen mindestens investiert
+ * werden, um den Spruch zu wirken. Zus�tzliche Mp k�nnen unterschiedliche
* Auswirkungen haben, die in der Spruchfunktionsroutine definiert werden.
*
* R_PERMAURA:
* Kosten an permantenter Aura
*
* Komponenten Kostentyp:
- * SPC_LEVEL == Spruch mit Levelabhängigen Magiekosten. Die angegeben
- * Kosten müssen für Stufe 1 berechnet sein.
+ * SPC_LEVEL == Spruch mit Levelabh�ngigen Magiekosten. Die angegeben
+ * Kosten m�ssen f�r Stufe 1 berechnet sein.
* SPC_FIX == Feste Kosten
*
* Wenn keine spezielle Syntax angegeben ist, wird die
@@ -128,34 +137,34 @@ extern "C" {
*
* u : eine Einheitennummer
* r : hier kommen zwei Regionskoordinaten x y
- * b : Gebäude- oder Burgnummer
+ * b : Geb�ude- oder Burgnummer
* s : Schiffsnummer
- * c : String, wird ohne Weiterverarbeitung übergeben
- * i : Zahl (int), wird ohne Weiterverarbeitung übergeben
+ * c : String, wird ohne Weiterverarbeitung �bergeben
+ * i : Zahl (int), wird ohne Weiterverarbeitung �bergeben
* k : Keywort - dieser String gibt den Paramter an, der folgt. Der
* Parameter wird mit findparam() identifiziert.
- * k muss immer von einem c als Platzhalter für das Objekt gefolgt
+ * k muss immer von einem c als Platzhalter f�r das Objekt gefolgt
* werden.
- * Ein gutes Beispiel sind hierfür die Sprüche zur Magieanalyse.
+ * Ein gutes Beispiel sind hierf�r die Spr�che zur Magieanalyse.
* + : gibt an, das der vorherige Parameter mehrfach vorkommen kann. Da
* ein Ende nicht definiert werden kann, muss dies immer am Schluss
* kommen.
*
- * Flags für das Parsing:
+ * Flags f�r das Parsing:
* TESTRESISTANCE : alle Zielobjekte, also alle Parameter vom Typ Unit,
* Burg, Schiff oder Region, werden auf ihre
- * Magieresistenz überprüft
+ * Magieresistenz �berpr�ft
* TESTCANSEE : jedes Objekt vom Typ Einheit wird auf seine
- * Sichtbarkeit überprüft
+ * Sichtbarkeit �berpr�ft
* SEARCHLOCAL : die Zielobjekte werden nur regional gesucht
* REGIONSPELL : Ziel ist die Region, auch wenn kein Zielobjekt
* angegeben wird. Ist TESTRESISTANCE gesetzt, so wird
- * die Magieresistenz der Region überprüft
+ * die Magieresistenz der Region �berpr�ft
*
* Bei fehlendem Ziel oder wenn dieses dem Zauber widersteht, wird die
* Spruchfunktion nicht aufgerufen.
* Sind zu wenig Parameter vorhanden, wird der Zauber ebenfalls nicht
- * ausgeführt.
+ * ausgef�hrt.
* Ist eins von mehreren Zielobjekten resistent, so wird das Flag
* pa->param[n]->flag == TARGET_RESISTS
* Ist eins von mehreren Zielobjekten nicht gefunden worden, so ist
diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c
index 6bb2ac449..b500f94cc 100644
--- a/src/kernel/spell.test.c
+++ b/src/kernel/spell.test.c
@@ -69,9 +69,27 @@ static void test_create_spell_with_id(CuTest * tc)
test_cleanup();
}
+static void test_spellref(CuTest *tc)
+{
+ spellref *ref;
+ spell *sp;
+ test_setup();
+ ref = spellref_create(NULL, "hodor");
+ CuAssertPtrNotNull(tc, ref);
+ CuAssertPtrEquals(tc, NULL, ref->sp);
+ CuAssertStrEquals(tc, "hodor", ref->name);
+ CuAssertPtrEquals(tc, NULL, spellref_get(ref));
+ sp = create_spell("hodor", 0);
+ CuAssertPtrNotNull(tc, sp);
+ CuAssertPtrEquals(tc, sp, spellref_get(ref));
+ spellref_free(ref);
+ test_cleanup();
+}
+
CuSuite *get_spell_suite(void)
{
CuSuite *suite = CuSuiteNew();
+ SUITE_ADD_TEST(suite, test_spellref);
SUITE_ADD_TEST(suite, test_create_a_spell);
SUITE_ADD_TEST(suite, test_create_duplicate_spell);
SUITE_ADD_TEST(suite, test_create_spell_with_id);
diff --git a/src/kernel/spellbook.c b/src/kernel/spellbook.c
index bb060eaee..b7f65420c 100644
--- a/src/kernel/spellbook.c
+++ b/src/kernel/spellbook.c
@@ -71,7 +71,7 @@ void write_spellbook(const struct spellbook *book, struct storage *store)
WRITE_TOK(store, "end");
}
-void spellbook_add(spellbook *sb, struct spell * sp, int level)
+void spellbook_add(spellbook *sb, spell *sp, int level)
{
spellbook_entry * sbe;
@@ -116,7 +116,7 @@ int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *),
return 0;
}
-spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp)
+spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp)
{
if (sb) {
selist *ql;
@@ -124,11 +124,10 @@ spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp)
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
- if (sp == sbe->sp) {
+ if (sbe->sp==sp) {
return sbe;
}
}
}
return 0;
}
-
diff --git a/src/kernel/spellbook.h b/src/kernel/spellbook.h
index 75a420c06..fb3438a8b 100644
--- a/src/kernel/spellbook.h
+++ b/src/kernel/spellbook.h
@@ -29,7 +29,7 @@ extern "C" {
struct selist;
typedef struct spellbook_entry {
- struct spell * sp;
+ struct spell *sp;
int level;
} spellbook_entry;
@@ -44,10 +44,10 @@ extern "C" {
void read_spellbook(struct spellbook **bookp, struct gamedata *data, int(*get_level)(const struct spell * sp, void *), void * cbdata);
void write_spellbook(const struct spellbook *book, struct storage *store);
- void spellbook_add(spellbook *sbp, struct spell * sp, int level);
+ void spellbook_add(spellbook *sbp, struct spell *sp, int level);
int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data);
void spellbook_clear(spellbook *sb);
- spellbook_entry * spellbook_get(spellbook *sb, const struct spell * sp);
+ spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp);
#ifdef __cplusplus
}
diff --git a/src/kernel/version.c b/src/kernel/version.c
index 8add29ccc..7e8ed01d7 100644
--- a/src/kernel/version.c
+++ b/src/kernel/version.c
@@ -5,15 +5,18 @@
#ifndef ERESSEA_VERSION
// the version number, if it was not passed to make with -D
-#define ERESSEA_VERSION "3.11.0-devel"
+#define ERESSEA_VERSION "3.11.0"
#endif
const char *eressea_version(void) {
+#ifdef ERESSEA_BUILDNO
+ return ERESSEA_VERSION "-" ERESSEA_BUILDNO;
+#endif
return ERESSEA_VERSION;
}
int version_no(const char *str) {
- int maj = 0, min = 0, bld = 0;
- sscanf(str, "%d.%d.%d", &maj, &min, &bld);
- return (maj << 16) | (min << 8) | bld;
+ int maj = 0, min = 0, pat = 0;
+ sscanf(str, "%d.%d.%d", &maj, &min, &pat);
+ return (maj << 16) | (min << 8) | pat;
}
diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c
index cba01bc7b..854a6dd4c 100644
--- a/src/kernel/xmlreader.c
+++ b/src/kernel/xmlreader.c
@@ -75,16 +75,15 @@ static void xml_readtext(xmlNodePtr node, struct locale **lang, xmlChar ** text)
*text = xmlNodeListGetString(node->doc, node->children, 1);
}
-static const spell *xml_spell(xmlNode * node, const char *name)
+static spellref *xml_spellref(xmlNode * node, const char *name)
{
- const spell *sp = NULL;
xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
if (propValue != NULL) {
- sp = find_spell((const char *)propValue);
- assert(sp);
+ spellref *ref = spellref_create(NULL, (const char *)propValue);
xmlFree(propValue);
+ return ref;
}
- return sp;
+ return NULL;
}
static xmlChar *xml_cleanup_string(xmlChar * str)
@@ -1853,7 +1852,7 @@ static int parse_races(xmlDocPtr doc)
|| !"precombatspell is already initialized");
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
- rc->precombatspell = xml_spell(node, "spell");
+ rc->precombatspell = xml_spellref(node, "spell");
}
xmlXPathFreeObject(result);
@@ -1878,11 +1877,11 @@ static int parse_races(xmlDocPtr doc)
xmlFree(propValue);
}
else {
- attack->data.sp = xml_spell(node, "spell");
+ attack->data.sp = xml_spellref(node, "spell");
if (attack->data.sp) {
attack->level = xml_ivalue(node, "level", 0);
if (attack->level <= 0) {
- log_error("magical attack '%s' for race '%s' needs a level: %d\n", attack->data.sp->sname, rc->_name, attack->level);
+ log_error("magical attack '%s' for race '%s' needs a level: %d\n", attack->data.sp->name, rc->_name, attack->level);
}
}
}
@@ -2069,17 +2068,20 @@ static int parse_strings(xmlDocPtr doc)
void register_xmlreader(void)
{
- xml_register_callback(parse_strings);
- xml_register_callback(parse_messages);
- xml_register_callback(parse_resources);
xml_register_callback(parse_rules);
- xml_register_callback(parse_buildings); /* requires resources */
- xml_register_callback(parse_ships); /* requires terrains */
- xml_register_callback(parse_spells); /* requires resources */
- xml_register_callback(parse_spellbooks); /* requires spells */
- xml_register_callback(parse_equipment); /* requires spells */
- xml_register_callback(parse_races); /* requires spells */
+ xml_register_callback(parse_races);
xml_register_callback(parse_calendar);
+ xml_register_callback(parse_resources);
+
+ xml_register_callback(parse_buildings); /* requires resources */
+ xml_register_callback(parse_ships); /* requires resources, terrains */
+ xml_register_callback(parse_equipment); /* requires resources */
+
+ xml_register_callback(parse_spells); /* requires resources */
+ xml_register_callback(parse_spellbooks); /* requires spells */
+
+ xml_register_callback(parse_strings);
+ xml_register_callback(parse_messages);
}
#endif
diff --git a/src/magic.c b/src/magic.c
index f2992538c..7e820f9c3 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -430,7 +430,6 @@ void show_new_spells(faction * f, int level, const spellbook *book)
for (qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= level) {
-
if (!already_seen(f, sbe->sp)) {
attrib * a = a_new(&at_reportspell);
spellbook_entry * entry = (spellbook_entry *)a->data.v;
@@ -481,13 +480,15 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
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;
+ 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;
+ }
+ sbe = 0;
}
- sbe = 0;
}
}
@@ -560,8 +561,11 @@ const spell *get_combatspell(const unit * u, int nr)
if (m) {
return m->combatspells[nr].sp;
}
- else if (u_race(u)->precombatspell != NULL) {
- return u_race(u)->precombatspell;
+ else {
+ const race * rc = u_race(u);
+ if (rc->precombatspell) {
+ return spellref_get(rc->precombatspell);
+ }
}
return NULL;
@@ -2945,6 +2949,7 @@ const char *spell_info(const spell * sp, const struct locale *lang)
return LOC(lang, mkname("spellinfo", sp->sname));
}
+// TODO: should take the name, not the spell (spellref optimizations)
const char *spell_name(const spell * sp, const struct locale *lang)
{
return LOC(lang, mkname("spell", sp->sname));
@@ -2964,15 +2969,14 @@ static void select_spellbook(void **tokens, spellbook *sb, const struct locale *
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
- spell *sp = sbe->sp;
- const char *n = spell_name(sp, lang);
+ const char *n = spell_name(sbe->sp, lang);
if (!n) {
- log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname);
+ log_error("no translation in locale %s for spell %s\n", locale_name(lang), sbe->sp->sname);
}
else {
variant token;
- token.v = sp;
+ token.v = sbe->sp;
addtoken((struct tnode **)tokens, n, token);
}
}
diff --git a/src/main.c b/src/main.c
index 777770f0a..a3bcdb866 100644
--- a/src/main.c
+++ b/src/main.c
@@ -76,10 +76,20 @@ static void load_inifile(dictionary * d)
static dictionary *parse_config(const char *filename)
{
- dictionary *d = iniparser_load(filename);
+ char path[MAX_PATH];
+ dictionary *d;
+ const char *cfgpath = config_get("config.path");
+
+ if (cfgpath) {
+ join_path(cfgpath, filename, path, sizeof(path));
+ log_debug("reading from configuration file %s\n", path);
+ d = iniparser_load(path);
+ } else {
+ log_debug("reading from configuration file %s\n", filename);
+ d = iniparser_load(filename);
+ }
if (d) {
load_inifile(d);
- log_debug("reading from configuration file %s\n", filename);
config_set_from(d);
memdebug = iniparser_getint(d, "game:memcheck", memdebug);
@@ -176,6 +186,10 @@ static int parse_args(int argc, char **argv, int *exitcode)
else {
const char *arg;
switch (argi[1]) {
+ case 'c':
+ i = get_arg(argc, argv, 2, i, &arg, 0);
+ config_set("config.path", arg);
+ break;
case 'r':
i = get_arg(argc, argv, 2, i, &arg, 0);
config_set("config.rules", arg);
@@ -270,15 +284,15 @@ int main(int argc, char **argv)
{
int err = 0;
lua_State *L;
- dictionary *d;
+ dictionary *d = 0;
setup_signal_handler();
- /* ini file sets defaults for arguments*/
+ /* parse arguments again, to override ini file */
+ parse_args(argc, argv, &err);
+
d = parse_config(inifile);
if (!d) {
log_error("could not open ini configuration %s\n", inifile);
}
- /* parse arguments again, to override ini file */
- parse_args(argc, argv, &err);
locale_init();
diff --git a/src/report.c b/src/report.c
index 1282789fa..06244c70c 100644
--- a/src/report.c
+++ b/src/report.c
@@ -234,7 +234,7 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
} while (*begin);
}
-static size_t write_spell_modifier(spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) {
+static size_t write_spell_modifier(const spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) {
if (sp->sptyp & flag) {
size_t bytes = 0;
if (cont) {
@@ -255,7 +255,7 @@ void nr_spell_syntax(struct stream *out, spellbook_entry * sbe, const struct loc
char buf[4096];
char *bufp = buf;
size_t size = sizeof(buf) - 1;
- spell * sp = sbe->sp;
+ const spell * sp = sbe->sp;
const char *params = sp->parameter;
if (sp->sptyp & ISCOMBATSPELL) {
@@ -445,7 +445,7 @@ void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *la
char buf[4096];
char *startp, *bufp = buf;
size_t size = sizeof(buf) - 1;
- spell * sp = sbe->sp;
+ const spell * sp = sbe->sp;
newline(out);
centre(out, spell_name(sp, lang), true);
diff --git a/src/reports.c b/src/reports.c
index 5a47acfed..318660024 100644
--- a/src/reports.c
+++ b/src/reports.c
@@ -680,6 +680,7 @@ size_t size)
if (wrptr(&bufp, &size, result) != 0) {
WARN_STATIC_BUFFER();
}
+ // TODO: no need to deref the spellref here (spref->name is good)
bufp = STRLCPY(bufp, spell_name(sbe->sp, f->locale), size);
}
}
diff --git a/src/util/unicode.test.c b/src/util/unicode.test.c
index a6268186e..76cda9a8f 100644
--- a/src/util/unicode.test.c
+++ b/src/util/unicode.test.c
@@ -116,6 +116,13 @@ static void test_unicode_bug2262(CuTest *tc) {
CuAssertIntEquals(tc, EILSEQ, unicode_utf8_trim(name));
}
+static void test_unicode_compare(CuTest *tc)
+{
+ CuAssertIntEquals(tc, 0, unicode_utf8_strcasecmp("ABCDEFG", "abcdefg"));
+ CuAssertIntEquals(tc, 0, unicode_utf8_strcasecmp("abcdefg123", "ABCDEFG123"));
+ CuAssertIntEquals(tc, 1, unicode_utf8_strcasecmp("bacdefg123", "ABCDEFG123"));
+}
+
CuSuite *get_unicode_suite(void)
{
CuSuite *suite = CuSuiteNew();
@@ -124,5 +131,6 @@ CuSuite *get_unicode_suite(void)
SUITE_ADD_TEST(suite, test_unicode_trim);
SUITE_ADD_TEST(suite, test_unicode_utf8_to_other);
SUITE_ADD_TEST(suite, test_unicode_utf8_to_ucs);
+ SUITE_ADD_TEST(suite, test_unicode_compare);
return suite;
}
diff --git a/tests/runtests.bat b/tests/runtests.bat
index 996fb47b7..41b5f8056 100644
--- a/tests/runtests.bat
+++ b/tests/runtests.bat
@@ -8,7 +8,6 @@ SET SERVER=%BUILD%\eressea.exe
%SERVER% ..\scripts\run-tests.lua
%SERVER% -re2 ..\scripts\run-tests-e2.lua
%SERVER% -re3 ..\scripts\run-tests-e3.lua
-%SERVER% -re4 ..\scripts\run-tests-e4.lua
PAUSE
RMDIR /s /q reports
DEL score score.alliances datum turn