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