Merge pull request #254 from badgerman/develop

static analysis bugfixes
This commit is contained in:
Enno Rehling 2015-07-07 15:42:59 +02:00
commit f86314c55a
25 changed files with 910 additions and 804 deletions

View File

@ -2,10 +2,12 @@ language: c
compiler: compiler:
- gcc - gcc
- clang - clang
script: s/travis-build
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq zlib1g-dev libtolua-dev liblua5.1-dev libncurses5-dev libsqlite3-dev libxml2-dev valgrind install:
- sudo apt-get install -qq zlib1g-dev libtolua-dev liblua5.1-dev libncurses5-dev libsqlite3-dev libxml2-dev valgrind clang
script:
- s/travis-build
os: os:
- linux - linux
- osx - osx

View File

@ -4,9 +4,8 @@ set -e
ROOT=`pwd` ROOT=`pwd`
SUPP=../share/ubuntu-12_04.supp SUPP=../share/ubuntu-12_04.supp
MACHINE=`uname -m` MACHINE=`uname -m`
[ -z "$CC" ] && [ ! -z `which clang` ] && CC="clang"
[ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc" [ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc"
[ -z "$CC" ] && [ ! -z `which tcc` ] && CC="tcc"
[ -z "$CC" ] && [ ! -z `which cc` ] && CC="cc"
BUILD="$ROOT/build-$MACHINE-$CC-Debug" BUILD="$ROOT/build-$MACHINE-$CC-Debug"
inifile() { inifile() {
@ -20,7 +19,7 @@ fi
build() { build() {
cd $BUILD cd $BUILD
cmake -DCMAKE_MODULE_PATH=$ROOT/cmake/Modules -DCMAKE_BUILD_TYPE=Debug .. cmake -DCMAKE_MODULE_PATH=$ROOT/cmake/Modules -DCMAKE_BUILD_TYPE=Debug ..
make scan-build make
} }
test_valgrind_report () { test_valgrind_report () {

View File

@ -1,4 +1,4 @@
/* /*
+-------------------+ Enno Rehling <enno@eressea.de> +-------------------+ Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de> | Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
| (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de> | (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de>
@ -184,9 +184,9 @@ cr_output_curses(FILE * F, const faction * viewer, const void *obj, objtype_t ty
region *r; region *r;
/* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei /* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei
* Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden. * Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden.
* Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer. * Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer.
* Spezialfälle (besonderes Talent, verursachender Magier usw. werde * Spezialfälle (besonderes Talent, verursachender Magier usw. werde
* bei jedem curse gesondert behandelt. */ * bei jedem curse gesondert behandelt. */
if (typ == TYP_SHIP) { if (typ == TYP_SHIP) {
ship *sh = (ship *)obj; ship *sh = (ship *)obj;
@ -747,8 +747,11 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
static const curse_type *itemcloak_ct = 0; static const curse_type *itemcloak_ct = 0;
static bool init = false; static bool init = false;
item result[MAX_INVENTORY]; item result[MAX_INVENTORY];
const faction *sf;
const char *prefix;
if (fval(u_race(u), RCF_INVISIBLE)) assert(u && u->number);
if (u != NULL || fval(u_race(u), RCF_INVISIBLE))
return; return;
if (!init) { if (!init) {
@ -756,256 +759,253 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
itemcloak_ct = ct_find("itemcloak"); itemcloak_ct = ct_find("itemcloak");
} }
if (itemcloak_ct != NULL) { if (itemcloak_ct != NULL) {
itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); curse * cu = get_curse(u->attribs, itemcloak_ct);
itemcloak = cu && curse_active(cu);
} }
assert(u && u->number);
fprintf(F, "EINHEIT %d\n", u->no); fprintf(F, "EINHEIT %d\n", u->no);
fprintf(F, "\"%s\";Name\n", unit_getname(u)); fprintf(F, "\"%s\";Name\n", unit_getname(u));
str = u_description(u, f->locale); str = u_description(u, f->locale);
if (str) { if (str) {
fprintf(F, "\"%s\";Beschr\n", str); fprintf(F, "\"%s\";Beschr\n", str);
} }
{ /* print faction information */
/* print faction information */ sf = visible_faction(f, u);
const faction *sf = visible_faction(f, u); prefix = raceprefix(u);
const char *prefix = raceprefix(u); if (u->faction == f || omniscient(f)) {
if (u->faction == f || omniscient(f)) { const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction);
const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); const faction *otherfaction =
const faction *otherfaction = a_otherfaction ? get_otherfaction(a_otherfaction) : NULL;
a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; /* my own faction, full info */
/* my own faction, full info */ const attrib *a = NULL;
const attrib *a = NULL; unit *mage;
unit *mage;
if (fval(u, UFL_GROUP)) if (fval(u, UFL_GROUP))
a = a_find(u->attribs, &at_group); a = a_find(u->attribs, &at_group);
if (a != NULL) { if (a != NULL) {
const group *g = (const group *)a->data.v; const group *g = (const group *)a->data.v;
fprintf(F, "%d;gruppe\n", g->gid); fprintf(F, "%d;gruppe\n", g->gid);
} }
fprintf(F, "%d;Partei\n", u->faction->no); fprintf(F, "%d;Partei\n", u->faction->no);
if (sf != u->faction) if (sf != u->faction)
fprintf(F, "%d;Verkleidung\n", sf->no); fprintf(F, "%d;Verkleidung\n", sf->no);
if (fval(u, UFL_ANON_FACTION)) if (fval(u, UFL_ANON_FACTION))
fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION)));
if (otherfaction) { if (otherfaction) {
if (otherfaction != u->faction) { if (otherfaction != u->faction) {
fprintf(F, "%d;Anderepartei\n", otherfaction->no); fprintf(F, "%d;Anderepartei\n", otherfaction->no);
} }
} }
mage = get_familiar_mage(u); mage = get_familiar_mage(u);
if (mage) { if (mage) {
fprintf(F, "%u;familiarmage\n", mage->no); fprintf(F, "%u;familiarmage\n", mage->no);
} }
} }
else { else {
if (fval(u, UFL_ANON_FACTION)) { if (fval(u, UFL_ANON_FACTION)) {
/* faction info is hidden */ /* faction info is hidden */
fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION))); fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION)));
} }
else { else {
const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); const attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction);
const faction *otherfaction = const faction *otherfaction =
a_otherfaction ? get_otherfaction(a_otherfaction) : NULL; a_otherfaction ? get_otherfaction(a_otherfaction) : NULL;
/* other unit. show visible faction, not u->faction */ /* other unit. show visible faction, not u->faction */
fprintf(F, "%d;Partei\n", sf->no); fprintf(F, "%d;Partei\n", sf->no);
if (sf == f) { if (sf == f) {
fprintf(F, "1;Verraeter\n"); fprintf(F, "1;Verraeter\n");
} }
if (a_otherfaction) { if (a_otherfaction) {
if (otherfaction != u->faction) { if (otherfaction != u->faction) {
if (alliedunit(u, f, HELP_FSTEALTH)) { if (alliedunit(u, f, HELP_FSTEALTH)) {
fprintf(F, "%d;Anderepartei\n", otherfaction->no); fprintf(F, "%d;Anderepartei\n", otherfaction->no);
} }
} }
} }
} }
} }
if (prefix) { if (prefix) {
prefix = mkname("prefix", prefix); prefix = mkname("prefix", prefix);
fprintf(F, "\"%s\";typprefix\n", translate(prefix, LOC(f->locale, fprintf(F, "\"%s\";typprefix\n", translate(prefix, LOC(f->locale,
prefix))); prefix)));
} }
} if (u->faction != f && a_fshidden
if (u->faction != f && a_fshidden && a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) {
&& a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) { fprintf(F, "-1;Anzahl\n");
fprintf(F, "-1;Anzahl\n"); }
} else {
else { fprintf(F, "%d;Anzahl\n", u->number);
fprintf(F, "%d;Anzahl\n", u->number); }
}
pzTmp = get_racename(u->attribs); pzTmp = get_racename(u->attribs);
if (pzTmp) { if (pzTmp) {
fprintf(F, "\"%s\";Typ\n", pzTmp); fprintf(F, "\"%s\";Typ\n", pzTmp);
if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) {
const char *zRace = rc_name_s(u_race(u), NAME_PLURAL); const char *zRace = rc_name_s(u_race(u), NAME_PLURAL);
fprintf(F, "\"%s\";wahrerTyp\n", fprintf(F, "\"%s\";wahrerTyp\n",
translate(zRace, LOC(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
} }
} }
else { else {
const race *irace = u_irace(u); const race *irace = u_irace(u);
const char *zRace = rc_name_s(irace, NAME_PLURAL); const char *zRace = rc_name_s(irace, NAME_PLURAL);
fprintf(F, "\"%s\";Typ\n", fprintf(F, "\"%s\";Typ\n",
translate(zRace, LOC(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
if (u->faction == f && irace != u_race(u)) { if (u->faction == f && irace != u_race(u)) {
assert(skill_enabled(SK_STEALTH) assert(skill_enabled(SK_STEALTH)
|| !"we're resetting this on load, so.. ircase should never be used"); || !"we're resetting this on load, so.. ircase should never be used");
zRace = rc_name_s(u_race(u), NAME_PLURAL); zRace = rc_name_s(u_race(u), NAME_PLURAL);
fprintf(F, "\"%s\";wahrerTyp\n", fprintf(F, "\"%s\";wahrerTyp\n",
translate(zRace, LOC(f->locale, zRace))); translate(zRace, LOC(f->locale, zRace)));
} }
} }
if (u->building) { if (u->building) {
assert(u->building->region); assert(u->building->region);
fprintf(F, "%d;Burg\n", u->building->no); fprintf(F, "%d;Burg\n", u->building->no);
} }
if (u->ship) { if (u->ship) {
assert(u->ship->region); assert(u->ship->region);
fprintf(F, "%d;Schiff\n", u->ship->no); fprintf(F, "%d;Schiff\n", u->ship->no);
} }
if (is_guard(u, GUARD_ALL) != 0) { if (is_guard(u, GUARD_ALL) != 0) {
fprintf(F, "%d;bewacht\n", 1); fprintf(F, "%d;bewacht\n", 1);
} }
if ((b = usiege(u)) != NULL) { if ((b = usiege(u)) != NULL) {
fprintf(F, "%d;belagert\n", b->no); fprintf(F, "%d;belagert\n", b->no);
} }
/* additional information for own units */ /* additional information for own units */
if (u->faction == f || omniscient(f)) { if (u->faction == f || omniscient(f)) {
order *ord; order *ord;
const char *xc; const char *xc;
const char *c; const char *c;
int i; int i;
sc_mage *mage; sc_mage *mage;
i = ualias(u); i = ualias(u);
if (i > 0) if (i > 0)
fprintf(F, "%d;temp\n", i); fprintf(F, "%d;temp\n", i);
else if (i < 0) else if (i < 0)
fprintf(F, "%d;alias\n", -i); fprintf(F, "%d;alias\n", -i);
i = get_money(u); i = get_money(u);
fprintf(F, "%d;Kampfstatus\n", u->status); fprintf(F, "%d;Kampfstatus\n", u->status);
fprintf(F, "%d;weight\n", weight(u)); fprintf(F, "%d;weight\n", weight(u));
if (fval(u, UFL_NOAID)) { if (fval(u, UFL_NOAID)) {
fputs("1;unaided\n", F); fputs("1;unaided\n", F);
} }
if (fval(u, UFL_STEALTH)) { if (fval(u, UFL_STEALTH)) {
i = u_geteffstealth(u); i = u_geteffstealth(u);
if (i >= 0) { if (i >= 0) {
fprintf(F, "%d;Tarnung\n", i); fprintf(F, "%d;Tarnung\n", i);
} }
} }
xc = uprivate(u); xc = uprivate(u);
if (xc) { if (xc) {
fprintf(F, "\"%s\";privat\n", xc); fprintf(F, "\"%s\";privat\n", xc);
} }
c = hp_status(u); c = hp_status(u);
if (c && *c && (u->faction == f || omniscient(f))) { if (c && *c && (u->faction == f || omniscient(f))) {
fprintf(F, "\"%s\";hp\n", translate(c, fprintf(F, "\"%s\";hp\n", translate(c,
LOC(u->faction->locale, c))); LOC(u->faction->locale, c)));
} }
if (fval(u, UFL_HERO)) { if (fval(u, UFL_HERO)) {
fputs("1;hero\n", F); fputs("1;hero\n", F);
} }
if (fval(u, UFL_HUNGER) && (u->faction == f)) { if (fval(u, UFL_HUNGER) && (u->faction == f)) {
fputs("1;hunger\n", F); fputs("1;hunger\n", F);
} }
if (is_mage(u)) { if (is_mage(u)) {
fprintf(F, "%d;Aura\n", get_spellpoints(u)); fprintf(F, "%d;Aura\n", get_spellpoints(u));
fprintf(F, "%d;Auramax\n", max_spellpoints(u->region, u)); fprintf(F, "%d;Auramax\n", max_spellpoints(u->region, u));
} }
/* default commands */ /* default commands */
fprintf(F, "COMMANDS\n"); fprintf(F, "COMMANDS\n");
for (ord = u->old_orders; ord; ord = ord->next) { for (ord = u->old_orders; ord; ord = ord->next) {
/* this new order will replace the old defaults */ /* this new order will replace the old defaults */
if (is_persistent(ord)) { if (is_persistent(ord)) {
fwriteorder(F, ord, f->locale, true); fwriteorder(F, ord, f->locale, true);
fputc('\n', F); fputc('\n', F);
} }
} }
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (u->old_orders && is_repeated(ord)) if (u->old_orders && is_repeated(ord))
continue; /* unit has defaults */ continue; /* unit has defaults */
if (is_persistent(ord)) { if (is_persistent(ord)) {
fwriteorder(F, ord, f->locale, true); fwriteorder(F, ord, f->locale, true);
fputc('\n', F); fputc('\n', F);
} }
} }
/* talents */ /* talents */
pr = 0; pr = 0;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
if (sv->level > 0) { if (sv->level > 0) {
skill_t sk = sv->id; skill_t sk = sv->id;
int esk = eff_skill(u, sk, r); int esk = eff_skill(u, sk, r);
if (!pr) { if (!pr) {
pr = 1; pr = 1;
fprintf(F, "TALENTE\n"); fprintf(F, "TALENTE\n");
} }
fprintf(F, "%d %d;%s\n", u->number * level_days(sv->level), esk, fprintf(F, "%d %d;%s\n", u->number * level_days(sv->level), esk,
translate(mkname("skill", skillnames[sk]), skillname(sk, translate(mkname("skill", skillnames[sk]), skillname(sk,
f->locale))); f->locale)));
} }
} }
/* spells that this unit can cast */ /* spells that this unit can cast */
mage = get_mage(u); mage = get_mage(u);
if (mage) { if (mage) {
int i, maxlevel = effskill(u, SK_MAGIC); int i, maxlevel = effskill(u, SK_MAGIC);
cr_output_spells(F, u, maxlevel); cr_output_spells(F, u, maxlevel);
for (i = 0; i != MAXCOMBATSPELLS; ++i) { for (i = 0; i != MAXCOMBATSPELLS; ++i) {
const spell *sp = mage->combatspells[i].sp; const spell *sp = mage->combatspells[i].sp;
if (sp) { if (sp) {
const char *name = const char *name =
translate(mkname("spell", sp->sname), spell_name(sp, translate(mkname("spell", sp->sname), spell_name(sp,
f->locale)); f->locale));
fprintf(F, "KAMPFZAUBER %d\n", i); fprintf(F, "KAMPFZAUBER %d\n", i);
fprintf(F, "\"%s\";name\n", name); fprintf(F, "\"%s\";name\n", name);
fprintf(F, "%d;level\n", mage->combatspells[i].level); fprintf(F, "%d;level\n", mage->combatspells[i].level);
} }
} }
} }
} }
/* items */ /* items */
pr = 0; pr = 0;
if (f == u->faction || omniscient(f)) { if (f == u->faction || omniscient(f)) {
show = u->items; show = u->items;
} }
else if (!itemcloak && mode >= see_unit && !(a_fshidden else if (!itemcloak && mode >= see_unit && !(a_fshidden
&& a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) { && a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) {
int n = report_items(u->items, result, MAX_INVENTORY, u, f); int n = report_items(u->items, result, MAX_INVENTORY, u, f);
assert(n >= 0); assert(n >= 0);
if (n > 0) if (n > 0)
show = result; show = result;
else else
show = NULL; show = NULL;
} }
else { else {
show = NULL; show = NULL;
} }
lasttype = NULL; lasttype = NULL;
for (itm = show; itm; itm = itm->next) { for (itm = show; itm; itm = itm->next) {
const char *ic; const char *ic;
int in; int in;
assert(itm->type != lasttype assert(itm->type != lasttype
|| !"error: list contains two objects of the same item"); || !"error: list contains two objects of the same item");
report_item(u, itm, f, NULL, &ic, &in, true); report_item(u, itm, f, NULL, &ic, &in, true);
if (in == 0) if (in == 0)
continue; continue;
if (!pr) { if (!pr) {
pr = 1; pr = 1;
fputs("GEGENSTAENDE\n", F); fputs("GEGENSTAENDE\n", F);
} }
fprintf(F, "%d;%s\n", in, translate(ic, LOC(f->locale, ic))); fprintf(F, "%d;%s\n", in, translate(ic, LOC(f->locale, ic)));
} }
cr_output_curses(F, f, u, TYP_UNIT); cr_output_curses(F, f, u, TYP_UNIT);
} }
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
@ -1037,18 +1037,6 @@ static void show_alliances_cr(FILE * F, const faction * f)
} }
} }
/* prints all visible spells in a region */
static void show_active_spells(const region * r)
{
char fogwall[MAXDIRECTIONS];
#ifdef TODO /* alte Regionszauberanzeigen umstellen */
unit *u;
int env = 0;
#endif
memset(fogwall, 0, sizeof(char) * MAXDIRECTIONS);
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/* this is a copy of laws.c->find_address output changed. */ /* this is a copy of laws.c->find_address output changed. */
@ -1312,6 +1300,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
if (r->display && r->display[0]) if (r->display && r->display[0])
fprintf(F, "\"%s\";Beschr\n", r->display); fprintf(F, "\"%s\";Beschr\n", r->display);
if (fval(r->terrain, LAND_REGION)) { if (fval(r->terrain, LAND_REGION)) {
assert(r->land);
fprintf(F, "%d;Bauern\n", rpeasants(r)); fprintf(F, "%d;Bauern\n", rpeasants(r));
if (fval(r, RF_ORCIFIED)) { if (fval(r, RF_ORCIFIED)) {
fprintf(F, "1;Verorkt\n"); fprintf(F, "1;Verorkt\n");
@ -1342,7 +1331,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
fputs("1;mourning\n", F); fputs("1;mourning\n", F);
} }
} }
if (r->land->ownership) { if (r->land && r->land->ownership) {
fprintf(F, "%d;morale\n", r->land->morale); fprintf(F, "%d;morale\n", r->land->morale);
} }
} }
@ -1412,7 +1401,6 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
} }
/* describe both passed and inhabited regions */ /* describe both passed and inhabited regions */
show_active_spells(r);
if (fval(r, RF_TRAVELUNIT)) { if (fval(r, RF_TRAVELUNIT)) {
bool seeunits = false, seeships = false; bool seeunits = false, seeships = false;
const attrib *ru; const attrib *ru;

View File

@ -1,4 +1,4 @@
/* /*
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de> +-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea.de> | | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de> | Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
@ -299,7 +299,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
error = 96; error = 96;
} }
else if (u->faction != u2->faction) { else if (u->faction != u2->faction) {
if (maxt>=0 && u2->faction->newbies + n > maxt) { if (maxt >= 0 && u2->faction->newbies + n > maxt) {
error = 129; error = 129;
} }
else if (u_race(u) != u2->faction->race) { else if (u_race(u) != u2->faction->race) {
@ -332,7 +332,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY))
k += n; k += n;
/* Wenn Parteigrenzen überschritten werden */ /* Wenn Parteigrenzen überschritten werden */
if (u2->faction != u->faction) if (u2->faction != u->faction)
k += n; k += n;
@ -354,14 +354,14 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord)
freset(u2, UFL_HERO); freset(u2, UFL_HERO);
} }
/* Einheiten von Schiffen können nicht NACH in von /* Einheiten von Schiffen können nicht NACH in von
* Nicht-alliierten bewachten Regionen ausführen */ * Nicht-alliierten bewachten Regionen ausführen */
sh = leftship(u); sh = leftship(u);
if (sh) { if (sh) {
set_leftship(u2, sh); set_leftship(u2, sh);
} }
transfermen(u, u2, n); transfermen(u, u2, n);
if (maxt>=0 && u->faction != u2->faction) { if (maxt >= 0 && u->faction != u2->faction) {
u2->faction->newbies += n; u2->faction->newbies += n;
} }
} }
@ -400,15 +400,15 @@ message * disband_men(int n, unit * u, struct order *ord) {
void give_unit(unit * u, unit * u2, order * ord) void give_unit(unit * u, unit * u2, order * ord)
{ {
region *r = u->region;
int maxt = max_transfers(); int maxt = max_transfers();
assert(u);
if (!rule_transfermen() && u->faction != u2->faction) { if (!rule_transfermen() && u->faction != u2->faction) {
cmistake(u, ord, 74, MSG_COMMERCE); cmistake(u, ord, 74, MSG_COMMERCE);
return; return;
} }
if (u && unit_has_cursed_item(u)) { if (unit_has_cursed_item(u)) {
cmistake(u, ord, 78, MSG_COMMERCE); cmistake(u, ord, 78, MSG_COMMERCE);
return; return;
} }
@ -423,6 +423,7 @@ void give_unit(unit * u, unit * u2, order * ord)
} }
if (u2 == NULL) { if (u2 == NULL) {
region *r = u->region;
message *msg; message *msg;
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
msg = disband_men(u->number, u, ord); msg = disband_men(u->number, u, ord);
@ -518,7 +519,7 @@ void give_unit(unit * u, unit * u2, order * ord)
} }
bool can_give_to(unit *u, unit *u2) { bool can_give_to(unit *u, unit *u2) {
/* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */
if (!u2) { if (!u2) {
return false; return false;
} }
@ -613,7 +614,7 @@ void give_cmd(unit * u, order * ord)
item *itm = *itmp; item *itm = *itmp;
const item_type *itype = itm->type; const item_type *itype = itm->type;
if (fval(itype, ITF_HERB) && itm->number > 0) { if (fval(itype, ITF_HERB) && itm->number > 0) {
/* give_item ändert im fall,das man alles übergibt, die /* give_item ändert im fall,das man alles übergibt, die
* item-liste der unit, darum continue vor pointerumsetzten */ * item-liste der unit, darum continue vor pointerumsetzten */
if (give_item(itm->number, itm->type, u, u2, ord) == 0) { if (give_item(itm->number, itm->type, u, u2, ord) == 0) {
given = true; given = true;
@ -669,8 +670,8 @@ void give_cmd(unit * u, order * ord)
return; return;
} }
/* für alle items einmal prüfen, ob wir mehr als von diesem Typ /* für alle items einmal prüfen, ob wir mehr als von diesem Typ
* reserviert ist besitzen und diesen Teil dann übergeben */ * reserviert ist besitzen und diesen Teil dann übergeben */
if (u->items) { if (u->items) {
item **itmp = &u->items; item **itmp = &u->items;
while (*itmp) { while (*itmp) {

View File

@ -249,6 +249,8 @@ static void paint_map(window * wnd, const state * st)
int cols = getmaxx(win); int cols = getmaxx(win);
int vx, vy; int vx, vy;
assert(st);
if (!st) return;
lines = lines / THEIGHT; lines = lines / THEIGHT;
cols = cols / TWIDTH; cols = cols / TWIDTH;
for (vy = 0; vy != lines; ++vy) { for (vy = 0; vy != lines; ++vy) {
@ -260,11 +262,9 @@ static void paint_map(window * wnd, const state * st)
int xp = vx * TWIDTH + (vy & 1) * TWIDTH / 2; int xp = vx * TWIDTH + (vy & 1) * TWIDTH / 2;
int nx, ny; int nx, ny;
if (mr) { if (mr) {
if (st) { cnormalize(&mr->coord, &nx, &ny);
cnormalize(&mr->coord, &nx, &ny); if (tagged_region(st->selected, nx, ny)) {
if (tagged_region(st->selected, nx, ny)) { attr |= A_REVERSE;
attr |= A_REVERSE;
}
} }
if (mr->r && (mr->r->flags & RF_MAPPER_HIGHLIGHT)) if (mr->r && (mr->r->flags & RF_MAPPER_HIGHLIGHT))
hl = 1; hl = 1;

View File

@ -1,4 +1,4 @@
#include "reports.h" #include "reports.h"
#include "jsreport.h" #include "jsreport.h"
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/terrain.h> #include <kernel/terrain.h>
@ -74,7 +74,7 @@ static int report_json(const char *filename, report_context * ctx, const char *c
} }
return 0; return 0;
} }
return ferror(F); return -1;
} }
return 0; return 0;
} }

View File

@ -307,19 +307,23 @@ const curse_type *ct_find(const char *c)
{ {
unsigned int hash = tolower(c[0]); unsigned int hash = tolower(c[0]);
quicklist *ctl = cursetypes[hash]; quicklist *ctl = cursetypes[hash];
int qi;
for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { if (ctl) {
curse_type *type = (curse_type *)ql_get(ctl, qi); size_t c_len = strlen(c);
int qi;
if (strcmp(c, type->cname) == 0) { for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) {
return type; curse_type *type = (curse_type *)ql_get(ctl, qi);
}
else { if (strcmp(c, type->cname) == 0) {
size_t k = _min(strlen(c), strlen(type->cname));
if (!_memicmp(c, type->cname, k)) {
return type; return type;
} }
else {
size_t k = _min(c_len, strlen(type->cname));
if (!_memicmp(c, type->cname, k)) {
return type;
}
}
} }
} }
return NULL; return NULL;

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -332,10 +332,15 @@ potion_type *new_potiontype(item_type * itype, int level)
} }
void it_set_appearance(item_type *itype, const char *appearance) { void it_set_appearance(item_type *itype, const char *appearance) {
assert(itype && itype->rtype); assert(itype);
itype->_appearance[0] = _strdup(appearance); assert(itype->rtype);
itype->_appearance[1] = appearance ? if (appearance) {
strcat(strcpy((char *)malloc(strlen((char *)appearance) + 3), (char *)appearance), "_p") : 0; itype->_appearance[0] = _strdup(appearance);
itype->_appearance[1] = strcat(strcpy((char *)malloc(strlen((char *)appearance) + 3), (char *)appearance), "_p");
} else {
itype->_appearance[0] = 0;
itype->_appearance[1] = 0;
}
} }
const resource_type *item2resource(const item_type * itype) const resource_type *item2resource(const item_type * itype)

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -305,7 +305,7 @@ void free_messagelist(message_list * msgs)
message *add_message(message_list ** pm, message * m) message *add_message(message_list ** pm, message * m)
{ {
assert(m->type); assert(m && m->type);
if (!lomem && m != NULL) { if (!lomem && m != NULL) {
struct mlist *mnew = malloc(sizeof(struct mlist)); struct mlist *mnew = malloc(sizeof(struct mlist));
if (*pm == NULL) { if (*pm == NULL) {

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -200,7 +200,7 @@ static unit *unitorders(FILE * F, int enc, struct faction *f)
} }
} }
} }
/* Nun wird der Befehl erzeut und eingehängt */ /* Nun wird der Befehl erzeut und eingehängt */
*ordp = parse_order(s, u->faction->locale); *ordp = parse_order(s, u->faction->locale);
if (*ordp) { if (*ordp) {
ordp = &(*ordp)->next; ordp = &(*ordp)->next;
@ -233,8 +233,8 @@ static faction *factionorders(void)
f->no, pass)); f->no, pass));
return 0; return 0;
} }
/* Die Partei hat sich zumindest gemeldet, so daß sie noch /* Die Partei hat sich zumindest gemeldet, so daß sie noch
* nicht als untätig gilt */ * nicht als untätig gilt */
/* TODO: +1 ist ein Workaround, weil cturn erst in process_orders /* TODO: +1 ist ein Workaround, weil cturn erst in process_orders
* incrementiert wird. */ * incrementiert wird. */
@ -308,9 +308,9 @@ int readorders(const char *filename)
/* Falls in unitorders() abgebrochen wird, steht dort entweder eine neue /* Falls in unitorders() abgebrochen wird, steht dort entweder eine neue
* Partei, eine neue Einheit oder das File-Ende. Das switch() wird erneut * Partei, eine neue Einheit oder das File-Ende. Das switch() wird erneut
* durchlaufen, und die entsprechende Funktion aufgerufen. Man darf buf * durchlaufen, und die entsprechende Funktion aufgerufen. Man darf buf
* auf alle Fälle nicht überschreiben! Bei allen anderen Einträgen hier * auf alle Fälle nicht überschreiben! Bei allen anderen Einträgen hier
* muß buf erneut gefüllt werden, da die betreffende Information in nur * muß buf erneut gefüllt werden, da die betreffende Information in nur
* einer Zeile steht, und nun die nächste gelesen werden muß. */ * einer Zeile steht, und nun die nächste gelesen werden muß. */
case P_NEXT: case P_NEXT:
f = NULL; f = NULL;
@ -331,7 +331,7 @@ int readorders(const char *filename)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* #define INNER_WORLD */ /* #define INNER_WORLD */
/* fürs debuggen nur den inneren Teil der Welt laden */ /* fürs debuggen nur den inneren Teil der Welt laden */
/* -9;-27;-1;-19;Sumpfloch */ /* -9;-27;-1;-19;Sumpfloch */
int inner_world(region * r) int inner_world(region * r)
{ {
@ -978,6 +978,9 @@ static region *readregion(struct gamedata *data, int x, int y)
void writeregion(struct gamedata *data, const region * r) void writeregion(struct gamedata *data, const region * r)
{ {
assert(r);
assert(data);
WRITE_INT(data->store, r->uid); WRITE_INT(data->store, r->uid);
WRITE_STR(data->store, region_getinfo(r)); WRITE_STR(data->store, region_getinfo(r));
WRITE_TOK(data->store, r->terrain->_name); WRITE_TOK(data->store, r->terrain->_name);
@ -988,6 +991,8 @@ void writeregion(struct gamedata *data, const region * r)
const item_type *rht; const item_type *rht;
struct demand *demand; struct demand *demand;
rawmaterial *res = r->resources; rawmaterial *res = r->resources;
assert(r->land);
WRITE_STR(data->store, (const char *)r->land->name); WRITE_STR(data->store, (const char *)r->land->name);
assert(rtrees(r, 0) >= 0); assert(rtrees(r, 0) >= 0);
assert(rtrees(r, 1) >= 0); assert(rtrees(r, 1) >= 0);
@ -1018,11 +1023,9 @@ void writeregion(struct gamedata *data, const region * r)
WRITE_INT(data->store, rherbs(r)); WRITE_INT(data->store, rherbs(r));
WRITE_INT(data->store, rpeasants(r)); WRITE_INT(data->store, rpeasants(r));
WRITE_INT(data->store, rmoney(r)); WRITE_INT(data->store, rmoney(r));
if (r->land) { for (demand = r->land->demands; demand; demand = demand->next) {
for (demand = r->land->demands; demand; demand = demand->next) { WRITE_TOK(data->store, resourcename(demand->type->itype->rtype, 0));
WRITE_TOK(data->store, resourcename(demand->type->itype->rtype, 0)); WRITE_INT(data->store, demand->value);
WRITE_INT(data->store, demand->value);
}
} }
WRITE_TOK(data->store, "end"); WRITE_TOK(data->store, "end");
write_items(data->store, r->land->items); write_items(data->store, r->land->items);

View File

@ -435,13 +435,25 @@ void write_ship_reference(const struct ship *sh, struct storage *store)
void ship_setname(ship * self, const char *name) void ship_setname(ship * self, const char *name)
{ {
free(self->name); free(self->name);
if (name) self->name = name ? _strdup(name) : 0;
self->name = _strdup(name);
else
self->name = NULL;
} }
const char *ship_getname(const ship * self) const char *ship_getname(const ship * self)
{ {
return self->name; return self->name;
} }
unit *get_captain(const ship * sh)
{
const region *r = sh->region;
unit *u;
for (u = r->units; u; u = u->next) {
if (u->ship == sh && u->number
&& eff_skill(u, SK_SAILING, r) >= sh->type->cptskill)
return u;
}
return NULL;
}

View File

@ -121,9 +121,10 @@ extern "C" {
extern void free_ship(struct ship *s); extern void free_ship(struct ship *s);
extern void free_ships(void); extern void free_ships(void);
extern const char *ship_getname(const struct ship *self); const char *ship_getname(const struct ship *self);
extern void ship_setname(struct ship *self, const char *name); void ship_setname(struct ship *self, const char *name);
int shipspeed(const struct ship *sh, const struct unit *u); int shipspeed(const struct ship *sh, const struct unit *u);
struct unit *get_captain(const struct ship *sh);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2014, Copyright (c) 1998-2014,
Enno Rehling <enno@eressea.de> Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
@ -165,7 +165,7 @@ static void live(region * r)
while (*up) { while (*up) {
unit *u = *up; unit *u = *up;
/* IUW: age_unit() kann u loeschen, u->next ist dann /* IUW: age_unit() kann u loeschen, u->next ist dann
* undefiniert, also muessen wir hier schon das nächste * undefiniert, also muessen wir hier schon das nächste
* Element bestimmen */ * Element bestimmen */
int effect = get_effect(u, oldpotiontype[P_FOOL]); int effect = get_effect(u, oldpotiontype[P_FOOL]);
@ -183,7 +183,7 @@ static void live(region * r)
reduce_skill(u, sb, weeks); reduce_skill(u, sb, weeks);
ADDMSG(&u->faction->msgs, msg_message("dumbeffect", ADDMSG(&u->faction->msgs, msg_message("dumbeffect",
"unit weeks skill", u, weeks, (skill_t)sb->id)); "unit weeks skill", u, weeks, (skill_t)sb->id));
} /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */ } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */
change_effect(u, oldpotiontype[P_FOOL], -effect); change_effect(u, oldpotiontype[P_FOOL], -effect);
} }
age_unit(r, u); age_unit(r, u);
@ -325,16 +325,16 @@ static void peasants(region * r)
peasants += births + luck; peasants += births + luck;
} }
/* Alle werden satt, oder halt soviele für die es auch Geld gibt */ /* Alle werden satt, oder halt soviele für die es auch Geld gibt */
satiated = _min(peasants, money / maintenance_cost(NULL)); satiated = _min(peasants, money / maintenance_cost(NULL));
rsetmoney(r, money - satiated * maintenance_cost(NULL)); rsetmoney(r, money - satiated * maintenance_cost(NULL));
/* Von denjenigen, die nicht satt geworden sind, verhungert der /* Von denjenigen, die nicht satt geworden sind, verhungert der
* Großteil. dead kann nie größer als rpeasants(r) - satiated werden, * Großteil. dead kann nie größer als rpeasants(r) - satiated werden,
* so dass rpeasants(r) >= 0 bleiben muß. */ * so dass rpeasants(r) >= 0 bleiben muß. */
/* Es verhungert maximal die unterernährten Bevölkerung. */ /* Es verhungert maximal die unterernährten Bevölkerung. */
n = _min(peasants - satiated, rpeasants(r)); n = _min(peasants - satiated, rpeasants(r));
dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE); dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE);
@ -399,10 +399,10 @@ static void migrate(region * r)
rsethorses(r, rhorses(r) + m->horses); rsethorses(r, rhorses(r) + m->horses);
/* Was macht das denn hier? /* Was macht das denn hier?
* Baumwanderung wird in trees() gemacht. * Baumwanderung wird in trees() gemacht.
* wer fragt das? Die Baumwanderung war abhängig von der * wer fragt das? Die Baumwanderung war abhängig von der
* Auswertungsreihenfolge der regionen, * Auswertungsreihenfolge der regionen,
* das hatte ich geändert. jemand hat es wieder gelöscht, toll. * das hatte ich geändert. jemand hat es wieder gelöscht, toll.
* ich habe es wieder aktiviert, muß getestet werden. * ich habe es wieder aktiviert, muß getestet werden.
*/ */
*hp = m->next; *hp = m->next;
m->next = free_migrants; m->next = free_migrants;
@ -442,8 +442,8 @@ static void horses(region * r)
/* Pferde wandern in Nachbarregionen. /* Pferde wandern in Nachbarregionen.
* Falls die Nachbarregion noch berechnet * Falls die Nachbarregion noch berechnet
* werden muß, wird eine migration-Struktur gebildet, * werden muß, wird eine migration-Struktur gebildet,
* die dann erst in die Berechnung der Nachbarstruktur einfließt. * die dann erst in die Berechnung der Nachbarstruktur einfließt.
*/ */
for (n = 0; n != MAXDIRECTIONS; n++) { for (n = 0; n != MAXDIRECTIONS; n++) {
@ -457,7 +457,7 @@ static void horses(region * r)
else { else {
migration *nb; migration *nb;
/* haben wir die Migration schonmal benutzt? /* haben wir die Migration schonmal benutzt?
* wenn nicht, müssen wir sie suchen. * wenn nicht, müssen wir sie suchen.
* Wandernde Pferde vermehren sich nicht. * Wandernde Pferde vermehren sich nicht.
*/ */
nb = get_migrants(r2); nb = get_migrants(r2);
@ -553,11 +553,11 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
a = a_find(r->attribs, &at_germs); a = a_find(r->attribs, &at_germs);
if (a && last_weeks_season == SEASON_SPRING) { if (a && last_weeks_season == SEASON_SPRING) {
/* ungekeimte Samen bleiben erhalten, Sprößlinge wachsen */ /* ungekeimte Samen bleiben erhalten, Sprößlinge wachsen */
sprout = _min(a->data.sa[1], rtrees(r, 1)); sprout = _min(a->data.sa[1], rtrees(r, 1));
/* aus dem gesamt Sprößlingepool abziehen */ /* aus dem gesamt Sprößlingepool abziehen */
rsettrees(r, 1, rtrees(r, 1) - sprout); rsettrees(r, 1, rtrees(r, 1) - sprout);
/* zu den Bäumen hinzufügen */ /* zu den Bäumen hinzufügen */
rsettrees(r, 2, rtrees(r, 2) + sprout); rsettrees(r, 2, rtrees(r, 2) + sprout);
a_removeall(&r->attribs, &at_germs); a_removeall(&r->attribs, &at_germs);
@ -573,7 +573,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
return; return;
/* Grundchance 1.0% */ /* Grundchance 1.0% */
/* Jeder Elf in der Region erhöht die Chance marginal */ /* Jeder Elf in der Region erhöht die Chance marginal */
elves = _min(elves, production(r) / 8); elves = _min(elves, production(r) / 8);
if (elves) { if (elves) {
seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY); seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY);
@ -594,19 +594,19 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
} }
} }
/* Bäume breiten sich in Nachbarregionen aus. */ /* Bäume breiten sich in Nachbarregionen aus. */
/* Gesamtzahl der Samen: /* Gesamtzahl der Samen:
* bis zu 6% (FORESTGROWTH*3) der Bäume samen in die Nachbarregionen */ * bis zu 6% (FORESTGROWTH*3) der Bäume samen in die Nachbarregionen */
seeds = (rtrees(r, 2) * FORESTGROWTH * 3) / 1000000; seeds = (rtrees(r, 2) * FORESTGROWTH * 3) / 1000000;
for (d = 0; d != MAXDIRECTIONS; ++d) { for (d = 0; d != MAXDIRECTIONS; ++d) {
region *r2 = rconnect(r, d); region *r2 = rconnect(r, d);
if (r2 && fval(r2->terrain, LAND_REGION) && r2->terrain->size) { if (r2 && fval(r2->terrain, LAND_REGION) && r2->terrain->size) {
/* Eine Landregion, wir versuchen Samen zu verteilen: /* Eine Landregion, wir versuchen Samen zu verteilen:
* Die Chance, das Samen ein Stück Boden finden, in dem sie * Die Chance, das Samen ein Stück Boden finden, in dem sie
* keimen können, hängt von der Bewuchsdichte und der * keimen können, hängt von der Bewuchsdichte und der
* verfügbaren Fläche ab. In Gletschern gibt es weniger * verfügbaren Fläche ab. In Gletschern gibt es weniger
* Möglichkeiten als in Ebenen. */ * Möglichkeiten als in Ebenen. */
sprout = 0; sprout = 0;
seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size; seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size;
for (i = 0; i < seeds / MAXDIRECTIONS; i++) { for (i = 0; i < seeds / MAXDIRECTIONS; i++) {
@ -623,8 +623,8 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0))
return; return;
/* in at_germs merken uns die Zahl der Samen und Sprößlinge, die /* in at_germs merken uns die Zahl der Samen und Sprößlinge, die
* dieses Jahr älter werden dürfen, damit nicht ein Same im selben * dieses Jahr älter werden dürfen, damit nicht ein Same im selben
* Zyklus zum Baum werden kann */ * Zyklus zum Baum werden kann */
a = a_find(r->attribs, &at_germs); a = a_find(r->attribs, &at_germs);
if (!a) { if (!a) {
@ -632,13 +632,13 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
a->data.sa[0] = (short)rtrees(r, 0); a->data.sa[0] = (short)rtrees(r, 0);
a->data.sa[1] = (short)rtrees(r, 1); a->data.sa[1] = (short)rtrees(r, 1);
} }
/* wir haben 6 Wochen zum wachsen, jeder Same/Sproß hat 18% Chance /* wir haben 6 Wochen zum wachsen, jeder Same/Sproß hat 18% Chance
* zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */ * zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */
growth = 1800; growth = 1800;
/* Samenwachstum */ /* Samenwachstum */
/* Raubbau abfangen, es dürfen nie mehr Samen wachsen, als aktuell /* Raubbau abfangen, es dürfen nie mehr Samen wachsen, als aktuell
* in der Region sind */ * in der Region sind */
seeds = _min(a->data.sa[0], rtrees(r, 0)); seeds = _min(a->data.sa[0], rtrees(r, 0));
sprout = 0; sprout = 0;
@ -651,15 +651,15 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
a->data.sa[0] = (short)(seeds - sprout); a->data.sa[0] = (short)(seeds - sprout);
/* aus dem gesamt Samenpool abziehen */ /* aus dem gesamt Samenpool abziehen */
rsettrees(r, 0, rtrees(r, 0) - sprout); rsettrees(r, 0, rtrees(r, 0) - sprout);
/* zu den Sprößlinge hinzufügen */ /* zu den Sprößlinge hinzufügen */
rsettrees(r, 1, rtrees(r, 1) + sprout); rsettrees(r, 1, rtrees(r, 1) + sprout);
/* Baumwachstum */ /* Baumwachstum */
/* hier gehen wir davon aus, das Jungbäume nicht ohne weiteres aus /* hier gehen wir davon aus, das Jungbäume nicht ohne weiteres aus
* der Region entfernt werden können, da Jungbäume in der gleichen * der Region entfernt werden können, da Jungbäume in der gleichen
* Runde nachwachsen, wir also nicht mehr zwischen diesjährigen und * Runde nachwachsen, wir also nicht mehr zwischen diesjährigen und
* 'alten' Jungbäumen unterscheiden könnten */ * 'alten' Jungbäumen unterscheiden könnten */
sprout = _min(a->data.sa[1], rtrees(r, 1)); sprout = _min(a->data.sa[1], rtrees(r, 1));
grownup_trees = 0; grownup_trees = 0;
@ -667,11 +667,11 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
if (rng_int() % 10000 < growth) if (rng_int() % 10000 < growth)
grownup_trees++; grownup_trees++;
} }
/* aus dem Sprößlingepool dieses Jahres abziehen */ /* aus dem Sprößlingepool dieses Jahres abziehen */
a->data.sa[1] = (short)(sprout - grownup_trees); a->data.sa[1] = (short)(sprout - grownup_trees);
/* aus dem gesamt Sprößlingepool abziehen */ /* aus dem gesamt Sprößlingepool abziehen */
rsettrees(r, 1, rtrees(r, 1) - grownup_trees); rsettrees(r, 1, rtrees(r, 1) - grownup_trees);
/* zu den Bäumen hinzufügen */ /* zu den Bäumen hinzufügen */
rsettrees(r, 2, rtrees(r, 2) + grownup_trees); rsettrees(r, 2, rtrees(r, 2) + grownup_trees);
} }
} }
@ -679,10 +679,10 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
static void static void
growing_herbs(region * r, const int current_season, const int last_weeks_season) growing_herbs(region * r, const int current_season, const int last_weeks_season)
{ {
/* Jetzt die Kräutervermehrung. Vermehrt wird logistisch: /* Jetzt die Kräutervermehrung. Vermehrt wird logistisch:
* *
* Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene * Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene
* Kräuter))% sich zu vermehren. */ * Kräuter))% sich zu vermehren. */
if (current_season != SEASON_WINTER) { if (current_season != SEASON_WINTER) {
int i; int i;
for (i = rherbs(r); i > 0; i--) { for (i = rherbs(r); i > 0; i--) {
@ -1098,7 +1098,7 @@ int enter_building(unit * u, order * ord, int id, bool report)
region *r = u->region; region *r = u->region;
building *b; building *b;
/* Schwimmer können keine Gebäude betreten, außer diese sind /* Schwimmer können keine Gebäude betreten, außer diese sind
* auf dem Ozean */ * auf dem Ozean */
if (!fval(u_race(u), RCF_WALK) && !fval(u_race(u), RCF_FLY)) { if (!fval(u_race(u), RCF_WALK) && !fval(u_race(u), RCF_FLY)) {
if (!fval(r->terrain, SEA_REGION)) { if (!fval(r->terrain, SEA_REGION)) {
@ -1214,8 +1214,8 @@ void do_enter(struct region *r, bool is_final_attempt)
} }
if (ulast != NULL) { if (ulast != NULL) {
/* Wenn wir hier angekommen sind, war der Befehl /* Wenn wir hier angekommen sind, war der Befehl
* erfolgreich und wir löschen ihn, damit er im * erfolgreich und wir löschen ihn, damit er im
* zweiten Versuch nicht nochmal ausgeführt wird. */ * zweiten Versuch nicht nochmal ausgeführt wird. */
*ordp = ord->next; *ordp = ord->next;
ord->next = NULL; ord->next = NULL;
free_order(ord); free_order(ord);
@ -1527,9 +1527,10 @@ int prefix_cmd(unit * u, struct order *ord)
ap = &u->faction->attribs; ap = &u->faction->attribs;
if (fval(u, UFL_GROUP)) { if (fval(u, UFL_GROUP)) {
attrib *a = a_find(u->attribs, &at_group); attrib *a = a_find(u->attribs, &at_group);
group *g = (group *)a->data.v; if (a) {
if (a) group *g = (group *)a->data.v;
ap = &g->attribs; ap = &g->attribs;
}
} }
set_prefix(ap, race_prefixes[var.i]); set_prefix(ap, race_prefixes[var.i]);
} }
@ -1765,10 +1766,11 @@ int name_cmd(struct unit *u, struct order *ord)
} }
else { else {
const struct locale *lang = locales; const struct locale *lang = locales;
size_t f_len = strlen(f->name);
for (; lang; lang = nextlocale(lang)) { for (; lang; lang = nextlocale(lang)) {
const char *fdname = LOC(lang, "factiondefault"); const char *fdname = LOC(lang, "factiondefault");
size_t fdlen = strlen(fdname); size_t fdlen = strlen(fdname);
if (strlen(f->name) >= fdlen && strncmp(f->name, fdname, fdlen) == 0) { if (f_len >= fdlen && strncmp(f->name, fdname, fdlen) == 0) {
break; break;
} }
} }
@ -1802,18 +1804,17 @@ int name_cmd(struct unit *u, struct order *ord)
} }
else { else {
const struct locale *lang = locales; const struct locale *lang = locales;
size_t sh_len = strlen(sh->name);
for (; lang; lang = nextlocale(lang)) { for (; lang; lang = nextlocale(lang)) {
const char *sdname = LOC(lang, sh->type->_name); const char *sdname = LOC(lang, sh->type->_name);
size_t sdlen = strlen(sdname); size_t sdlen = strlen(sdname);
if (strlen(sh->name) >= sdlen if (sh_len >= sdlen && strncmp(sh->name, sdname, sdlen) == 0) {
&& strncmp(sh->name, sdname, sdlen) == 0) {
break; break;
} }
sdname = LOC(lang, parameters[P_SHIP]); sdname = LOC(lang, parameters[P_SHIP]);
sdlen = strlen(sdname); sdlen = strlen(sdname);
if (strlen(sh->name) >= sdlen if (sh_len >= sdlen && strncmp(sh->name, sdname, sdlen) == 0) {
&& strncmp(sh->name, sdname, sdlen) == 0) {
break; break;
} }
@ -1989,13 +1990,13 @@ int mail_cmd(unit * u, struct order *ord)
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
/* Falls kein Parameter, ist das eine Einheitsnummer; /* Falls kein Parameter, ist das eine Einheitsnummer;
* das Füllwort "AN" muß wegfallen, da gültige Nummer! */ * das Füllwort "AN" muß wegfallen, da gültige Nummer! */
do { do {
cont = 0; cont = 0;
switch (findparam_ex(s, u->faction->locale)) { switch (findparam_ex(s, u->faction->locale)) {
case P_REGION: case P_REGION:
/* können alle Einheiten in der Region sehen */ /* können alle Einheiten in der Region sehen */
s = getstrtoken(); s = getstrtoken();
if (!s || !s[0]) { if (!s || !s[0]) {
cmistake(u, ord, 30, MSG_MESSAGE); cmistake(u, ord, 30, MSG_MESSAGE);
@ -2348,7 +2349,7 @@ static bool display_race(faction * f, unit * u, const race * rc)
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
/* b_armor : Rüstung */ /* b_armor : Rüstung */
if (rc->armor > 0) { if (rc->armor > 0) {
bytes = bytes =
slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor);
@ -2659,7 +2660,7 @@ int combatspell_cmd(unit * u, struct order *ord)
init_order(ord); init_order(ord);
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
/* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */ /* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */
if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) { if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) {
unset_combatspell(u, 0); unset_combatspell(u, 0);
return 0; return 0;
@ -2667,7 +2668,7 @@ int combatspell_cmd(unit * u, struct order *ord)
/* Optional: STUFE n */ /* Optional: STUFE n */
if (findparam(s, u->faction->locale) == P_LEVEL) { if (findparam(s, u->faction->locale) == P_LEVEL) {
/* Merken, setzen kommt erst später */ /* Merken, setzen kommt erst später */
level = getint(); level = getint();
level = _max(0, level); level = _max(0, level);
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
@ -2682,7 +2683,7 @@ int combatspell_cmd(unit * u, struct order *ord)
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
if (findparam(s, u->faction->locale) == P_NOT) { if (findparam(s, u->faction->locale) == P_NOT) {
/* KAMPFZAUBER "<Spruchname>" NICHT löscht diesen speziellen /* KAMPFZAUBER "<Spruchname>" NICHT löscht diesen speziellen
* Kampfzauber */ * Kampfzauber */
unset_combatspell(u, sp); unset_combatspell(u, sp);
return 0; return 0;
@ -2697,7 +2698,7 @@ int combatspell_cmd(unit * u, struct order *ord)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Beachten: einige Monster sollen auch unbewaffent die Region bewachen /* Beachten: einige Monster sollen auch unbewaffent die Region bewachen
* können */ * können */
enum { E_GUARD_OK, E_GUARD_UNARMED, E_GUARD_NEWBIE, E_GUARD_FLEEING }; enum { E_GUARD_OK, E_GUARD_UNARMED, E_GUARD_NEWBIE, E_GUARD_FLEEING };
@ -2740,12 +2741,15 @@ void update_guards(void)
int guard_on_cmd(unit * u, struct order *ord) int guard_on_cmd(unit * u, struct order *ord)
{ {
assert(getkeyword(ord) == K_GUARD); assert(getkeyword(ord) == K_GUARD);
assert(u);
assert(u->faction);
init_order(ord); init_order(ord);
/* GUARD NOT is handled in goard_off_cmd earlier in the turn */ /* GUARD NOT is handled in goard_off_cmd earlier in the turn */
if (getparam(u->faction->locale) == P_NOT) if (getparam(u->faction->locale) == P_NOT) {
return 0; return 0;
}
if (fval(u->region->terrain, SEA_REGION)) { if (fval(u->region->terrain, SEA_REGION)) {
cmistake(u, ord, 2, MSG_EVENT); cmistake(u, ord, 2, MSG_EVENT);
@ -2759,7 +2763,7 @@ int guard_on_cmd(unit * u, struct order *ord)
cmistake(u, ord, 95, MSG_EVENT); cmistake(u, ord, 95, MSG_EVENT);
} }
else { else {
/* Monster der Monsterpartei dürfen immer bewachen */ /* Monster der Monsterpartei dürfen immer bewachen */
if (is_monsters(u->faction)) { if (is_monsters(u->faction)) {
guard(u, GUARD_ALL); guard(u, GUARD_ALL);
} }
@ -2793,7 +2797,7 @@ void sinkships(struct region * r)
if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) { if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) {
if (fval(r->terrain, SEA_REGION) && (!enoughsailors(sh, r) if (fval(r->terrain, SEA_REGION) && (!enoughsailors(sh, r)
|| get_captain(sh) == NULL)) { || get_captain(sh) == NULL)) {
/* Schiff nicht seetüchtig */ /* Schiff nicht seetüchtig */
float dmg = get_param_flt(global.parameters, float dmg = get_param_flt(global.parameters,
"rules.ship.damage.nocrewocean", "rules.ship.damage.nocrewocean",
0.30F); 0.30F);
@ -3250,7 +3254,7 @@ static void ageing(void)
sp = &(*sp)->next; sp = &(*sp)->next;
} }
/* Gebäude */ /* Gebäude */
for (bp = &r->buildings; *bp;) { for (bp = &r->buildings; *bp;) {
building *b = *bp; building *b = *bp;
age_building(b); age_building(b);
@ -3456,7 +3460,7 @@ void update_long_order(unit * u)
freset(u, UFL_MOVED); freset(u, UFL_MOVED);
freset(u, UFL_LONGACTION); freset(u, UFL_LONGACTION);
if (hunger) { if (hunger) {
/* Hungernde Einheiten führen NUR den default-Befehl aus */ /* Hungernde Einheiten führen NUR den default-Befehl aus */
set_order(&u->thisorder, default_order(u->faction->locale)); set_order(&u->thisorder, default_order(u->faction->locale));
} }
else { else {
@ -3477,7 +3481,7 @@ void update_long_order(unit * u)
continue; continue;
if (is_exclusive(ord)) { if (is_exclusive(ord)) {
/* Über dieser Zeile nur Befehle, die auch eine idle Faction machen darf */ /* Über dieser Zeile nur Befehle, die auch eine idle Faction machen darf */
if (idle(u->faction)) { if (idle(u->faction)) {
set_order(&u->thisorder, default_order(u->faction->locale)); set_order(&u->thisorder, default_order(u->faction->locale));
} }
@ -3489,13 +3493,13 @@ void update_long_order(unit * u)
else { else {
keyword_t keyword = getkeyword(ord); keyword_t keyword = getkeyword(ord);
switch (keyword) { switch (keyword) {
/* Wenn gehandelt wird, darf kein langer Befehl ausgeführt /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt
* werden. Da Handel erst nach anderen langen Befehlen kommt, * werden. Da Handel erst nach anderen langen Befehlen kommt,
* muß das vorher abgefangen werden. Wir merken uns also * muß das vorher abgefangen werden. Wir merken uns also
* hier, ob die Einheit handelt. */ * hier, ob die Einheit handelt. */
case K_BUY: case K_BUY:
case K_SELL: case K_SELL:
/* Wenn die Einheit handelt, muß der Default-Befehl gelöscht /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
* werden. * werden.
* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen * Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
* mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
@ -3505,7 +3509,7 @@ void update_long_order(unit * u)
case K_CAST: case K_CAST:
/* dient dazu, das neben Zaubern kein weiterer Befehl /* dient dazu, das neben Zaubern kein weiterer Befehl
* ausgeführt werden kann, Zaubern ist ein kurzer Befehl */ * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */
set_order(&u->thisorder, copy_order(ord)); set_order(&u->thisorder, copy_order(ord));
break; break;
@ -3518,7 +3522,7 @@ void update_long_order(unit * u)
if (hunger) { if (hunger) {
return; return;
} }
/* Wenn die Einheit handelt, muß der Default-Befehl gelöscht /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
* werden. */ * werden. */
if (trade) { if (trade) {
@ -3594,7 +3598,7 @@ void monthly_healing(void)
double healingcurse = 0; double healingcurse = 0;
if (heal_ct != NULL) { if (heal_ct != NULL) {
/* bonus zurücksetzen */ /* bonus zurücksetzen */
curse *c = get_curse(r->attribs, heal_ct); curse *c = get_curse(r->attribs, heal_ct);
if (c != NULL) { if (c != NULL) {
healingcurse = curse_geteffect(c); healingcurse = curse_geteffect(c);
@ -3604,8 +3608,8 @@ void monthly_healing(void)
int umhp = unit_max_hp(u) * u->number; int umhp = unit_max_hp(u) * u->number;
double p = 1.0; double p = 1.0;
/* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht /* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht
* oder verändertes Ausdauertalent verursacht */ * oder verändertes Ausdauertalent verursacht */
if (u->hp > umhp) { if (u->hp > umhp) {
u->hp -= (int)ceil((u->hp - umhp) / 2.0); u->hp -= (int)ceil((u->hp - umhp) / 2.0);
if (u->hp < umhp) if (u->hp < umhp)
@ -3632,7 +3636,7 @@ void monthly_healing(void)
if (btype == bt_find("inn")) { if (btype == bt_find("inn")) {
p *= 1.5; p *= 1.5;
} }
/* pro punkt 5% höher */ /* pro punkt 5% höher */
p *= (1.0 + healingcurse * 0.05); p *= (1.0 + healingcurse * 0.05);
maxheal = p * maxheal; maxheal = p * maxheal;
@ -3644,7 +3648,7 @@ void monthly_healing(void)
/* Aufaddieren der geheilten HP. */ /* Aufaddieren der geheilten HP. */
u->hp = _min(u->hp + addhp, umhp); u->hp = _min(u->hp + addhp, umhp);
/* soll man an negativer regeneration sterben können? */ /* soll man an negativer regeneration sterben können? */
assert(u->hp > 0); assert(u->hp > 0);
} }
} }
@ -3691,7 +3695,7 @@ void defaultorders(void)
ord->next = NULL; ord->next = NULL;
free_order(ord); free_order(ord);
if (!neworders) { if (!neworders) {
/* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */ /* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */
remove_exclusive(&u->orders); remove_exclusive(&u->orders);
remove_exclusive(&u->old_orders); remove_exclusive(&u->old_orders);
neworders = true; neworders = true;
@ -4564,8 +4568,8 @@ void processorders(void)
wormholes_update(); wormholes_update();
} }
/* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich /* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich
* Beschreibungen geändert haben */ * Beschreibungen geändert haben */
update_spells(); update_spells();
warn_password(); warn_password();
} }

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2014, Copyright (c) 1998-2014,
Enno Rehling <enno@eressea.de> Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
@ -193,7 +193,7 @@ attrib_type at_icastle = {
extern int dice(int count, int value); extern int dice(int count, int value);
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* aus dem alten System übriggebliegene Funktionen, die bei der /* aus dem alten System übriggebliegene Funktionen, die bei der
* Umwandlung von alt nach neu gebraucht werden */ * Umwandlung von alt nach neu gebraucht werden */
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -352,9 +352,9 @@ sc_mage *get_mage(const unit * u)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Ausgabe der Spruchbeschreibungen /* Ausgabe der Spruchbeschreibungen
* Anzeige des Spruchs nur, wenn die Stufe des besten Magiers vorher * Anzeige des Spruchs nur, wenn die Stufe des besten Magiers vorher
* kleiner war (u->faction->seenspells). Ansonsten muss nur geprüft * kleiner war (u->faction->seenspells). Ansonsten muss nur geprüft
* werden, ob dieser Magier den Spruch schon kennt, und andernfalls der * werden, ob dieser Magier den Spruch schon kennt, und andernfalls der
* Spruch zu seiner List-of-known-spells hinzugefügt werden. * Spruch zu seiner List-of-known-spells hinzugefügt werden.
*/ */
static int read_seenspell(attrib * a, void *owner, struct storage *store) static int read_seenspell(attrib * a, void *owner, struct storage *store)
@ -507,7 +507,7 @@ sc_mage *create_mage(unit * u, magic_t mtyp)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Funktionen für die Bearbeitung der List-of-known-spells */ /* Funktionen für die Bearbeitung der List-of-known-spells */
int u_hasspell(const unit *u, const struct spell *sp) int u_hasspell(const unit *u, const struct spell *sp)
{ {
@ -535,7 +535,7 @@ int get_combatspelllevel(const unit * u, int nr)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Kampfzauber ermitteln, setzen oder löschen */ /* Kampfzauber ermitteln, setzen oder löschen */
const spell *get_combatspell(const unit * u, int nr) const spell *get_combatspell(const unit * u, int nr)
{ {
@ -560,7 +560,7 @@ void set_combatspell(unit * u, spell * sp, struct order *ord, int level)
assert(mage || !"trying to set a combat spell for non-mage"); assert(mage || !"trying to set a combat spell for non-mage");
/* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */
if (!knowsspell(u->region, u, sp)) { if (!knowsspell(u->region, u, sp)) {
/* Fehler 'Spell not found' */ /* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC); cmistake(u, ord, 173, MSG_MAGIC);
@ -626,7 +626,7 @@ void unset_combatspell(unit * u, spell * sp)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */ /* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */
int get_spellpoints(const unit * u) int get_spellpoints(const unit * u)
{ {
sc_mage *m; sc_mage *m;
@ -652,7 +652,7 @@ void set_spellpoints(unit * u, int sp)
} }
/* /*
* verändert die Anzahl der Magiepunkte der Einheit um +mp * verändert die Anzahl der Magiepunkte der Einheit um +mp
*/ */
int change_spellpoints(unit * u, int mp) int change_spellpoints(unit * u, int mp)
{ {
@ -671,7 +671,7 @@ int change_spellpoints(unit * u, int mp)
return sp; return sp;
} }
/* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit /* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit
* Regionszaubern oder Attributen zu beinflussen * Regionszaubern oder Attributen zu beinflussen
*/ */
static int get_spchange(const unit * u) static int get_spchange(const unit * u)
@ -687,13 +687,13 @@ static int get_spchange(const unit * u)
/* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte
* haben. * haben.
* Manche Rassen haben einen zusätzlichen Multiplikator * Manche Rassen haben einen zusätzlichen Multiplikator
* Durch Talentverlust (zB Insekten im Berg) können negative Werte * Durch Talentverlust (zB Insekten im Berg) können negative Werte
* entstehen * entstehen
*/ */
/* Artefakt der Stärke /* Artefakt der Stärke
* Ermöglicht dem Magier mehr Magiepunkte zu 'speichern' * Ermöglicht dem Magier mehr Magiepunkte zu 'speichern'
*/ */
/** TODO: at_skillmod daraus machen */ /** TODO: at_skillmod daraus machen */
static int use_item_aura(const region * r, const unit * u) static int use_item_aura(const region * r, const unit * u)
@ -741,8 +741,8 @@ int change_maxspellpoints(unit * u, int csp)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Counter für die bereits gezauberte Anzahl Sprüche pro Runde. /* Counter für die bereits gezauberte Anzahl Sprüche pro Runde.
* Um nur die Zahl der bereits gezauberten Sprüche zu ermitteln mit * Um nur die Zahl der bereits gezauberten Sprüche zu ermitteln mit
* step = 0 aufrufen. * step = 0 aufrufen.
*/ */
int countspells(unit * u, int step) int countspells(unit * u, int step)
@ -766,9 +766,9 @@ int countspells(unit * u, int step)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Die für den Spruch benötigte Aura pro Stufe. /* Die für den Spruch benötigte Aura pro Stufe.
* Die Grundkosten pro Stufe werden hier um 2^count erhöht. Der * Die Grundkosten pro Stufe werden hier um 2^count erhöht. Der
* Parameter count ist dabei die Anzahl der bereits gezauberten Sprüche * Parameter count ist dabei die Anzahl der bereits gezauberten Sprüche
*/ */
int spellcost(unit * u, const spell * sp) int spellcost(unit * u, const spell * sp)
{ {
@ -786,12 +786,12 @@ int spellcost(unit * u, const spell * sp)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* SPC_LINEAR ist am höchstwertigen, dann müssen Komponenten für die /* SPC_LINEAR ist am höchstwertigen, dann müssen Komponenten für die
* Stufe des Magiers vorhanden sein. * Stufe des Magiers vorhanden sein.
* SPC_LINEAR hat die gewünschte Stufe als multiplikator, * SPC_LINEAR hat die gewünschte Stufe als multiplikator,
* nur SPC_FIX muss nur einmal vorhanden sein, ist also am * nur SPC_FIX muss nur einmal vorhanden sein, ist also am
* niedrigstwertigen und sollte von den beiden anderen Typen * niedrigstwertigen und sollte von den beiden anderen Typen
* überschrieben werden */ * überschrieben werden */
static int spl_costtyp(const spell * sp) static int spl_costtyp(const spell * sp)
{ {
int k; int k;
@ -805,7 +805,7 @@ static int spl_costtyp(const spell * sp)
return SPC_LINEAR; return SPC_LINEAR;
} }
/* wenn keine Fixkosten, Typ übernehmen */ /* wenn keine Fixkosten, Typ übernehmen */
if (sp->components[k].cost != SPC_FIX) { if (sp->components[k].cost != SPC_FIX) {
costtyp = sp->components[k].cost; costtyp = sp->components[k].cost;
} }
@ -814,10 +814,10 @@ static int spl_costtyp(const spell * sp)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* durch Komponenten und cast_level begrenzter maximal möglicher /* durch Komponenten und cast_level begrenzter maximal möglicher
* Level * Level
* Da die Funktion nicht alle Komponenten durchprobiert sondern beim * Da die Funktion nicht alle Komponenten durchprobiert sondern beim
* ersten Fehler abbricht, muss die Fehlermeldung später mit cancast() * ersten Fehler abbricht, muss die Fehlermeldung später mit cancast()
* generiert werden. * generiert werden.
* */ * */
int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
@ -831,8 +831,8 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
return 0; return 0;
if (sp->components[k].amount > 0) { if (sp->components[k].amount > 0) {
/* Die Kosten für Aura sind auch von der Zahl der bereits /* Die Kosten für Aura sind auch von der Zahl der bereits
* gezauberten Sprüche abhängig */ * gezauberten Sprüche abhängig */
if (sp->components[k].type == r_aura) { if (sp->components[k].type == r_aura) {
needplevel = spellcost(u, sp) * range; needplevel = spellcost(u, sp) * range;
} }
@ -844,18 +844,18 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
needplevel * cast_level) / needplevel; needplevel * cast_level) / needplevel;
/* sind die Kosten fix, so muss die Komponente nur einmal vorhanden /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden
* sein und der cast_level ändert sich nicht */ * sein und der cast_level ändert sich nicht */
if (sp->components[k].cost == SPC_FIX) { if (sp->components[k].cost == SPC_FIX) {
if (maxlevel < 1) if (maxlevel < 1)
cast_level = 0; cast_level = 0;
/* ansonsten wird das Minimum aus maximal möglicher Stufe und der /* ansonsten wird das Minimum aus maximal möglicher Stufe und der
* gewünschten gebildet */ * gewünschten gebildet */
} }
else if (sp->components[k].cost == SPC_LEVEL) { else if (sp->components[k].cost == SPC_LEVEL) {
costtyp = SPC_LEVEL; costtyp = SPC_LEVEL;
cast_level = _min(cast_level, maxlevel); cast_level = _min(cast_level, maxlevel);
/* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden
* sein, ansonsten schlägt der Spruch fehl */ * sein, ansonsten schlägt der Spruch fehl */
} }
else if (sp->components[k].cost == SPC_LINEAR) { else if (sp->components[k].cost == SPC_LINEAR) {
costtyp = SPC_LINEAR; costtyp = SPC_LINEAR;
@ -882,7 +882,7 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Die Spruchgrundkosten werden mit der Entfernung (Farcasting) /* Die Spruchgrundkosten werden mit der Entfernung (Farcasting)
* multipliziert, wobei die Aurakosten ein Sonderfall sind, da sie sich * multipliziert, wobei die Aurakosten ein Sonderfall sind, da sie sich
* auch durch die Menge der bereits gezauberten Sprüche erhöht. * auch durch die Menge der bereits gezauberten Sprüche erhöht.
* Je nach Kostenart werden dann die Komponenten noch mit cast_level * Je nach Kostenart werden dann die Komponenten noch mit cast_level
* multipliziert. * multipliziert.
*/ */
@ -913,12 +913,12 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Ein Magier kennt den Spruch und kann sich die Beschreibung anzeigen /* Ein Magier kennt den Spruch und kann sich die Beschreibung anzeigen
* lassen, wenn diese in seiner Spruchliste steht. Zaubern muss er ihn * lassen, wenn diese in seiner Spruchliste steht. Zaubern muss er ihn
* aber dann immer noch nicht können, vieleicht ist seine Stufe derzeit * aber dann immer noch nicht können, vieleicht ist seine Stufe derzeit
* nicht ausreichend oder die Komponenten fehlen. * nicht ausreichend oder die Komponenten fehlen.
*/ */
bool knowsspell(const region * r, const unit * u, const spell * sp) bool knowsspell(const region * r, const unit * u, const spell * sp)
{ {
/* Ist überhaupt ein gültiger Spruch angegeben? */ /* Ist überhaupt ein gültiger Spruch angegeben? */
if (!sp || sp->id == 0) { if (!sp || sp->id == 0) {
return false; return false;
} }
@ -929,7 +929,7 @@ bool knowsspell(const region * r, const unit * u, const spell * sp)
/* Um einen Spruch zu beherrschen, muss der Magier die Stufe des /* Um einen Spruch zu beherrschen, muss der Magier die Stufe des
* Spruchs besitzen, nicht nur wissen, das es ihn gibt (also den Spruch * Spruchs besitzen, nicht nur wissen, das es ihn gibt (also den Spruch
* in seiner Spruchliste haben). * in seiner Spruchliste haben).
* Kosten für einen Spruch können Magiepunkte, Silber, Kraeuter * Kosten für einen Spruch können Magiepunkte, Silber, Kraeuter
* und sonstige Gegenstaende sein. * und sonstige Gegenstaende sein.
*/ */
@ -948,7 +948,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
} }
/* reicht die Stufe aus? */ /* reicht die Stufe aus? */
if (eff_skill(u, SK_MAGIC, u->region) < level) { if (eff_skill(u, SK_MAGIC, u->region) < level) {
/* die Einheit ist nicht erfahren genug für diesen Zauber */ /* die Einheit ist nicht erfahren genug für diesen Zauber */
cmistake(u, ord, 169, MSG_MAGIC); cmistake(u, ord, 169, MSG_MAGIC);
return false; return false;
} }
@ -958,8 +958,8 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
const resource_type *rtype = sp->components[k].type; const resource_type *rtype = sp->components[k].type;
int itemhave; int itemhave;
/* Die Kosten für Aura sind auch von der Zahl der bereits /* Die Kosten für Aura sind auch von der Zahl der bereits
* gezauberten Sprüche abhängig */ * gezauberten Sprüche abhängig */
if (rtype == r_aura) { if (rtype == r_aura) {
itemanz = spellcost(u, sp) * range; itemanz = spellcost(u, sp) * range;
} }
@ -967,7 +967,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
itemanz = sp->components[k].amount * range; itemanz = sp->components[k].amount * range;
} }
/* sind die Kosten stufenabhängig, so muss itemanz noch mit dem /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem
* level multipliziert werden */ * level multipliziert werden */
switch (sp->components[k].cost) { switch (sp->components[k].cost) {
case SPC_LEVEL: case SPC_LEVEL:
@ -1004,7 +1004,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
* Spruchitems und Antimagiefeldern zusammen. Es koennen noch die * Spruchitems und Antimagiefeldern zusammen. Es koennen noch die
* Stufe des Spruchs und Magiekosten mit einfliessen. * Stufe des Spruchs und Magiekosten mit einfliessen.
* *
* Die effektive Spruchstärke und ihre Auswirkungen werden in der * Die effektive Spruchstärke und ihre Auswirkungen werden in der
* Spruchfunktionsroutine ermittelt. * Spruchfunktionsroutine ermittelt.
*/ */
@ -1080,7 +1080,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* farcasting() == 1 -> gleiche Region, da man mit Null nicht vernünfigt /* farcasting() == 1 -> gleiche Region, da man mit Null nicht vernünfigt
* rechnen kann */ * rechnen kann */
static int farcasting(unit * magician, region * r) static int farcasting(unit * magician, region * r)
{ {
@ -1166,7 +1166,7 @@ double magic_resistance(unit * target)
/* Bonus durch Artefakte */ /* Bonus durch Artefakte */
/* TODO (noch gibs keine) */ /* TODO (noch gibs keine) */
/* Bonus durch Gebäude */ /* Bonus durch Gebäude */
{ {
struct building *b = inside_building(target); struct building *b = inside_building(target);
const struct building_type *btype = b ? b->type : NULL; const struct building_type *btype = b ? b->type : NULL;
@ -1179,14 +1179,14 @@ double magic_resistance(unit * target)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Prüft, ob das Objekt dem Zauber widerstehen kann. /* Prüft, ob das Objekt dem Zauber widerstehen kann.
* Objekte können Regionen, Units, Gebäude oder Schiffe sein. * Objekte können Regionen, Units, Gebäude oder Schiffe sein.
* TYP_UNIT: * TYP_UNIT:
* Das höchste Talent des Ziels ist sein 'Magieresistenz-Talent', Magier * Das höchste Talent des Ziels ist sein 'Magieresistenz-Talent', Magier
* bekommen einen Bonus. Grundchance ist 50%, für jede Stufe * bekommen einen Bonus. Grundchance ist 50%, für jede Stufe
* Unterschied gibt es 5%, minimalchance ist 5% für jeden (5-95%) * Unterschied gibt es 5%, minimalchance ist 5% für jeden (5-95%)
* Scheitert der Spruch an der Magieresistenz, so gibt die Funktion * Scheitert der Spruch an der Magieresistenz, so gibt die Funktion
* true zurück * true zurück
*/ */
bool bool
@ -1248,8 +1248,8 @@ target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus)
probability = _min(0.98, probability); probability = _min(0.98, probability);
/* gibt true, wenn die Zufallszahl kleiner als die chance ist und /* gibt true, wenn die Zufallszahl kleiner als die chance ist und
* false, wenn sie gleich oder größer ist, dh je größer die * false, wenn sie gleich oder größer ist, dh je größer die
* Magieresistenz (chance) desto eher gibt die Funktion true zurück */ * Magieresistenz (chance) desto eher gibt die Funktion true zurück */
return chance(probability); return chance(probability);
} }
@ -1276,7 +1276,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade)
{ {
/* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. /* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier.
* 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch
* benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit
* 20% Warscheinlichkeit nicht * 20% Warscheinlichkeit nicht
* */ * */
@ -1306,8 +1306,8 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade)
fumble_chance += CHAOSPATZERCHANCE; fumble_chance += CHAOSPATZERCHANCE;
} }
/* wenn die Chance kleiner als 0 ist, können wir gleich false /* wenn die Chance kleiner als 0 ist, können wir gleich false
* zurückgeben */ * zurückgeben */
if (fumble_chance <= 0) { if (fumble_chance <= 0) {
return false; return false;
} }
@ -1317,7 +1317,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Dummy-Zauberpatzer, Platzhalter für speziel auf die Sprüche /* Dummy-Zauberpatzer, Platzhalter für speziel auf die Sprüche
* zugeschnittene Patzer */ * zugeschnittene Patzer */
static void fumble_default(castorder * co) static void fumble_default(castorder * co)
{ {
@ -1328,7 +1328,7 @@ static void fumble_default(castorder * co)
return; return;
} }
/* Die normalen Spruchkosten müssen immer bezahlt werden, hier noch /* Die normalen Spruchkosten müssen immer bezahlt werden, hier noch
* alle weiteren Folgen eines Patzers * alle weiteren Folgen eines Patzers
*/ */
@ -1390,7 +1390,7 @@ static void do_fumble(castorder * co)
break; break;
case 3: case 3:
case 4: case 4:
/* Spruch schlägt fehl, alle Magiepunkte weg */ /* Spruch schlägt fehl, alle Magiepunkte weg */
set_spellpoints(u, 0); set_spellpoints(u, 0);
ADDMSG(&u->faction->msgs, msg_message("patzer3", "unit region spell", ADDMSG(&u->faction->msgs, msg_message("patzer3", "unit region spell",
u, r, sp)); u, r, sp));
@ -1409,7 +1409,7 @@ static void do_fumble(castorder * co)
case 8: case 8:
case 9: case 9:
default: default:
/* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */ /* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */
co->level = sp->cast(co); co->level = sp->cast(co);
ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell", ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell",
u, r, sp)); u, r, sp));
@ -1422,7 +1422,7 @@ static void do_fumble(castorder * co)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Ein Magier regeneriert pro Woche W(Stufe^1.5/2+1), mindestens 1 /* Ein Magier regeneriert pro Woche W(Stufe^1.5/2+1), mindestens 1
* Zwerge nur die Hälfte * Zwerge nur die Hälfte
*/ */
static double regeneration(unit * u) static double regeneration(unit * u)
{ {
@ -1439,7 +1439,7 @@ static double regeneration(unit * u)
/* Einfluss von Artefakten */ /* Einfluss von Artefakten */
/* TODO (noch gibs keine) */ /* TODO (noch gibs keine) */
/* Würfeln */ /* Würfeln */
aura = (rng_double() * d + rng_double() * d) / 2 + 1; aura = (rng_double() * d + rng_double() * d) / 2 + 1;
aura *= MagicRegeneration(); aura *= MagicRegeneration();
@ -1469,8 +1469,8 @@ void regenerate_aura(void)
const struct building_type *btype = b ? b->type : NULL; const struct building_type *btype = b ? b->type : NULL;
reg_aura = regeneration(u); reg_aura = regeneration(u);
/* Magierturm erhöht die Regeneration um 75% */ /* Magierturm erhöht die Regeneration um 75% */
/* Steinkreis erhöht die Regeneration um 50% */ /* Steinkreis erhöht die Regeneration um 50% */
if (btype) if (btype)
reg_aura *= btype->auraregen; reg_aura *= btype->auraregen;
@ -1609,14 +1609,14 @@ order * ord)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Zuerst wird versucht alle noch nicht gefundenen Objekte zu finden /* Zuerst wird versucht alle noch nicht gefundenen Objekte zu finden
* oder zu prüfen, ob das gefundene Objekt wirklich hätte gefunden * oder zu prüfen, ob das gefundene Objekt wirklich hätte gefunden
* werden dürfen (nicht alle Zauber wirken global). Dabei zählen wir die * werden dürfen (nicht alle Zauber wirken global). Dabei zählen wir die
* Misserfolge (failed). * Misserfolge (failed).
* Dann folgen die Tests der gefundenen Objekte auf Magieresistenz und * Dann folgen die Tests der gefundenen Objekte auf Magieresistenz und
* Sichtbarkeit. Dabei zählen wir die magieresistenten (resists) * Sichtbarkeit. Dabei zählen wir die magieresistenten (resists)
* Objekte. Alle anderen werten wir als Erfolge (success) */ * Objekte. Alle anderen werten wir als Erfolge (success) */
/* gibt bei Misserfolg 0 zurück, bei Magieresistenz zumindeste eines /* gibt bei Misserfolg 0 zurück, bei Magieresistenz zumindeste eines
* Objektes 1 und bei Erfolg auf ganzer Linie 2 */ * Objektes 1 und bei Erfolg auf ganzer Linie 2 */
static void static void
verify_targets(castorder * co, int *invalid, int *resist, int *success) verify_targets(castorder * co, int *invalid, int *resist, int *success)
@ -1634,8 +1634,8 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success)
if (sa && sa->length) { if (sa && sa->length) {
/* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden.
* Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber
* gar nicht global hätte suchen dürften, setzen wir das Objekt * gar nicht global hätte suchen dürften, setzen wir das Objekt
* zurück. */ * zurück. */
for (i = 0; i < sa->length; i++) { for (i = 0; i < sa->length; i++) {
spllprm *spobj = sa->param[i]; spllprm *spobj = sa->param[i];
@ -1719,7 +1719,7 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success)
case SPP_REGION: case SPP_REGION:
/* haben wir ein Regionsobjekt, dann wird auch dieses und /* haben wir ein Regionsobjekt, dann wird auch dieses und
nicht target_r überprüft. */ nicht target_r überprüft. */
tr = spobj->data.r; tr = spobj->data.r;
if ((sp->sptyp & TESTRESISTANCE) if ((sp->sptyp & TESTRESISTANCE)
@ -1745,7 +1745,7 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success)
else { else {
/* der Zauber hat keine expliziten Parameter/Ziele, es kann sich /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich
* aber um einen Regionszauber handeln. Wenn notwendig hier die * aber um einen Regionszauber handeln. Wenn notwendig hier die
* Magieresistenz der Region prüfen. */ * Magieresistenz der Region prüfen. */
if ((sp->sptyp & REGIONSPELL)) { if ((sp->sptyp & REGIONSPELL)) {
/* Zielobjekt Region anlegen */ /* Zielobjekt Region anlegen */
spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); spllprm *spobj = (spllprm *)malloc(sizeof(spllprm));
@ -1782,16 +1782,17 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success)
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Hilfsstrukturen für ZAUBERE */ /* Hilfsstrukturen für ZAUBERE */
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static void free_spellparameter(spellparameter * pa) static void free_spellparameter(spellparameter * pa)
{ {
int i; int i;
/* Elemente free'en */ assert(pa->param);
for (i = 0; i < pa->length; i++) {
for (i = 0; i < pa->length; i++) {
assert(pa->param[i]);
switch (pa->param[i]->typ) { switch (pa->param[i]->typ) {
case SPP_STRING: case SPP_STRING:
free(pa->param[i]->data.s); free(pa->param[i]->data.s);
@ -1801,10 +1802,7 @@ static void free_spellparameter(spellparameter * pa)
} }
free(pa->param[i]); free(pa->param[i]);
} }
free(pa->param);
if (pa->param)
free(pa->param);
/* struct free'en */
free(pa); free(pa);
} }
@ -1966,7 +1964,7 @@ static spellparameter *add_spellparameter(region * target_r, unit * u,
break; break;
case '+': case '+':
/* das vorhergehende Element kommt ein oder mehrmals vor, wir /* das vorhergehende Element kommt ein oder mehrmals vor, wir
* springen zum key zurück */ * springen zum key zurück */
j = 0; j = 0;
--c; --c;
break; break;
@ -2090,7 +2088,7 @@ void free_castorder(struct castorder *co)
if (co->order) free_order(co->order); if (co->order) free_order(co->order);
} }
/* Hänge c-order co an die letze c-order von cll an */ /* Hänge c-order co an die letze c-order von cll an */
void add_castorder(spellrank * cll, castorder * co) void add_castorder(spellrank * cll, castorder * co)
{ {
if (cll->begin == NULL) { if (cll->begin == NULL) {
@ -2521,7 +2519,7 @@ static castorder *cast_cmd(unit * u, order * ord)
init_order(ord); init_order(ord);
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
param = findparam(s, u->faction->locale); param = findparam(s, u->faction->locale);
/* für Syntax ' STUFE x REGION y z ' */ /* für Syntax ' STUFE x REGION y z ' */
if (param == P_LEVEL) { if (param == P_LEVEL) {
int p = getint(); int p = getint();
level = _min(p, level); level = _min(p, level);
@ -2550,8 +2548,8 @@ static castorder *cast_cmd(unit * u, order * ord)
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
param = findparam(s, u->faction->locale); param = findparam(s, u->faction->locale);
} }
/* für Syntax ' REGION x y STUFE z ' /* für Syntax ' REGION x y STUFE z '
* hier nach REGION nochmal auf STUFE prüfen */ * hier nach REGION nochmal auf STUFE prüfen */
if (param == P_LEVEL) { if (param == P_LEVEL) {
int p = getint(); int p = getint();
level = _min(p, level); level = _min(p, level);
@ -2570,8 +2568,8 @@ static castorder *cast_cmd(unit * u, order * ord)
sp = unit_getspell(u, s, u->faction->locale); sp = unit_getspell(u, s, u->faction->locale);
/* Vertraute können auch Zauber sprechen, die sie selbst nicht /* Vertraute können auch Zauber sprechen, die sie selbst nicht
* können. unit_getspell findet aber nur jene Sprüche, die * können. unit_getspell findet aber nur jene Sprüche, die
* die Einheit beherrscht. */ * die Einheit beherrscht. */
if (!sp && is_familiar(u)) { if (!sp && is_familiar(u)) {
caster = get_familiar_mage(u); caster = get_familiar_mage(u);
@ -2594,7 +2592,7 @@ static castorder *cast_cmd(unit * u, order * ord)
/* um testen auf spruchnamen zu unterbinden sollte vor allen /* um testen auf spruchnamen zu unterbinden sollte vor allen
* fehlermeldungen die anzeigen das der magier diesen Spruch * fehlermeldungen die anzeigen das der magier diesen Spruch
* nur in diese Situation nicht anwenden kann, noch eine * nur in diese Situation nicht anwenden kann, noch eine
* einfache Sicherheitsprüfung kommen */ * einfache Sicherheitsprüfung kommen */
if (!knowsspell(r, u, sp)) { if (!knowsspell(r, u, sp)) {
/* vorsicht! u kann der familiar sein */ /* vorsicht! u kann der familiar sein */
if (!familiar) { if (!familiar) {
@ -2607,9 +2605,9 @@ static castorder *cast_cmd(unit * u, order * ord)
cmistake(u, ord, 174, MSG_MAGIC); cmistake(u, ord, 174, MSG_MAGIC);
return 0; return 0;
} }
/* Auf dem Ozean Zaubern als quasi-langer Befehl können /* Auf dem Ozean Zaubern als quasi-langer Befehl können
* normalerweise nur Meermenschen, ausgenommen explizit als * normalerweise nur Meermenschen, ausgenommen explizit als
* OCEANCASTABLE deklarierte Sprüche */ * OCEANCASTABLE deklarierte Sprüche */
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
if (u_race(u) != get_race(RC_AQUARIAN) if (u_race(u) != get_race(RC_AQUARIAN)
&& !fval(u_race(u), RCF_SWIM) && !fval(u_race(u), RCF_SWIM)
@ -2632,7 +2630,7 @@ static castorder *cast_cmd(unit * u, order * ord)
} }
} }
} }
/* Farcasting bei nicht farcastbaren Sprüchen abfangen */ /* Farcasting bei nicht farcastbaren Sprüchen abfangen */
range = farcasting(u, target_r); range = farcasting(u, target_r);
if (range > 1) { if (range > 1) {
if (!(sp->sptyp & FARCASTING)) { if (!(sp->sptyp & FARCASTING)) {
@ -2647,7 +2645,7 @@ static castorder *cast_cmd(unit * u, order * ord)
return 0; return 0;
} }
} }
/* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */
if (!(sp->sptyp & SPELLLEVEL)) { if (!(sp->sptyp & SPELLLEVEL)) {
int ilevel = eff_skill(u, SK_MAGIC, u->region); int ilevel = eff_skill(u, SK_MAGIC, u->region);
if (ilevel != level) { if (ilevel != level) {
@ -2680,9 +2678,9 @@ static castorder *cast_cmd(unit * u, order * ord)
"mage", caster)); "mage", caster));
return 0; return 0;
} }
/* mage auf magier setzen, level anpassen, range für Erhöhung /* mage auf magier setzen, level anpassen, range für Erhöhung
* der Spruchkosten nutzen, langen Befehl des Magiers * der Spruchkosten nutzen, langen Befehl des Magiers
* löschen, zaubern kann er noch */ * löschen, zaubern kann er noch */
range *= 2; range *= 2;
set_order(&caster->thisorder, NULL); set_order(&caster->thisorder, NULL);
level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2);
@ -2721,19 +2719,19 @@ static castorder *cast_cmd(unit * u, order * ord)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Damit man keine Rituale in fremden Gebiet machen kann, diese vor /* Damit man keine Rituale in fremden Gebiet machen kann, diese vor
* Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde * Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde
* lang verletzlich, da sie es betreten, und angegriffen werden können, * lang verletzlich, da sie es betreten, und angegriffen werden können,
* bevor sie ein Ritual machen können. * bevor sie ein Ritual machen können.
* *
* Syntax: ZAUBER [REGION X Y] [STUFE <stufe>] "Spruchname" [Einheit-1 * Syntax: ZAUBER [REGION X Y] [STUFE <stufe>] "Spruchname" [Einheit-1
* Einheit-2 ..] * Einheit-2 ..]
* *
* Nach Priorität geordnet die Zauber global auswerten. * Nach Priorität geordnet die Zauber global auswerten.
* *
* Die Kosten für Farcasting multiplizieren sich mit der Entfernung, * Die Kosten für Farcasting multiplizieren sich mit der Entfernung,
* cast_level gibt die virtuelle Stufe an, die den durch das Farcasten * cast_level gibt die virtuelle Stufe an, die den durch das Farcasten
* entstandenen Spruchkosten entspricht. Sind die Spruchkosten nicht * entstandenen Spruchkosten entspricht. Sind die Spruchkosten nicht
* levelabhängig, so sind die Kosten nur von der Entfernung bestimmt, * levelabhängig, so sind die Kosten nur von der Entfernung bestimmt,
* die Stärke/Level durch den realen Skill des Magiers * die Stärke/Level durch den realen Skill des Magiers
*/ */
void magic(void) void magic(void)
@ -2776,11 +2774,11 @@ void magic(void)
} }
} }
/* Da sich die Aura und Komponenten in der Zwischenzeit verändert /* Da sich die Aura und Komponenten in der Zwischenzeit verändert
* haben können und sich durch vorherige Sprüche das Zaubern * haben können und sich durch vorherige Sprüche das Zaubern
* erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der
* Spruch überhaupt gezaubert werden kann. * Spruch überhaupt gezaubert werden kann.
* (level) die effektive Stärke des Spruchs (= Stufe, auf der der * (level) die effektive Stärke des Spruchs (= Stufe, auf der der
* Spruch gezaubert wird) */ * Spruch gezaubert wird) */
for (rank = 0; rank < MAX_SPELLRANK; rank++) { for (rank = 0; rank < MAX_SPELLRANK; rank++) {
@ -2802,30 +2800,30 @@ void magic(void)
} }
if (cast_level > co->level) { if (cast_level > co->level) {
/* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs
* gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */
if (spl_costtyp(sp) != SPC_FIX) { if (spl_costtyp(sp) != SPC_FIX) {
ADDMSG(&u->faction->msgs, msg_message("missing_components", ADDMSG(&u->faction->msgs, msg_message("missing_components",
"unit spell level", u, sp, cast_level)); "unit spell level", u, sp, cast_level));
} }
} }
/* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt
* werden können */ * werden können */
if (!cancast(u, sp, co->level, co->distance, ord)) { if (!cancast(u, sp, co->level, co->distance, ord)) {
/* die Fehlermeldung wird in cancast generiert */ /* die Fehlermeldung wird in cancast generiert */
continue; continue;
} }
co->force = spellpower(target_r, u, sp, co->level, ord); co->force = spellpower(target_r, u, sp, co->level, ord);
/* die Stärke kann durch Antimagie auf 0 sinken */ /* die Stärke kann durch Antimagie auf 0 sinken */
if (co->force <= 0) { if (co->force <= 0) {
co->force = 0; co->force = 0;
ADDMSG(&u->faction->msgs, msg_message("missing_force", ADDMSG(&u->faction->msgs, msg_message("missing_force",
"unit spell level", u, sp, co->level)); "unit spell level", u, sp, co->level));
} }
/* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde
* kein Ziel gefunden, so ist verify_targets=0. Scheitert der * kein Ziel gefunden, so ist verify_targets=0. Scheitert der
* Spruch an der Magieresistenz, so ist verify_targets = 1, bei * Spruch an der Magieresistenz, so ist verify_targets = 1, bei
* Erfolg auf ganzer Linie ist verify_targets= 2 * Erfolg auf ganzer Linie ist verify_targets= 2
@ -2833,8 +2831,8 @@ void magic(void)
verify_targets(co, &invalid, &resist, &success); verify_targets(co, &invalid, &resist, &success);
if (success + resist == 0) { if (success + resist == 0) {
/* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */
/* keine kosten für den zauber */ /* keine kosten für den zauber */
continue; /* äußere Schleife, nächster Zauberer */ continue; /* äußere Schleife, nächster Zauberer */
} }
else if (co->force > 0 && resist > 0) { else if (co->force > 0 && resist > 0) {
/* einige oder alle Ziele waren magieresistent */ /* einige oder alle Ziele waren magieresistent */
@ -2847,8 +2845,8 @@ void magic(void)
} }
} }
/* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten
* bezahlt werden und die nachfolgenden Sprüche werden teurer */ * bezahlt werden und die nachfolgenden Sprüche werden teurer */
if (co->force > 0) { if (co->force > 0) {
if (fumble(target_r, u, sp, co->level)) { if (fumble(target_r, u, sp, co->level)) {
/* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */
@ -2857,12 +2855,12 @@ void magic(void)
else { else {
co->level = sp->cast(co); co->level = sp->cast(co);
if (co->level <= 0) { if (co->level <= 0) {
/* Kosten nur für real benötige Stufe berechnen */ /* Kosten nur für real benötige Stufe berechnen */
continue; continue;
} }
} }
} }
/* erst bezahlen, dann Kostenzähler erhöhen */ /* erst bezahlen, dann Kostenzähler erhöhen */
if (co->level > 0) { if (co->level > 0) {
pay_spell(u, sp, co->level, co->distance); pay_spell(u, sp, co->level, co->distance);
} }

View File

@ -31,8 +31,7 @@ extern "C" {
void make_zombie(struct unit * u); void make_zombie(struct unit * u);
#define MONSTER_ID 666 #define MONSTER_ID 666
#define is_monsters(f) (f && fval(f, FFL_NPC) && f==get_monsters()) #define is_monsters(f) (fval(f, FFL_NPC) && f==get_monsters())
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2014, Copyright (c) 1998-2014,
Enno Rehling <enno@eressea.de> Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
@ -90,7 +90,7 @@ static attrib_type at_traveldir = {
"traveldir", "traveldir",
DEFAULT_INIT, DEFAULT_INIT,
DEFAULT_FINALIZE, DEFAULT_FINALIZE,
DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */ DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */
a_writechars, a_writechars,
a_readchars a_readchars
}; };
@ -245,15 +245,15 @@ static int ridingcapacity(unit * u)
get_transporters(u->items, &animals, &acap, &vehicles, &vcap); get_transporters(u->items, &animals, &acap, &vehicles, &vcap);
/* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen
** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er
** von zwei Pferden gezogen wird */ ** von zwei Pferden gezogen wird */
animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2);
if (fval(u_race(u), RCF_HORSE)) if (fval(u_race(u), RCF_HORSE))
animals += u->number; animals += u->number;
/* maximal diese Pferde können zum Ziehen benutzt werden */ /* maximal diese Pferde können zum Ziehen benutzt werden */
vehicles = _min(animals / HORSESNEEDED, vehicles); vehicles = _min(animals / HORSESNEEDED, vehicles);
return vehicles * vcap + animals * acap; return vehicles * vcap + animals * acap;
@ -282,7 +282,7 @@ int walkingcapacity(const struct unit *u)
people = u->number; people = u->number;
} }
/* maximal diese Pferde können zum Ziehen benutzt werden */ /* maximal diese Pferde können zum Ziehen benutzt werden */
wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED);
n = wagen_mit_pferden * vcap; n = wagen_mit_pferden * vcap;
@ -295,7 +295,7 @@ int walkingcapacity(const struct unit *u)
/* Genug Trolle, um die Restwagen zu ziehen? */ /* Genug Trolle, um die Restwagen zu ziehen? */
wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde);
/* Wagenkapazität hinzuzählen */ /* Wagenkapazität hinzuzählen */
n += wagen_mit_trollen * vcap; n += wagen_mit_trollen * vcap;
wagen_ohne_pferde -= wagen_mit_trollen; wagen_ohne_pferde -= wagen_mit_trollen;
} }
@ -357,16 +357,16 @@ static int canwalk(unit * u)
if (walkingcapacity(u) - eff_weight(u) >= 0) if (walkingcapacity(u) - eff_weight(u) >= 0)
return E_CANWALK_OK; return E_CANWALK_OK;
/* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne
* Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat
* die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen
* als erlaubt. */ * als erlaubt. */
if (vehicles > maxwagen) if (vehicles > maxwagen)
return E_CANWALK_TOOMANYCARTS; return E_CANWALK_TOOMANYCARTS;
/* Es muß nicht zwingend an den Wagen liegen, aber egal... (man /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man
* könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als
* Fracht draufpaßt) */ * Fracht draufpaßt) */
return E_CANWALK_TOOHEAVY; return E_CANWALK_TOOHEAVY;
} }
@ -663,7 +663,7 @@ int check_ship_allowed(struct ship *sh, const region * r)
bt_harbour = bt_find("harbour"); bt_harbour = bt_find("harbour");
if (sh->region && r_insectstalled(r)) { if (sh->region && r_insectstalled(r)) {
/* insekten dürfen nicht hier rein. haben wir welche? */ /* insekten dürfen nicht hier rein. haben wir welche? */
unit *u; unit *u;
for (u = sh->region->units; u != NULL; u = u->next) { for (u = sh->region->units; u != NULL; u = u->next) {
@ -757,13 +757,13 @@ static void drifting_ships(region * r)
sh->flags |= SF_FISHING; sh->flags |= SF_FISHING;
} }
/* Schiff schon abgetrieben oder durch Zauber geschützt? */ /* Schiff schon abgetrieben oder durch Zauber geschützt? */
if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) {
shp = &sh->next; shp = &sh->next;
continue; continue;
} }
/* Kapitän bestimmen */ /* Kapitän bestimmen */
for (captain = r->units; captain; captain = captain->next) { for (captain = r->units; captain; captain = captain->next) {
if (captain->ship != sh) if (captain->ship != sh)
continue; continue;
@ -773,8 +773,8 @@ static void drifting_ships(region * r)
break; break;
} }
} }
/* Kapitän da? Beschädigt? Genügend Matrosen? /* Kapitän da? Beschädigt? Genügend Matrosen?
* Genügend leicht? Dann ist alles OK. */ * Genügend leicht? Dann ist alles OK. */
assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */
if (captain && sh->size == sh->type->construction->maxsize if (captain && sh->size == sh->type->construction->maxsize
@ -784,7 +784,7 @@ static void drifting_ships(region * r)
} }
/* Auswahl einer Richtung: Zuerst auf Land, dann /* Auswahl einer Richtung: Zuerst auf Land, dann
* zufällig. Falls unmögliches Resultat: vergiß es. */ * zufällig. Falls unmögliches Resultat: vergiß es. */
d_offset = rng_int() % MAXDIRECTIONS; d_offset = rng_int() % MAXDIRECTIONS;
for (d = 0; d != MAXDIRECTIONS; ++d) { for (d = 0; d != MAXDIRECTIONS; ++d) {
region *rn; region *rn;
@ -1335,7 +1335,9 @@ static bool roadto(const region * r, direction_t dir)
region *r2; region *r2;
static const curse_type *roads_ct = NULL; static const curse_type *roads_ct = NULL;
if (dir >= MAXDIRECTIONS || dir < 0) assert(r);
assert(dir<MAXDIRECTIONS);
if (!r || dir >= MAXDIRECTIONS || dir < 0)
return false; return false;
r2 = rconnect(r, dir); r2 = rconnect(r, dir);
if (r == NULL || r2 == NULL) if (r == NULL || r2 == NULL)
@ -1476,12 +1478,12 @@ static void make_route(unit * u, order * ord, region_list ** routep)
/** calculate the speed of a unit /** calculate the speed of a unit
* *
* zu Fuß reist man 1 Region, zu Pferd 2 Regionen. Mit Straßen reist * zu Fuß reist man 1 Region, zu Pferd 2 Regionen. Mit Straßen reist
* man zu Fuß 2, mit Pferden 3 weit. * man zu Fuß 2, mit Pferden 3 weit.
* *
* Berechnet wird das mit BPs. Zu Fuß hat man 4 BPs, zu Pferd 6. * Berechnet wird das mit BPs. Zu Fuß hat man 4 BPs, zu Pferd 6.
* Normalerweise verliert man 3 BP pro Region, bei Straßen nur 2 BP. * Normalerweise verliert man 3 BP pro Region, bei Straßen nur 2 BP.
* Außerdem: Wenn Einheit transportiert, nur halbe BP * Außerdem: Wenn Einheit transportiert, nur halbe BP
*/ */
static int movement_speed(unit * u) static int movement_speed(unit * u)
{ {
@ -1621,7 +1623,7 @@ static const region_list *travel_route(unit * u,
landing = true; landing = true;
} }
else if ((u_race(u)->flags & RCF_WALK) == 0) { else if ((u_race(u)->flags & RCF_WALK) == 0) {
/* Spezialeinheiten, die nicht laufen können. */ /* Spezialeinheiten, die nicht laufen können. */
ADDMSG(&u->faction->msgs, msg_message("detectocean", ADDMSG(&u->faction->msgs, msg_message("detectocean",
"unit region", u, next)); "unit region", u, next));
break; break;
@ -1634,7 +1636,7 @@ static const region_list *travel_route(unit * u,
} }
} }
else { else {
/* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne
* Pferde betreten werden. */ * Pferde betreten werden. */
if (!(canswim(u) || canfly(u))) { if (!(canswim(u) || canfly(u))) {
ADDMSG(&u->faction->msgs, msg_message("detectocean", ADDMSG(&u->faction->msgs, msg_message("detectocean",
@ -1729,7 +1731,7 @@ static const region_list *travel_route(unit * u,
walkmode = 2; walkmode = 2;
} }
/* Berichte über Durchreiseregionen */ /* Berichte über Durchreiseregionen */
if (mode != TRAVEL_TRANSPORTED) { if (mode != TRAVEL_TRANSPORTED) {
arg_regions *ar = var_copy_regions(route_begin, steps - 1); arg_regions *ar = var_copy_regions(route_begin, steps - 1);
@ -1808,7 +1810,7 @@ buildingtype_exists(const region * r, const building_type * bt, bool working)
return false; return false;
} }
/* Prüft, ob Ablegen von einer Küste in eine der erlaubten Richtungen erfolgt. */ /* Prüft, ob Ablegen von einer Küste in eine der erlaubten Richtungen erfolgt. */
static bool check_takeoff(ship * sh, region * from, region * to) static bool check_takeoff(ship * sh, region * from, region * to)
{ {
@ -1858,18 +1860,18 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
return; return;
/* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden
* dann nacheinander ausgeführt. */ * dann nacheinander ausgeführt. */
k = shipspeed(sh, u); k = shipspeed(sh, u);
last_point = starting_point; last_point = starting_point;
current_point = starting_point; current_point = starting_point;
/* die nächste Region, in die man segelt, wird durch movewhere () aus der /* die nächste Region, in die man segelt, wird durch movewhere () aus der
* letzten Region bestimmt. * letzten Region bestimmt.
* *
* Anfangen tun wir bei starting_point. next_point ist beim ersten * Anfangen tun wir bei starting_point. next_point ist beim ersten
* Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige,
* befahrene Region. */ * befahrene Region. */
while (next_point && current_point != next_point && step < k) { while (next_point && current_point != next_point && step < k) {
@ -1916,7 +1918,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
bool storm = true; bool storm = true;
int d_offset = rng_int() % MAXDIRECTIONS; int d_offset = rng_int() % MAXDIRECTIONS;
direction_t d; direction_t d;
/* Sturm nur, wenn nächste Region Hochsee ist. */ /* Sturm nur, wenn nächste Region Hochsee ist. */
for (d = 0; d != MAXDIRECTIONS; ++d) { for (d = 0; d != MAXDIRECTIONS; ++d) {
direction_t dnext = (direction_t)((d + d_offset) % MAXDIRECTIONS); direction_t dnext = (direction_t)((d + d_offset) % MAXDIRECTIONS);
region *rn = rconnect(current_point, dnext); region *rn = rconnect(current_point, dnext);
@ -2052,16 +2054,16 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
sh = NULL; sh = NULL;
} }
/* Nun enthält current_point die Region, in der das Schiff seine Runde /* Nun enthält current_point die Region, in der das Schiff seine Runde
* beendet hat. Wir generieren hier ein Ereignis für den Spieler, das * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das
* ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck
* gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins
* Inland zu segeln versuchte */ * Inland zu segeln versuchte */
if (sh != NULL && fval(sh, SF_MOVED)) { if (sh != NULL && fval(sh, SF_MOVED)) {
unit *harbourmaster; unit *harbourmaster;
/* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten
* transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */
cycle_route(ord, u, step); cycle_route(ord, u, step);
set_order(&u->thisorder, NULL); set_order(&u->thisorder, NULL);
if (!move_on_land) { if (!move_on_land) {
@ -2086,7 +2088,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
sh = move_ship(sh, starting_point, current_point, *routep); sh = move_ship(sh, starting_point, current_point, *routep);
/* Hafengebühren ? */ /* Hafengebühren ? */
harbourmaster = owner_buildingtyp(current_point, bt_find("harbour")); harbourmaster = owner_buildingtyp(current_point, bt_find("harbour"));
if (sh && harbourmaster != NULL) { if (sh && harbourmaster != NULL) {
@ -2128,20 +2130,6 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
} }
} }
unit *get_captain(const ship * sh)
{
const region *r = sh->region;
unit *u;
for (u = r->units; u; u = u->next) {
if (u->ship == sh && u->number
&& eff_skill(u, SK_SAILING, r) >= sh->type->cptskill)
return u;
}
return NULL;
}
/* Segeln, Wandern, Reiten /* Segeln, Wandern, Reiten
* when this routine returns a non-zero value, movement for the region needs * when this routine returns a non-zero value, movement for the region needs
* to be done again because of followers that got new MOVE orders. * to be done again because of followers that got new MOVE orders.
@ -2434,7 +2422,7 @@ static void piracy_cmd(unit * u, struct order *ord)
/* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */
if (target_dir == NODIRECTION) { if (target_dir == NODIRECTION) {
/* Einheit ist also Kapitän. Jetzt gucken, in wievielen /* Einheit ist also Kapitän. Jetzt gucken, in wievielen
* Nachbarregionen potentielle Opfer sind. */ * Nachbarregionen potentielle Opfer sind. */
for (dir = 0; dir < MAXDIRECTIONS; dir++) { for (dir = 0; dir < MAXDIRECTIONS; dir++) {
@ -2493,7 +2481,7 @@ static void piracy_cmd(unit * u, struct order *ord)
set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s",
LOC(u->faction->locale, directions[target_dir]))); LOC(u->faction->locale, directions[target_dir])));
/* Bewegung ausführen */ /* Bewegung ausführen */
init_order(u->thisorder); init_order(u->thisorder);
move(u, true); move(u, true);
} }
@ -2604,7 +2592,7 @@ static int hunt(unit * u, order * ord)
/* NACH ignorieren und Parsing initialisieren. */ /* NACH ignorieren und Parsing initialisieren. */
init_tokens_str(command); init_tokens_str(command);
getstrtoken(); getstrtoken();
/* NACH ausführen */ /* NACH ausführen */
move(u, false); move(u, false);
return 1; /* true -> Einheitenliste von vorne durchgehen */ return 1; /* true -> Einheitenliste von vorne durchgehen */
} }
@ -2803,7 +2791,7 @@ void movement(void)
if (repeat) if (repeat)
continue; continue;
if (ships == 0) { if (ships == 0) {
/* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */
drifting_ships(r); drifting_ships(r);
} }
r = r->next; r = r->next;

View File

@ -64,7 +64,6 @@ extern "C" {
int enoughsailors(const struct ship *sh, const struct region *r); int enoughsailors(const struct ship *sh, const struct region *r);
bool canswim(struct unit *u); bool canswim(struct unit *u);
bool canfly(struct unit *u); bool canfly(struct unit *u);
struct unit *get_captain(const struct ship *sh);
void travelthru(const struct unit *u, struct region *r); void travelthru(const struct unit *u, struct region *r);
struct ship *move_ship(struct ship *sh, struct region *from, struct ship *move_ship(struct ship *sh, struct region *from,
struct region *to, struct region_list *route); struct region *to, struct region_list *route);

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -552,9 +552,9 @@ static void nr_curses(stream *out, int indent, const faction *viewer, objtype_t
region *r; region *r;
/* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei /* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei
* Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden. * Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden.
* Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer. * Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer.
* Spezialfälle (besonderes Talent, verursachender Magier usw. werde * Spezialfälle (besonderes Talent, verursachender Magier usw. werde
* bei jedem curse gesondert behandelt. */ * bei jedem curse gesondert behandelt. */
if (typ == TYP_SHIP) { if (typ == TYP_SHIP) {
ship *sh = (ship *)obj; ship *sh = (ship *)obj;
@ -840,7 +840,7 @@ bool see_border(const connection * b, const faction * f, const region * r)
static void describe(stream *out, const seen_region * sr, faction * f) static void describe(stream *out, const seen_region * sr, faction * f)
{ {
const region *r = sr->r; const region *r;
int n; int n;
bool dh; bool dh;
direction_t d; direction_t d;
@ -862,6 +862,11 @@ static void describe(stream *out, const seen_region * sr, faction * f)
size_t size = sizeof(buf); size_t size = sizeof(buf);
int bytes; int bytes;
assert(out);
assert(f);
assert(sr);
r = sr->r;
for (d = 0; d != MAXDIRECTIONS; d++) { for (d = 0; d != MAXDIRECTIONS; d++) {
/* Nachbarregionen, die gesehen werden, ermitteln */ /* Nachbarregionen, die gesehen werden, ermitteln */
region *r2 = rconnect(r, d); region *r2 = rconnect(r, d);
@ -953,7 +958,7 @@ static void describe(stream *out, const seen_region * sr, faction * f)
} }
/* iron & stone */ /* iron & stone */
if (sr->mode == see_unit && f != (faction *)NULL) { if (sr->mode == see_unit) {
resource_report result[MAX_RAWMATERIALS]; resource_report result[MAX_RAWMATERIALS];
int n, numresults = report_resources(sr, result, MAX_RAWMATERIALS, f); int n, numresults = report_resources(sr, result, MAX_RAWMATERIALS, f);
@ -1188,7 +1193,7 @@ static void describe(stream *out, const seen_region * sr, faction * f)
} }
} }
/* Wirkungen permanenter Sprüche */ /* Wirkungen permanenter Sprüche */
nr_curses(out, 0, f, TYP_REGION, r); nr_curses(out, 0, f, TYP_REGION, r);
n = 0; n = 0;
@ -1410,7 +1415,6 @@ static void durchreisende(stream *out, const region * r, const faction * f)
} }
} }
} }
/* TODO: finish localization */
if (size > 0) { if (size > 0) {
if (maxtravel == 1) { if (maxtravel == 1) {
bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one")); bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one"));

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -53,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
/* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und /* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und
* Spionage des Spions */ * Spionage des Spions */
@ -61,7 +62,7 @@ void spy_message(int spy, const unit * u, const unit * target)
const char *str = report_kampfstatus(target, u->faction->locale); const char *str = report_kampfstatus(target, u->faction->locale);
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u, ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
target, str)); target, str));
if (spy > 20) { if (spy > 20) {
sc_mage *mage = get_mage(target); sc_mage *mage = get_mage(target);
/* for mages, spells and magic school */ /* for mages, spells and magic school */
@ -375,7 +376,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
} }
else if (skilldiff < 0) { else if (skilldiff < 0) {
/* tell the unit that the attempt was detected: */ /* tell the unit that the attempt was detected: */
ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg, ADDMSG(&u->faction->msgs, msg_message(destruction_detected_msg,
"ship unit", sh, u)); "ship unit", sh, u));
/* tell the enemy whodunit: */ /* tell the enemy whodunit: */
if (u2) { if (u2) {
@ -394,7 +395,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
return 1; /* success */ return 1; /* success */
} }
static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) static void sink_ship(region * r, ship * sh, unit * saboteur)
{ {
unit **ui, *u; unit **ui, *u;
region *safety = r; region *safety = r;
@ -404,6 +405,9 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
message *sink_msg = NULL; message *sink_msg = NULL;
faction *f; faction *f;
assert(r);
assert(sh);
assert(saboteur);
for (f = NULL, u = r->units; u; u = u->next) { for (f = NULL, u = r->units; u; u = u->next) {
/* slight optimization to avoid dereferencing u->faction each time */ /* slight optimization to avoid dereferencing u->faction each time */
if (f != u->faction) { if (f != u->faction) {
@ -426,7 +430,7 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
} }
} }
} }
for (ui = &r->units; *ui; ui = &(*ui)->next) { for (ui = &r->units; *ui;) {
unit *u = *ui; unit *u = *ui;
/* inform this faction about the sinking ship: */ /* inform this faction about the sinking ship: */
@ -471,12 +475,13 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
add_message(&u->faction->msgs, msg); add_message(&u->faction->msgs, msg);
msg_release(msg); msg_release(msg);
if (dead == u->number) { if (dead == u->number) {
/* the poor creature, she dies */ if (remove_unit(ui, u) == 0) {
if (remove_unit(ui, u) != 0) { /* ui is already pointing at u->next */
ui = &u->next; continue;
} }
} }
} }
ui = &u->next;
} }
if (sink_msg) if (sink_msg)
msg_release(sink_msg); msg_release(sink_msg);
@ -487,19 +492,21 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
int sabotage_cmd(unit * u, struct order *ord) int sabotage_cmd(unit * u, struct order *ord)
{ {
const char *s; const char *s;
int i; param_t p;
ship *sh; ship *sh;
unit *u2; unit *u2;
char buffer[DISPLAYSIZE]; region *r;
region *r = u->region; int skdiff = INT_MAX;
int skdiff;
assert(u);
assert(ord);
init_order(ord); init_order(ord);
s = getstrtoken(); s = getstrtoken();
i = findparam(s, u->faction->locale); p = findparam(s, u->faction->locale);
switch (i) { switch (p) {
case P_SHIP: case P_SHIP:
sh = u->ship; sh = u->ship;
if (!sh) { if (!sh) {
@ -507,10 +514,13 @@ int sabotage_cmd(unit * u, struct order *ord)
return 0; return 0;
} }
u2 = ship_owner(sh); u2 = ship_owner(sh);
skdiff = r = u->region;
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); if (u2->faction != u->faction) {
skdiff =
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
}
if (try_destruction(u, u2, sh, skdiff)) { if (try_destruction(u, u2, sh, skdiff)) {
sink_ship(r, sh, buffer, u); sink_ship(r, sh, u);
} }
break; break;
default: default:

View File

@ -5,9 +5,12 @@
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <kernel/faction.h> #include <kernel/faction.h>
#include <kernel/ship.h>
#include <kernel/order.h>
#include <kernel/item.h> #include <kernel/item.h>
#include <kernel/messages.h> #include <kernel/messages.h>
#include <util/attrib.h> #include <util/attrib.h>
#include <util/language.h>
#include <util/message.h> #include <util/message.h>
#include <util/crmessage.h> #include <util/crmessage.h>
#include <tests.h> #include <tests.h>
@ -16,6 +19,7 @@
#include "spy.h" #include "spy.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <CuTest.h> #include <CuTest.h>
@ -65,9 +69,9 @@ static void test_simple_spy_message(CuTest *tc) {
static void set_factionstealth(unit *u, faction *f) { static void set_factionstealth(unit *u, faction *f) {
attrib *a = a_find(u->attribs, &at_otherfaction); attrib *a = a_find(u->attribs, &at_otherfaction);
if (!a) if (!a)
a = a_add(&u->attribs, make_otherfaction(f)); a = a_add(&u->attribs, make_otherfaction(f));
else else
a->data.v = f; a->data.v = f;
} }
static void test_all_spy_message(CuTest *tc) { static void test_all_spy_message(CuTest *tc) {
@ -89,21 +93,105 @@ static void test_all_spy_message(CuTest *tc) {
spy_message(99, fix.spy, fix.victim); spy_message(99, fix.spy, fix.victim);
assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 5, true, assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 5, true,
M_BASE, M_BASE,
M_MAGE, M_MAGE,
M_FACTION, M_FACTION,
M_SKILLS, M_SKILLS,
M_ITEMS); M_ITEMS);
test_cleanup(); test_cleanup();
} }
static void setup_sabotage(void) {
struct locale *lang;
test_cleanup();
lang = get_or_create_locale("de");
locale_setstring(lang, parameters[P_SHIP], "SCHIFF");
test_create_world();
init_locales();
}
static void test_sabotage_self(CuTest *tc) {
unit *u;
region *r;
order *ord;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
assert(u && u->faction && u->region == r);
u->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u->ship);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
CuAssertIntEquals(tc, 0, sabotage_cmd(u, ord));
CuAssertPtrEquals(tc, 0, r->ships);
test_cleanup();
}
static void test_sabotage_other_fail(CuTest *tc) {
unit *u, *u2;
region *r;
order *ord;
message *msg;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
assert(u && u2);
u2->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u2->ship);
u->ship = u2->ship;
ship_update_owner(u->ship);
assert(ship_owner(u->ship) == u);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord));
msg = test_get_last_message(u2->faction->msgs);
CuAssertStrEquals(tc, "destroy_ship_1", test_get_messagetype(msg));
msg = test_get_last_message(u->faction->msgs);
CuAssertStrEquals(tc, "destroy_ship_3", test_get_messagetype(msg));
CuAssertPtrNotNull(tc, r->ships);
test_cleanup();
}
static void test_sabotage_other_success(CuTest *tc) {
unit *u, *u2;
region *r;
order *ord;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
assert(u && u2);
u2->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u2->ship);
u->ship = u2->ship;
ship_update_owner(u->ship);
assert(ship_owner(u->ship) == u);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
set_level(u2, SK_SPY, 1);
CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord));
CuAssertPtrEquals(tc, 0, r->ships);
test_cleanup();
}
CuSuite *get_spy_suite(void) CuSuite *get_spy_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_simple_spy_message); SUITE_ADD_TEST(suite, test_simple_spy_message);
SUITE_ADD_TEST(suite, test_all_spy_message); SUITE_ADD_TEST(suite, test_all_spy_message);
return suite; SUITE_ADD_TEST(suite, test_sabotage_self);
SUITE_ADD_TEST(suite, test_sabotage_other_fail);
SUITE_ADD_TEST(suite, test_sabotage_other_success);
return suite;
} }

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -542,6 +542,9 @@ int learn_cmd(unit * u, order * ord)
int maxalchemy = 0; int maxalchemy = 0;
int speed_rule = (study_rule_t)get_param_int(global.parameters, "study.speedup", 0); int speed_rule = (study_rule_t)get_param_int(global.parameters, "study.speedup", 0);
static int learn_newskills = -1; static int learn_newskills = -1;
struct building *b = inside_building(u);
const struct building_type *btype = b ? b->type : NULL;
if (learn_newskills < 0) { if (learn_newskills < 0) {
const char *str = get_param(global.parameters, "study.newskills"); const char *str = get_param(global.parameters, "study.newskills");
if (str && strcmp(str, "false") == 0) if (str && strcmp(str, "false") == 0)
@ -603,220 +606,217 @@ int learn_cmd(unit * u, order * ord)
return 0; return 0;
} }
/* Akademie: */ /* Akademie: */
{ b = inside_building(u);
struct building *b = inside_building(u); btype = b ? b->type : NULL;
const struct building_type *btype = b ? b->type : NULL;
if (btype && btype == bt_find("academy")) { if (btype && btype == bt_find("academy")) {
studycost = _max(50, studycost * 2); studycost = _max(50, studycost * 2);
} }
}
if (sk == SK_MAGIC) { if (sk == SK_MAGIC) {
if (u->number > 1) { if (u->number > 1) {
cmistake(u, ord, 106, MSG_MAGIC); cmistake(u, ord, 106, MSG_MAGIC);
return 0; return 0;
} }
if (is_familiar(u)) { if (is_familiar(u)) {
/* Vertraute zaehlen nicht zu den Magiern einer Partei, /* Vertraute zaehlen nicht zu den Magiern einer Partei,
* koennen aber nur Graue Magie lernen */ * koennen aber nur Graue Magie lernen */
mtyp = M_GRAY; mtyp = M_GRAY;
if (!is_mage(u)) if (!is_mage(u))
create_mage(u, mtyp); create_mage(u, mtyp);
} }
else if (!has_skill(u, SK_MAGIC)) { else if (!has_skill(u, SK_MAGIC)) {
int mmax = skill_limit(u->faction, SK_MAGIC); int mmax = skill_limit(u->faction, SK_MAGIC);
/* Die Einheit ist noch kein Magier */ /* Die Einheit ist noch kein Magier */
if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) { if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians", ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians",
"amount", mmax)); "amount", mmax));
return 0; return 0;
} }
mtyp = getmagicskill(u->faction->locale); mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE || mtyp == M_GRAY) { if (mtyp == M_NONE || mtyp == M_GRAY) {
/* wurde kein Magiegebiet angegeben, wird davon /* wurde kein Magiegebiet angegeben, wird davon
* ausgegangen, dass das normal gelernt werden soll */ * ausgegangen, dass das normal gelernt werden soll */
if (u->faction->magiegebiet != 0) { if (u->faction->magiegebiet != 0) {
mtyp = u->faction->magiegebiet; mtyp = u->faction->magiegebiet;
} }
else { else {
/* Es wurde kein Magiegebiet angegeben und die Partei /* Es wurde kein Magiegebiet angegeben und die Partei
* hat noch keins gewaehlt. */ * hat noch keins gewaehlt. */
mtyp = getmagicskill(u->faction->locale); mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) { if (mtyp == M_NONE) {
cmistake(u, ord, 178, MSG_MAGIC); cmistake(u, ord, 178, MSG_MAGIC);
return 0; return 0;
} }
} }
} }
if (mtyp != u->faction->magiegebiet) { if (mtyp != u->faction->magiegebiet) {
/* Es wurde versucht, ein anderes Magiegebiet zu lernen /* Es wurde versucht, ein anderes Magiegebiet zu lernen
* als das der Partei */ * als das der Partei */
if (u->faction->magiegebiet != 0) { if (u->faction->magiegebiet != 0) {
cmistake(u, ord, 179, MSG_MAGIC); cmistake(u, ord, 179, MSG_MAGIC);
return 0; return 0;
} }
else { else {
/* Lernt zum ersten mal Magie und legt damit das /* Lernt zum ersten mal Magie und legt damit das
* Magiegebiet der Partei fest */ * Magiegebiet der Partei fest */
u->faction->magiegebiet = mtyp; u->faction->magiegebiet = mtyp;
} }
} }
if (!is_mage(u)) if (!is_mage(u))
create_mage(u, mtyp); create_mage(u, mtyp);
} }
else { else {
/* ist schon ein Magier und kein Vertrauter */ /* ist schon ein Magier und kein Vertrauter */
if (u->faction->magiegebiet == 0) { if (u->faction->magiegebiet == 0) {
/* die Partei hat noch kein Magiegebiet gewaehlt. */ /* die Partei hat noch kein Magiegebiet gewaehlt. */
mtyp = getmagicskill(u->faction->locale); mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) { if (mtyp == M_NONE) {
mtyp = getmagicskill(u->faction->locale); mtyp = getmagicskill(u->faction->locale);
if (mtyp == M_NONE) { if (mtyp == M_NONE) {
cmistake(u, ord, 178, MSG_MAGIC); cmistake(u, ord, 178, MSG_MAGIC);
return 0; return 0;
} }
} }
/* Legt damit das Magiegebiet der Partei fest */ /* Legt damit das Magiegebiet der Partei fest */
u->faction->magiegebiet = mtyp; u->faction->magiegebiet = mtyp;
} }
} }
} }
if (sk == SK_ALCHEMY) { if (sk == SK_ALCHEMY) {
maxalchemy = eff_skill(u, SK_ALCHEMY, r); maxalchemy = eff_skill(u, SK_ALCHEMY, r);
if (!has_skill(u, SK_ALCHEMY)) { if (!has_skill(u, SK_ALCHEMY)) {
int amax = skill_limit(u->faction, SK_ALCHEMY); int amax = skill_limit(u->faction, SK_ALCHEMY);
if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) { if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists", ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists",
"amount", amax)); "amount", amax));
return 0; return 0;
} }
} }
} }
if (studycost) { if (studycost) {
int cost = studycost * u->number; int cost = studycost * u->number;
money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost); money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost);
money = _min(money, cost); money = _min(money, cost);
} }
if (money < studycost * u->number) { if (money < studycost * u->number) {
studycost = p; /* Ohne Univertreurung */ studycost = p; /* Ohne Univertreurung */
money = _min(money, studycost); money = _min(money, studycost);
if (p > 0 && money < studycost * u->number) { if (p > 0 && money < studycost * u->number) {
cmistake(u, ord, 65, MSG_EVENT); cmistake(u, ord, 65, MSG_EVENT);
multi = money / (double)(studycost * u->number); multi = money / (double)(studycost * u->number);
} }
} }
if (teach == NULL) { if (teach == NULL) {
a = a_add(&u->attribs, a_new(&at_learning)); a = a_add(&u->attribs, a_new(&at_learning));
teach = (teaching_info *)a->data.v; teach = (teaching_info *)a->data.v;
teach->teachers[0] = 0; assert(teach);
} teach->teachers[0] = 0;
if (money > 0) { }
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money); if (money > 0) {
ADDMSG(&u->faction->msgs, msg_message("studycost", use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money);
"unit region cost skill", u, u->region, money, sk)); ADDMSG(&u->faction->msgs, msg_message("studycost",
} "unit region cost skill", u, u->region, money, sk));
}
if (get_effect(u, oldpotiontype[P_WISE])) { if (get_effect(u, oldpotiontype[P_WISE])) {
l = _min(u->number, get_effect(u, oldpotiontype[P_WISE])); l = _min(u->number, get_effect(u, oldpotiontype[P_WISE]));
teach->value += l * 10; teach->value += l * 10;
change_effect(u, oldpotiontype[P_WISE], -l); change_effect(u, oldpotiontype[P_WISE], -l);
} }
if (get_effect(u, oldpotiontype[P_FOOL])) { if (get_effect(u, oldpotiontype[P_FOOL])) {
l = _min(u->number, get_effect(u, oldpotiontype[P_FOOL])); l = _min(u->number, get_effect(u, oldpotiontype[P_FOOL]));
teach->value -= l * 30; teach->value -= l * 30;
change_effect(u, oldpotiontype[P_FOOL], -l); change_effect(u, oldpotiontype[P_FOOL], -l);
} }
if (p != studycost) { if (p != studycost) {
/* ist_in_gebaeude(r, u, BT_UNIVERSITAET) == 1) { */ /* ist_in_gebaeude(r, u, BT_UNIVERSITAET) == 1) { */
/* p ist Kosten ohne Uni, studycost mit; wenn /* p ist Kosten ohne Uni, studycost mit; wenn
* p!=studycost, ist die Einheit zwangsweise * p!=studycost, ist die Einheit zwangsweise
* in einer Uni */ * in einer Uni */
teach->value += u->number * 10; teach->value += u->number * 10;
} }
if (is_cursed(r->attribs, C_BADLEARN, 0)) { if (is_cursed(r->attribs, C_BADLEARN, 0)) {
teach->value -= u->number * 10; teach->value -= u->number * 10;
} }
multi *= study_speedup(u, sk, speed_rule); multi *= study_speedup(u, sk, speed_rule);
days = study_days(u, sk); days = study_days(u, sk);
days = (int)((days + teach->value) * multi); days = (int)((days + teach->value) * multi);
/* the artacademy currently improves the learning of entertainment /* the artacademy currently improves the learning of entertainment
of all units in the region, to be able to make it cumulative with of all units in the region, to be able to make it cumulative with
with an academy */ with an academy */
if (sk == SK_ENTERTAINMENT if (sk == SK_ENTERTAINMENT
&& buildingtype_exists(r, bt_find("artacademy"), false)) { && buildingtype_exists(r, bt_find("artacademy"), false)) {
days *= 2; days *= 2;
} }
if (fval(u, UFL_HUNGER)) if (fval(u, UFL_HUNGER))
days /= 2; days /= 2;
while (days) { while (days) {
if (days >= u->number * 30) { if (days >= u->number * 30) {
learn_skill(u, sk, 1.0); learn_skill(u, sk, 1.0);
days -= u->number * 30; days -= u->number * 30;
} }
else { else {
double chance = (double)days / u->number / 30; double chance = (double)days / u->number / 30;
learn_skill(u, sk, chance); learn_skill(u, sk, chance);
days = 0; days = 0;
} }
} }
if (a != NULL) { if (a != NULL) {
if (teach != NULL) { int index = 0;
int index = 0; while (teach->teachers[index] && index != MAXTEACHERS) {
while (teach->teachers[index] && index != MAXTEACHERS) { unit *teacher = teach->teachers[index++];
unit *teacher = teach->teachers[index++]; if (teacher->faction != u->faction) {
if (teacher->faction != u->faction) { bool feedback = alliedunit(u, teacher->faction, HELP_GUARD);
bool feedback = alliedunit(u, teacher->faction, HELP_GUARD); if (feedback) {
if (feedback) { ADDMSG(&teacher->faction->msgs, msg_message("teach_teacher",
ADDMSG(&teacher->faction->msgs, msg_message("teach_teacher", "teacher student skill level", teacher, u, sk,
"teacher student skill level", teacher, u, sk, effskill(u, sk)));
effskill(u, sk))); }
} ADDMSG(&u->faction->msgs, msg_message("teach_student",
ADDMSG(&u->faction->msgs, msg_message("teach_student", "teacher student skill", teacher, u, sk));
"teacher student skill", teacher, u, sk)); }
} }
} a_remove(&u->attribs, a);
} a = NULL;
a_remove(&u->attribs, a); }
a = NULL; fset(u, UFL_LONGACTION | UFL_NOTMOVING);
}
fset(u, UFL_LONGACTION | UFL_NOTMOVING);
/* Anzeigen neuer Traenke */ /* Anzeigen neuer Traenke */
/* Spruchlistenaktualiesierung ist in Regeneration */ /* Spruchlistenaktualiesierung ist in Regeneration */
if (sk == SK_ALCHEMY) { if (sk == SK_ALCHEMY) {
const potion_type *ptype; const potion_type *ptype;
faction *f = u->faction; faction *f = u->faction;
int skill = eff_skill(u, SK_ALCHEMY, r); int skill = eff_skill(u, SK_ALCHEMY, r);
if (skill > maxalchemy) { if (skill > maxalchemy) {
for (ptype = potiontypes; ptype; ptype = ptype->next) { for (ptype = potiontypes; ptype; ptype = ptype->next) {
if (skill == ptype->level * 2) { if (skill == ptype->level * 2) {
attrib *a = a_find(f->attribs, &at_showitem); attrib *a = a_find(f->attribs, &at_showitem);
while (a && a->type == &at_showitem && a->data.v != ptype) while (a && a->type == &at_showitem && a->data.v != ptype)
a = a->next; a = a->next;
if (a == NULL || a->type != &at_showitem) { if (a == NULL || a->type != &at_showitem) {
a = a_add(&f->attribs, a_new(&at_showitem)); a = a_add(&f->attribs, a_new(&at_showitem));
a->data.v = (void *)ptype->itype; a->data.v = (void *)ptype->itype;
} }
} }
} }
} }
} }
else if (sk == SK_MAGIC) { else if (sk == SK_MAGIC) {
sc_mage *mage = get_mage(u); sc_mage *mage = get_mage(u);
if (!mage) { if (!mage) {
mage = create_mage(u, u->faction->magiegebiet); mage = create_mage(u, u->faction->magiegebiet);
} }
} }
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
/* /*
* +-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de> * +-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
* | | Enno Rehling <enno@eressea.de> * | | Enno Rehling <enno@eressea.de>
* | Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de> * | Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>

View File

@ -1,4 +1,4 @@
#include <platform.h> #include <platform.h>
#include "upkeep.h" #include "upkeep.h"
#include <kernel/config.h> #include <kernel/config.h>
@ -82,6 +82,7 @@ void test_upkeep_from_pool(CuTest * tc)
assert(i_silver); assert(i_silver);
r = findregion(0, 0); r = findregion(0, 0);
u1 = test_create_unit(test_create_faction(test_create_race("human")), r); u1 = test_create_unit(test_create_faction(test_create_race("human")), r);
assert(u1);
u2 = test_create_unit(u1->faction, r); u2 = test_create_unit(u1->faction, r);
assert(r && u1 && u2); assert(r && u1 && u2);

View File

@ -1,4 +1,4 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -69,7 +69,7 @@ static attrib_type *at_find(unsigned int hk)
{ {
const char *translate[3][2] = { const char *translate[3][2] = {
{ "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */ { "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */
{ "verzaubert", "curse" }, /* remapping: früher verzaubert, jetzt curse */ { "verzaubert", "curse" }, /* remapping: früher verzaubert, jetzt curse */
{ NULL, NULL } { NULL, NULL }
}; };
attrib_type *find = at_hash[hk % MAXATHASH]; attrib_type *find = at_hash[hk % MAXATHASH];
@ -110,11 +110,11 @@ const attrib *a_findc(const attrib * a, const attrib_type * at)
static attrib *a_insert(attrib * head, attrib * a) static attrib *a_insert(attrib * head, attrib * a)
{ {
attrib **pa = &head->next; attrib **pa;
assert(!(a->type->flags & ATF_UNIQUE)); assert(!(a->type->flags & ATF_UNIQUE));
assert(head && head->type == a->type); assert(head && head->type == a->type);
pa = &head->next;
while (*pa && (*pa)->type == a->type) { while (*pa && (*pa)->type == a->type) {
pa = &(*pa)->next; pa = &(*pa)->next;
} }
@ -250,7 +250,7 @@ int a_age(attrib ** p)
{ {
attrib **ap = p; attrib **ap = p;
/* Attribute altern, und die Entfernung (age()==0) eines Attributs /* Attribute altern, und die Entfernung (age()==0) eines Attributs
* hat Einfluß auf den Besitzer */ * hat Einfluß auf den Besitzer */
while (*ap) { while (*ap) {
attrib *a = *ap; attrib *a = *ap;
if (a->type->age) { if (a->type->age) {

View File

@ -1,4 +1,4 @@
/* /*
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de> +-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea.de> | | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de> | Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
@ -54,13 +54,13 @@ cp_convert(const char *format, char *buffer, size_t length, int codepage)
char *pos = buffer; char *pos = buffer;
while (pos + 1 < buffer + length && *input) { while (pos + 1 < buffer + length && *input) {
size_t length = 0; size_t size = 0;
int result = 0; int result = 0;
if (codepage == 437) { if (codepage == 437) {
result = unicode_utf8_to_cp437(pos, input, &length); result = unicode_utf8_to_cp437(pos, input, &size);
} }
else if (codepage == 1252) { else if (codepage == 1252) {
result = unicode_utf8_to_cp1252(pos, input, &length); result = unicode_utf8_to_cp1252(pos, input, &size);
} }
if (result != 0) { if (result != 0) {
*pos = 0; /* just in case caller ignores our return value */ *pos = 0; /* just in case caller ignores our return value */