Merge pull request #771 from ennorehling/develop

latest 3.16 changes
This commit is contained in:
Enno Rehling 2018-02-25 11:53:58 +01:00 committed by GitHub
commit ac3fe6228c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 255 additions and 202 deletions

View file

@ -37,10 +37,10 @@ BRANCH=$(git status -s -b | head -1 | cut -d\ -f 2 | sed 's/\..*//')
if [ "$BRANCH" = "master" ] ; then if [ "$BRANCH" = "master" ] ; then
VERSION=$(git describe --match 'v*.*.*' --tags | sed 's/^v//') VERSION=$(git describe --match 'v*.*.*' --tags | sed 's/^v//')
echo "$BRANCH $VERSION" echo "$BRANCH $VERSION"
CMAKE_ARGS="-DERESSEA_VERSION=$VERSION ${CMAKE_ARGS}" CMAKE_ARGS="-DERESSEA_VERSION:STRING=$VERSION ${CMAKE_ARGS}"
else else
REV=$(git rev-parse --short HEAD) REV=$(git rev-parse --short HEAD)
CMAKE_ARGS="-DERESSEA_BUILDNO=$REV $CMAKE_ARGS" CMAKE_ARGS="-DERESSEA_BUILDNO:STRING=$REV $CMAKE_ARGS"
fi fi
cmake ${CMAKE_ARGS} cmake ${CMAKE_ARGS}

View file

@ -9,6 +9,7 @@ function setup()
eressea.settings.set("rules.ship.storms", "0") eressea.settings.set("rules.ship.storms", "0")
eressea.settings.set("rules.encounters", "0") eressea.settings.set("rules.encounters", "0")
eressea.settings.set("magic.regeneration.enable", "0") eressea.settings.set("magic.regeneration.enable", "0")
eressea.settings.set("study.random_progress", "0")
end end
function test_water_of_life() function test_water_of_life()

View file

@ -94,7 +94,7 @@ static int read_seenspell(variant *var, void *owner, struct gamedata *data)
} }
sp = find_spell(token); sp = find_spell(token);
if (!sp) { if (!sp) {
log_info("read_seenspell: could not find spell '%s'\n", token); log_error("read_seenspell: could not find spell '%s'\n", token);
return AT_READ_FAIL; return AT_READ_FAIL;
} }
var->v = sp; var->v = sp;

View file

@ -55,7 +55,7 @@ static int tolua_bufunit(lua_State * L) {
if (f) { if (f) {
char buf[8192]; char buf[8192];
int mode = (int)tolua_tonumber(L, 3, (int)seen_unit); int mode = (int)tolua_tonumber(L, 3, (int)seen_unit);
bufunit(f, u, 0, mode, buf, sizeof(buf)); bufunit(f, u, mode, buf, sizeof(buf));
tolua_pushstring(L, buf); tolua_pushstring(L, buf);
return 1; return 1;
} }

View file

@ -458,8 +458,7 @@ static int tolua_write_report(lua_State * L)
{ {
faction *f = (faction *)tolua_tousertype(L, 1, 0); faction *f = (faction *)tolua_tousertype(L, 1, 0);
if (f) { if (f) {
time_t ltime = time(0); int result = write_reports(f);
int result = write_reports(f, ltime);
lua_pushinteger(L, result); lua_pushinteger(L, result);
} }
else { else {
@ -924,7 +923,7 @@ static int tolua_report_unit(lua_State * L)
char buffer[512]; char buffer[512];
unit *u = (unit *)tolua_tousertype(L, 1, 0); unit *u = (unit *)tolua_tousertype(L, 1, 0);
faction *f = (faction *)tolua_tousertype(L, 2, 0); faction *f = (faction *)tolua_tousertype(L, 2, 0);
bufunit(f, u, 0, seen_unit, buffer, sizeof(buffer)); bufunit(f, u, seen_unit, buffer, sizeof(buffer));
tolua_pushstring(L, buffer); tolua_pushstring(L, buffer);
return 1; return 1;
} }

View file

@ -18,6 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_GC_ECONOMY #ifndef H_GC_ECONOMY
#define H_GC_ECONOMY #define H_GC_ECONOMY
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View file

@ -4,6 +4,7 @@
#include "kernel/calendar.h" #include "kernel/calendar.h"
#include "kernel/config.h" #include "kernel/config.h"
#include "kernel/curse.h" #include "kernel/curse.h"
#include "kernel/faction.h"
#include "kernel/building.h" #include "kernel/building.h"
#include "kernel/equipment.h" #include "kernel/equipment.h"
#include "kernel/item.h" #include "kernel/item.h"
@ -37,22 +38,17 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
/* manually free() everything at exit? */
#undef CLEANUP_CODE
void game_done(void) void game_done(void)
{ {
#undef CLEANUP_CODE log_dead_factions();
#ifdef CLEANUP_CODE #ifdef CLEANUP_CODE
/* Diese Routine enfernt allen allokierten Speicher wieder. Das ist nur free_gamedata();
* zum Debugging interessant, wenn man Leak Detection hat, und nach
* nicht freigegebenem Speicher sucht, der nicht bis zum Ende benoetigt
* wird (temporaere Hilsstrukturen) */
free_game();
creport_cleanup(); creport_cleanup();
#ifdef REPORT_FORMAT_NR
report_cleanup(); report_cleanup();
#endif
#endif
calendar_cleanup(); calendar_cleanup();
free_functions(); free_functions();
free_config(); free_config();
@ -60,6 +56,7 @@ void game_done(void)
free_locales(); free_locales();
kernel_done(); kernel_done();
dblib_close(); dblib_close();
#endif
} }
void game_init(void) void game_init(void)

View file

@ -778,8 +778,8 @@ void free_gamedata(void)
free(forbidden_ids); free(forbidden_ids);
forbidden_ids = NULL; forbidden_ids = NULL;
free_donations();
free_factions(); free_factions();
free_donations();
free_units(); free_units();
free_regions(); free_regions();
free_borders(); free_borders();

View file

@ -738,7 +738,6 @@ void remove_empty_factions(void)
faction *f = *fp; faction *f = *fp;
if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_NOIDLEOUT)) { if (!(f->_alive && f->units!=NULL) && !fval(f, FFL_NOIDLEOUT)) {
log_debug("dead: %s", factionname(f));
destroyfaction(fp); destroyfaction(fp);
} }
else { else {
@ -876,6 +875,27 @@ int writepasswd(void)
return 1; return 1;
} }
void log_dead_factions(void)
{
if (dead_factions) {
const char *logname = config_get("game.deadlog");
if (logname) {
FILE *F;
char path[PATH_MAX];
join_path(basepath(), logname, path, sizeof(path));
F = fopen(path, "at");
if (F) {
faction *f;
for (f = dead_factions; f; f = f->next) {
fprintf(F, "%d\t%d\t%d\t%s\t%s\t%s\n", turn, f->lastorders, f->age, itoa36(f->no), f->email, f->name);
}
fclose(F);
}
}
}
}
void free_factions(void) { void free_factions(void) {
#ifdef DMAXHASH #ifdef DMAXHASH
int i; int i;

View file

@ -133,6 +133,7 @@ extern "C" {
void renumber_faction(faction * f, int no); void renumber_faction(faction * f, int no);
void free_factions(void); void free_factions(void);
void log_dead_factions(void);
void remove_empty_factions(void); void remove_empty_factions(void);
void update_interval(struct faction *f, struct region *r); void update_interval(struct faction *f, struct region *r);

View file

@ -16,11 +16,14 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#include <kernel/config.h> #endif
#include "pool.h" #include "pool.h"
#include "ally.h" #include "ally.h"
#include "config.h"
#include "faction.h" #include "faction.h"
#include "item.h" #include "item.h"
#include "order.h" #include "order.h"
@ -168,7 +171,8 @@ int count)
use = have; use = have;
else if (rtype->itype && mode & (GET_SLACK | GET_RESERVE)) { else if (rtype->itype && mode & (GET_SLACK | GET_RESERVE)) {
int reserve = get_reservation(u, rtype->itype); int reserve = get_reservation(u, rtype->itype);
int slack = MAX(0, have - reserve); int slack = have - reserve;
if (slack < 0) slack = 0;
if (mode & GET_RESERVE) if (mode & GET_RESERVE)
use = have - slack; use = have - slack;
else if (mode & GET_SLACK) else if (mode & GET_SLACK)
@ -206,18 +210,20 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count)
} }
if ((mode & GET_SLACK) && (mode & GET_RESERVE)) { if ((mode & GET_SLACK) && (mode & GET_RESERVE)) {
n = MIN(use, have); n = (use < have) ? use : have;
} }
else if (rtype->itype) { else if (rtype->itype) {
int reserve = get_reservation(u, rtype->itype); int reserve = get_reservation(u, rtype->itype);
int slack = MAX(0, have - reserve); int slack = have - reserve;
if (slack < 0) slack = 0;
if (mode & GET_RESERVE) { if (mode & GET_RESERVE) {
n = have - slack; n = have - slack;
n = MIN(use, n); if (n > use) n = use;
change_reservation(u, rtype->itype, -n); change_reservation(u, rtype->itype, -n);
} }
else if (mode & GET_SLACK) { else if (mode & GET_SLACK) {
n = MIN(use, slack); n = slack;
if (n > use) n = use;
} }
} }
if (n > 0) { if (n > 0) {

View file

@ -135,6 +135,7 @@ spell * create_spell(const char * name)
} }
static const char *sp_aliases[][2] = { static const char *sp_aliases[][2] = {
{ "create_potion_p14", "create_potion_healing" },
{ "gwyrrdfamiliar", "summon_familiar" }, { "gwyrrdfamiliar", "summon_familiar" },
{ "illaunfamiliar", "summon_familiar" }, { "illaunfamiliar", "summon_familiar" },
{ "draigfamiliar", "summon_familiar" }, { "draigfamiliar", "summon_familiar" },
@ -150,16 +151,20 @@ static const char *sp_alias(const char *zname)
if (strcmp(sp_aliases[i][0], zname) == 0) if (strcmp(sp_aliases[i][0], zname) == 0)
return sp_aliases[i][1]; return sp_aliases[i][1];
} }
return zname; return NULL;
} }
spell *find_spell(const char *name) spell *find_spell(const char *name)
{ {
const char * match; const char * match;
spell * sp = 0; spell * sp = 0;
match = cb_find_str(&cb_spells, name);
if (!match) {
const char * alias = sp_alias(name); const char * alias = sp_alias(name);
if (alias) {
match = cb_find_str(&cb_spells, alias); match = cb_find_str(&cb_spells, alias);
}
}
if (match) { if (match) {
cb_get_kv(match, &sp, sizeof(sp)); cb_get_kv(match, &sp, sizeof(sp));
} }

View file

@ -82,6 +82,7 @@ static void load_inifile(void)
static const char * valid_keys[] = { static const char * valid_keys[] = {
"game.id", "game.id",
"game.deadlog",
"game.name", "game.name",
"game.start", "game.start",
"game.locale", "game.locale",

View file

@ -17,7 +17,9 @@
* permission from the authors. * permission from the authors.
*/ */
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#endif
#include "monsters.h" #include "monsters.h"
@ -132,7 +134,10 @@ static void reduce_weight(unit * u)
if (itype->weight >= 10 && itype->rtype->wtype == 0 if (itype->weight >= 10 && itype->rtype->wtype == 0
&& itype->rtype->atype == 0) { && itype->rtype->atype == 0) {
if (itype->capacity < itype->weight) { if (itype->capacity < itype->weight) {
int reduce = MIN(itm->number, -((capacity - weight) / itype->weight)); int reduce = (weight - capacity) / itype->weight;
if (reduce > itm->number) {
reduce = itm->number;
}
give_peasants(u, itm->type, reduce); give_peasants(u, itm->type, reduce);
weight -= reduce * itype->weight; weight -= reduce * itype->weight;
} }
@ -147,7 +152,10 @@ static void reduce_weight(unit * u)
const item_type *itype = itm->type; const item_type *itype = itm->type;
weight += itm->number * itype->weight; weight += itm->number * itype->weight;
if (itype->capacity < itype->weight) { if (itype->capacity < itype->weight) {
int reduce = MIN(itm->number, -((capacity - weight) / itype->weight)); int reduce = (weight - capacity) / itype->weight;
if (reduce > itm->number) {
reduce = itm->number;
}
give_peasants(u, itm->type, reduce); give_peasants(u, itm->type, reduce);
weight -= reduce * itype->weight; weight -= reduce * itype->weight;
} }
@ -1027,10 +1035,12 @@ static void eaten_by_monster(unit * u)
n = (int)(n * multi); n = (int)(n * multi);
if (n > 0) { if (n > 0) {
n = lovar(n); n = lovar(n);
n = MIN(rpeasants(u->region), n);
if (n > 0) { if (n > 0) {
int p = rpeasants(u->region);
if (p < n) n = p;
deathcounts(u->region, n); deathcounts(u->region, n);
rsetpeasants(u->region, rpeasants(u->region) - n); rsetpeasants(u->region, rpeasants(u->region) - n);
ADDMSG(&u->region->msgs, msg_message("eatpeasants", "unit amount", u, n)); ADDMSG(&u->region->msgs, msg_message("eatpeasants", "unit amount", u, n));
@ -1048,8 +1058,9 @@ static void absorbed_by_monster(unit * u)
if (n > 0) { if (n > 0) {
n = lovar(n); n = lovar(n);
n = MIN(rpeasants(u->region), n);
if (n > 0) { if (n > 0) {
int p = rpeasants(u->region);
if (p < n) n = p;
rsetpeasants(u->region, rpeasants(u->region) - n); rsetpeasants(u->region, rpeasants(u->region) - n);
scale_number(u, u->number + n); scale_number(u, u->number + n);
ADDMSG(&u->region->msgs, msg_message("absorbpeasants", ADDMSG(&u->region->msgs, msg_message("absorbpeasants",
@ -1063,7 +1074,10 @@ static int scareaway(region * r, int anzahl)
int n, p, diff = 0, emigrants[MAXDIRECTIONS]; int n, p, diff = 0, emigrants[MAXDIRECTIONS];
direction_t d; direction_t d;
anzahl = MIN(MAX(1, anzahl), rpeasants(r)); p = rpeasants(r);
if (anzahl < 1) anzahl = 1;
if (anzahl > p) anzahl = p;
assert(p >= 0 && anzahl >= 0);
/* Wandern am Ende der Woche (normal) oder wegen Monster. Die /* Wandern am Ende der Woche (normal) oder wegen Monster. Die
* Wanderung wird erst am Ende von demographics () ausgefuehrt. * Wanderung wird erst am Ende von demographics () ausgefuehrt.
@ -1073,9 +1087,7 @@ static int scareaway(region * r, int anzahl)
for (d = 0; d != MAXDIRECTIONS; d++) for (d = 0; d != MAXDIRECTIONS; d++)
emigrants[d] = 0; emigrants[d] = 0;
p = rpeasants(r); for (n = anzahl; n; n--) {
assert(p >= 0 && anzahl >= 0);
for (n = MIN(p, anzahl); n; n--) {
direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS); direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS);
region *rc = rconnect(r, dir); region *rc = rconnect(r, dir);
@ -1104,8 +1116,9 @@ static void scared_by_monster(unit * u)
} }
if (n > 0) { if (n > 0) {
n = lovar(n); n = lovar(n);
n = MIN(rpeasants(u->region), n);
if (n > 0) { if (n > 0) {
int p = rpeasants(u->region);
if (p < n) n = p;
n = scareaway(u->region, n); n = scareaway(u->region, n);
if (n > 0) { if (n > 0) {
ADDMSG(&u->region->msgs, msg_message("fleescared", ADDMSG(&u->region->msgs, msg_message("fleescared",

View file

@ -16,49 +16,52 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#include <kernel/config.h> #endif
#include "randenc.h" #include "randenc.h"
#include "volcano.h" #include "chaos.h"
#include "economy.h" #include "economy.h"
#include "monsters.h" #include "monsters.h"
#include "move.h" #include "move.h"
#include "chaos.h"
#include "study.h" #include "study.h"
#include "volcano.h"
#include <spells/unitcurse.h> #include "spells/unitcurse.h"
#include <spells/regioncurse.h> #include "spells/regioncurse.h"
/* attributes includes */ /* attributes includes */
#include <attributes/racename.h> #include "attributes/racename.h"
#include <attributes/reduceproduction.h> #include "attributes/reduceproduction.h"
/* kernel includes */ /* kernel includes */
#include <kernel/building.h> #include "kernel/building.h"
#include <kernel/curse.h> #include "kernel/config.h"
#include <kernel/equipment.h> #include "kernel/curse.h"
#include <kernel/faction.h> #include "kernel/equipment.h"
#include <kernel/item.h> #include "kernel/faction.h"
#include <kernel/messages.h> #include "kernel/item.h"
#include <kernel/order.h> #include "kernel/messages.h"
#include <kernel/plane.h> #include "kernel/order.h"
#include <kernel/pool.h> #include "kernel/plane.h"
#include <kernel/race.h> #include "kernel/pool.h"
#include <kernel/region.h> #include "kernel/race.h"
#include <kernel/ship.h> #include "kernel/region.h"
#include <kernel/terrain.h> #include "kernel/ship.h"
#include <kernel/terrainid.h> #include "kernel/terrain.h"
#include <kernel/unit.h> #include "kernel/terrainid.h"
#include "kernel/unit.h"
/* util includes */ /* util includes */
#include <util/attrib.h> #include "util/attrib.h"
#include <util/language.h> #include "util/language.h"
#include <util/lists.h> #include "util/lists.h"
#include <util/log.h> #include "util/log.h"
#include <util/rand.h> #include "util/rand.h"
#include <util/message.h> #include "util/message.h"
#include <util/rng.h> #include "util/rng.h"
/* libc includes */ /* libc includes */
#include <string.h> #include <string.h>
@ -785,9 +788,8 @@ static void rotting_herbs(void)
int n = itm->number; int n = itm->number;
double k = n * rot_chance / 100.0; double k = n * rot_chance / 100.0;
if (fval(itm->type, ITF_HERB)) { if (fval(itm->type, ITF_HERB)) {
double nv = normalvariate(k, k / 4); int delta = (int)normalvariate(k, k / 4);
int inv = (int)nv; if (n < delta) delta = n;
int delta = MIN(n, inv);
if (!i_change(itmp, itm->type, -delta)) { if (!i_change(itmp, itm->type, -delta)) {
continue; continue;
} }
@ -823,7 +825,9 @@ void randomevents(void)
while (*blist) { while (*blist) {
building *b = *blist; building *b = *blist;
if (fval(b->type, BTF_DECAY) && !building_owner(b)) { if (fval(b->type, BTF_DECAY) && !building_owner(b)) {
b->size -= MAX(1, (b->size * 20) / 100); int delta = (b->size * 20) / 100;
if (delta < 1) delta = 1;
b->size -= delta;
if (b->size == 0) { if (b->size == 0) {
remove_building(blist, r->buildings); remove_building(blist, r->buildings);
} }

View file

@ -695,7 +695,7 @@ nr_unit(struct stream *out, const faction * f, const unit * u, int indent, seen_
return; return;
newline(out); newline(out);
dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); dh = bufunit(f, u, mode, buf, sizeof(buf));
if (u->faction == f) { if (u->faction == f) {
marker = '*'; marker = '*';

View file

@ -16,12 +16,12 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/ **/
#ifdef _MSC_VER
#include <platform.h> #include <platform.h>
#include <kernel/config.h> #endif
#include "reports.h" #include "reports.h"
#include "battle.h" #include "battle.h"
#include "kernel/calendar.h"
#include "guard.h" #include "guard.h"
#include "laws.h" #include "laws.h"
#include "spells.h" #include "spells.h"
@ -30,48 +30,50 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "donations.h" #include "donations.h"
/* attributes includes */ /* attributes includes */
#include <attributes/attributes.h> #include "attributes/attributes.h"
#include <attributes/follow.h> #include "attributes/follow.h"
#include <attributes/otherfaction.h> #include "attributes/otherfaction.h"
#include <attributes/racename.h> #include "attributes/racename.h"
#include <attributes/stealth.h> #include "attributes/stealth.h"
#include <spells/unitcurse.h> #include "spells/unitcurse.h"
/* kernel includes */ /* kernel includes */
#include <kernel/ally.h> #include "kernel/config.h"
#include <kernel/alliance.h> #include "kernel/calendar.h"
#include <kernel/connection.h> #include "kernel/ally.h"
#include <kernel/building.h> #include "kernel/alliance.h"
#include <kernel/curse.h> #include "kernel/connection.h"
#include <kernel/faction.h> #include "kernel/building.h"
#include <kernel/group.h> #include "kernel/curse.h"
#include <kernel/item.h> #include "kernel/faction.h"
#include <kernel/messages.h> #include "kernel/group.h"
#include <kernel/order.h> #include "kernel/item.h"
#include <kernel/plane.h> #include "kernel/messages.h"
#include <kernel/race.h> #include "kernel/order.h"
#include <kernel/region.h> #include "kernel/plane.h"
#include <kernel/resources.h> #include "kernel/race.h"
#include <kernel/ship.h> #include "kernel/region.h"
#include <kernel/spell.h> #include "kernel/resources.h"
#include <kernel/spellbook.h> #include "kernel/ship.h"
#include <kernel/terrain.h> #include "kernel/spell.h"
#include <kernel/unit.h> #include "kernel/spellbook.h"
#include "kernel/terrain.h"
#include "kernel/unit.h"
/* util includes */ /* util includes */
#include <util/attrib.h> #include "util/attrib.h"
#include <util/base36.h> #include "util/base36.h"
#include <util/bsdstring.h> #include "util/bsdstring.h"
#include <util/functions.h> #include "util/functions.h"
#include <util/goodies.h> #include "util/goodies.h"
#include <util/language.h> #include "util/language.h"
#include <util/lists.h> #include "util/lists.h"
#include <util/log.h> #include "util/log.h"
#include <util/macros.h> #include "util/macros.h"
#include <util/path.h> #include "util/path.h"
#include <util/strings.h> #include "util/strings.h"
#include <util/translation.h> #include "util/translation.h"
#include <stream.h> #include <stream.h>
#include <selist.h> #include <selist.h>
@ -610,8 +612,72 @@ report_resources(const region * r, resource_report * result, int size,
return n; return n;
} }
static size_t spskill(char *buffer, size_t size, const struct locale * lang,
const struct unit * u, struct skill * sv, int *dh)
{
char *bufp = buffer;
int effsk;
if (!u->number)
return 0;
if (sv->level <= 0) {
if (sv->old <= 0 || (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) == 0) {
return 0;
}
}
bufp = STRLCPY(bufp, ", ", size);
if (!*dh) {
bufp = STRLCPY(bufp, LOC(lang, "nr_skills"), size);
bufp = STRLCPY(bufp, ": ", size);
*dh = 1;
}
bufp = STRLCPY(bufp, skillname(sv->id, lang), size);
bufp = STRLCPY(bufp, " ", size);
if (sv->id == SK_MAGIC) {
sc_mage *mage = get_mage(u);
if (mage && mage->magietyp != M_GRAY) {
bufp = STRLCPY(bufp, LOC(lang, mkname("school",
magic_school[mage->magietyp])), size);
bufp = STRLCPY(bufp, " ", size);
}
}
if (sv->id == SK_STEALTH && fval(u, UFL_STEALTH)) {
int i = u_geteffstealth(u);
if (i >= 0) {
if (wrptr(&bufp, &size, snprintf(bufp, size, "%d/", i)) != 0)
WARN_STATIC_BUFFER();
}
}
effsk = eff_skill(u, sv, 0);
if (wrptr(&bufp, &size, snprintf(bufp, size, "%d", effsk)) != 0)
WARN_STATIC_BUFFER();
if (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) {
int oldeff = 0;
int diff;
if (sv->old > 0) {
oldeff = sv->old + get_modifier(u, sv->id, sv->old, u->region, false);
if (oldeff < 0) oldeff = 0;
}
diff = effsk - oldeff;
if (diff != 0) {
if (wrptr(&bufp, &size, snprintf(bufp, size, " (%s%d)", (diff > 0) ? "+" : "", diff)) != 0)
WARN_STATIC_BUFFER();
}
}
return bufp - buffer;
}
int int
bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode, char *buf, bufunit(const faction * f, const unit * u, seen_mode mode, char *buf,
size_t size) size_t size)
{ {
int i, dh; int i, dh;
@ -750,7 +816,7 @@ bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode,
if (u->faction == f) { if (u->faction == f) {
skill *sv; skill *sv;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
size_t bytes = spskill(bufp, size, lang, u, sv, &dh, 1); size_t bytes = spskill(bufp, size, lang, u, sv, &dh);
assert(bytes <= INT_MAX); assert(bytes <= INT_MAX);
if (wrptr(&bufp, &size, (int)bytes) != 0) if (wrptr(&bufp, &size, (int)bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
@ -918,71 +984,6 @@ bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode,
return dh; return dh;
} }
size_t
spskill(char *buffer, size_t size, const struct locale * lang,
const struct unit * u, struct skill * sv, int *dh, int days)
{
char *bufp = buffer;
int effsk;
if (!u->number)
return 0;
if (sv->level <= 0) {
if (sv->old <= 0 || (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) == 0) {
return 0;
}
}
bufp = STRLCPY(bufp, ", ", size);
if (!*dh) {
bufp = STRLCPY(bufp, LOC(lang, "nr_skills"), size);
bufp = STRLCPY(bufp, ": ", size);
*dh = 1;
}
bufp = STRLCPY(bufp, skillname(sv->id, lang), size);
bufp = STRLCPY(bufp, " ", size);
if (sv->id == SK_MAGIC) {
sc_mage *mage = get_mage(u);
if (mage && mage->magietyp != M_GRAY) {
bufp = STRLCPY(bufp, LOC(lang, mkname("school",
magic_school[mage->magietyp])), size);
bufp = STRLCPY(bufp, " ", size);
}
}
if (sv->id == SK_STEALTH && fval(u, UFL_STEALTH)) {
int i = u_geteffstealth(u);
if (i >= 0) {
if (wrptr(&bufp, &size, snprintf(bufp, size, "%d/", i)) != 0)
WARN_STATIC_BUFFER();
}
}
effsk = eff_skill(u, sv, 0);
if (wrptr(&bufp, &size, snprintf(bufp, size, "%d", effsk)) != 0)
WARN_STATIC_BUFFER();
if (u->faction->options & WANT_OPTION(O_SHOWSKCHANGE)) {
int oldeff = 0;
int diff;
if (sv->old > 0) {
oldeff = sv->old + get_modifier(u, sv->id, sv->old, u->region, false);
}
oldeff = MAX(0, oldeff);
diff = effsk - oldeff;
if (diff != 0) {
if (wrptr(&bufp, &size, snprintf(bufp, size, " (%s%d)", (diff > 0) ? "+" : "", diff)) != 0)
WARN_STATIC_BUFFER();
}
}
return bufp - buffer;
}
void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark) void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark)
{ {
bool firstline; bool firstline;
@ -1013,7 +1014,7 @@ void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned
firstline = false; firstline = false;
} }
if (!cut) { if (!cut) {
cut = s + MIN(len, REPORTWIDTH); cut = s + ((len < REPORTWIDTH) ? len : REPORTWIDTH);
} }
memcpy(buf + indent, s, cut - s); memcpy(buf + indent, s, cut - s);
buf[indent + (cut - s)] = 0; buf[indent + (cut - s)] = 0;
@ -1054,7 +1055,7 @@ spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned in
seen_mode mode) seen_mode mode)
{ {
char buf[DISPLAYSIZE]; char buf[DISPLAYSIZE];
int dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); int dh = bufunit(f, u, mode, buf, sizeof(buf));
lparagraph(SP, buf, indent, lparagraph(SP, buf, indent,
(char)((u->faction == f) ? '*' : (dh ? '+' : '-'))); (char)((u->faction == f) ? '*' : (dh ? '+' : '-')));
} }
@ -1669,7 +1670,7 @@ void finish_reports(report_context *ctx) {
} }
} }
int write_reports(faction * f, time_t ltime) int write_reports(faction * f)
{ {
bool gotit = false; bool gotit = false;
struct report_context ctx; struct report_context ctx;
@ -1758,7 +1759,6 @@ int reports(void)
{ {
faction *f; faction *f;
FILE *mailit; FILE *mailit;
time_t ltime = time(NULL);
int retval = 0; int retval = 0;
char path[4096]; char path[4096];
const char * rpath = reportpath(); const char * rpath = reportpath();
@ -1775,7 +1775,7 @@ int reports(void)
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (f->email && !fval(f, FFL_NPC)) { if (f->email && !fval(f, FFL_NPC)) {
int error = write_reports(f, ltime); int error = write_reports(f);
if (error) if (error)
retval = error; retval = error;
if (mailit) if (mailit)
@ -1998,6 +1998,7 @@ static void eval_unitsize(struct opstack **stack, const void *userdata)
const struct unit *u = (const struct unit *)opop(stack).v; const struct unit *u = (const struct unit *)opop(stack).v;
variant var; variant var;
UNUSED_ARG(userdata);
var.i = u->number; var.i = u->number;
opush(stack, var); opush(stack, var);
} }
@ -2009,6 +2010,7 @@ static void eval_faction(struct opstack **stack, const void *userdata)
size_t len = strlen(c); size_t len = strlen(c);
variant var; variant var;
UNUSED_ARG(userdata);
var.v = strcpy(balloc(len + 1), c); var.v = strcpy(balloc(len + 1), c);
opush(stack, var); opush(stack, var);
} }
@ -2018,6 +2020,8 @@ static void eval_alliance(struct opstack **stack, const void *userdata)
const struct alliance *al = (const struct alliance *)opop(stack).v; const struct alliance *al = (const struct alliance *)opop(stack).v;
const char *c = alliancename(al); const char *c = alliancename(al);
variant var; variant var;
UNUSED_ARG(userdata);
if (c != NULL) { if (c != NULL) {
size_t len = strlen(c); size_t len = strlen(c);
var.v = strcpy(balloc(len + 1), c); var.v = strcpy(balloc(len + 1), c);

View file

@ -60,12 +60,11 @@ extern "C" {
void sparagraph(struct strlist **SP, const char *s, unsigned int indent, char mark); void sparagraph(struct strlist **SP, const char *s, unsigned int indent, char mark);
void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark); void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark);
const char *hp_status(const struct unit *u); const char *hp_status(const struct unit *u);
size_t spskill(char *pbuf, size_t siz, const struct locale *lang, const struct unit *u, struct skill *sv, int *dh, int days); /* mapper */
void spunit(struct strlist **SP, const struct faction *f, void spunit(struct strlist **SP, const struct faction *f,
const struct unit *u, unsigned int indent, seen_mode mode); const struct unit *u, unsigned int indent, seen_mode mode);
int reports(void); int reports(void);
int write_reports(struct faction *f, time_t ltime); int write_reports(struct faction *f);
int init_reports(void); int init_reports(void);
void reorder_units(struct region * r); void reorder_units(struct region * r);
@ -91,8 +90,8 @@ extern "C" {
void register_reporttype(const char *extension, report_fun write, void register_reporttype(const char *extension, report_fun write,
int flag); int flag);
int bufunit(const struct faction *f, const struct unit *u, unsigned int indent, int bufunit(const struct faction *f, const struct unit *u, seen_mode mode,
seen_mode mode, char *buf, size_t size); char *buf, size_t size);
const char *trailinto(const struct region *r, const char *trailinto(const struct region *r,
const struct locale *lang); const struct locale *lang);

View file

@ -199,56 +199,56 @@ static void test_bufunit_fstealth(CuTest *tc) {
key_set(&u->attribs, 42, 42); key_set(&u->attribs, 42, 42);
/* report to ourselves */ /* report to ourselves */
bufunit(f1, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f1, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressive.", buf); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressive.", buf);
/* ... also when we are anonymous */ /* ... also when we are anonymous */
u->flags |= UFL_ANON_FACTION; u->flags |= UFL_ANON_FACTION;
bufunit(f1, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f1, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf); CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf);
u->flags &= ~UFL_ANON_FACTION; u->flags &= ~UFL_ANON_FACTION;
/* we see that our unit is cloaked */ /* we see that our unit is cloaked */
set_factionstealth(u, f2); set_factionstealth(u, f2);
CuAssertPtrNotNull(tc, u->attribs); CuAssertPtrNotNull(tc, u->attribs);
bufunit(f1, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f1, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human, aggressive.", buf); CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human, aggressive.", buf);
/* ... also when we are anonymous */ /* ... also when we are anonymous */
u->flags |= UFL_ANON_FACTION; u->flags |= UFL_ANON_FACTION;
bufunit(f1, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f1, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf); CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human, aggressive.", buf);
u->flags &= ~UFL_ANON_FACTION; u->flags &= ~UFL_ANON_FACTION;
/* we can see that someone is presenting as us */ /* we can see that someone is presenting as us */
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), TWW (2), 1 human.", buf);
/* ... but not if they are anonymous */ /* ... but not if they are anonymous */
u->flags |= UFL_ANON_FACTION; u->flags |= UFL_ANON_FACTION;
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
u->flags &= ~UFL_ANON_FACTION; u->flags &= ~UFL_ANON_FACTION;
/* we see the same thing as them when we are an ally */ /* we see the same thing as them when we are an ally */
al = ally_add(&f1->allies, f2); al = ally_add(&f1->allies, f2);
al->status = HELP_FSTEALTH; al->status = HELP_FSTEALTH;
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), TWW (2) (UFO (1)), 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), TWW (2) (UFO (1)), 1 human.", buf);
/* ... also when they are anonymous */ /* ... also when they are anonymous */
u->flags |= UFL_ANON_FACTION; u->flags |= UFL_ANON_FACTION;
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
u->flags &= ~UFL_ANON_FACTION; u->flags &= ~UFL_ANON_FACTION;
/* fstealth has no influence when we are allies, same results again */ /* fstealth has no influence when we are allies, same results again */
set_factionstealth(u, NULL); set_factionstealth(u, NULL);
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buf);
u->flags |= UFL_ANON_FACTION; u->flags |= UFL_ANON_FACTION;
bufunit(f2, u, 0, seen_unit, buf, sizeof(buf)); bufunit(f2, u, seen_unit, buf, sizeof(buf));
CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf); CuAssertStrEquals(tc, "Hodor (1), anonymous, 1 human.", buf);
u->flags &= ~UFL_ANON_FACTION; u->flags &= ~UFL_ANON_FACTION;
@ -278,20 +278,20 @@ static void test_bufunit(CuTest *tc) {
unit_setname(u, "Hodor"); unit_setname(u, "Hodor");
unit_setid(u, 1); unit_setid(u, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer)); bufunit(u->faction, u, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv.", buffer); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv.", buffer);
set_level(u, SK_ALCHEMY, 1); set_level(u, SK_ALCHEMY, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer)); bufunit(u->faction, u, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2.", buffer); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2.", buffer);
set_level(u, SK_SAILING, 1); set_level(u, SK_SAILING, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer)); bufunit(u->faction, u, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2, Segeln 1.", buffer); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2, Segeln 1.", buffer);
f = test_create_faction(NULL); f = test_create_faction(NULL);
f->locale = get_or_create_locale("de"); f->locale = get_or_create_locale("de");
bufunit(f, u, 0, 0, buffer, sizeof(buffer)); bufunit(f, u, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buffer); CuAssertStrEquals(tc, "Hodor (1), UFO (1), 1 human.", buffer);
test_teardown(); test_teardown();