merge branch 'develop' of github.com:ennorehling/eressea into develop

This commit is contained in:
Enno Rehling 2018-11-29 16:22:05 +01:00
commit ed1cd367b1
6 changed files with 319 additions and 371 deletions

View file

@ -7,7 +7,7 @@
#ifndef ERESSEA_VERSION #ifndef ERESSEA_VERSION
/* the version number, if it was not passed to make with -D */ /* the version number, if it was not passed to make with -D */
#define ERESSEA_VERSION "3.18.0" #define ERESSEA_VERSION "3.19.0"
#endif #endif
const char *eressea_version(void) { const char *eressea_version(void) {

View file

@ -234,19 +234,18 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
} while (*begin); } while (*begin);
} }
static size_t write_spell_modifier(const spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) { static bool write_spell_modifier(const spell * sp, int flag, const char * str, bool cont, sbstring *sbp) {
if (sp->sptyp & flag) { if (sp->sptyp & flag) {
size_t bytes = 0;
if (cont) { if (cont) {
bytes = str_strlcpy(bufp, ", ", size); sbs_strcat(sbp, ", ");
} }
else { else {
bytes = str_strlcpy(bufp, " ", size); sbs_strcat(sbp, " ");
} }
bytes += str_strlcpy(bufp + bytes, str, size - bytes); sbs_strcat(sbp, str);
return bytes; return true;
} }
return 0; return cont;
} }
void nr_spell_syntax(char *buf, size_t size, spellbook_entry * sbe, const struct locale *lang) void nr_spell_syntax(char *buf, size_t size, spellbook_entry * sbe, const struct locale *lang)
@ -435,11 +434,11 @@ void nr_spell_syntax(char *buf, size_t size, spellbook_entry * sbe, const struct
void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *lang) void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *lang)
{ {
int bytes, k, itemanz, costtyp; int k, itemanz, costtyp;
bool cont;
char buf[4096]; char buf[4096];
char *startp, *bufp = buf;
size_t size = sizeof(buf) - 1;
const spell *sp = spellref_get(&sbe->spref); const spell *sp = spellref_get(&sbe->spref);
sbstring sbs;
newline(out); newline(out);
centre(out, spell_name(sp, lang), true); centre(out, spell_name(sp, lang), true);
@ -447,29 +446,22 @@ void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *la
paragraph(out, LOC(lang, "nr_spell_description"), 0, 0, 0); paragraph(out, LOC(lang, "nr_spell_description"), 0, 0, 0);
paragraph(out, spell_info(sp, lang), 2, 0, 0); paragraph(out, spell_info(sp, lang), 2, 0, 0);
bytes = (int)str_strlcpy(bufp, LOC(lang, "nr_spell_type"), size); sbs_init(&sbs, buf, sizeof(buf));
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(lang, "nr_spell_type"));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " ");
if (size) {
*bufp++ = ' ';
--size;
}
if (sp->sptyp & PRECOMBATSPELL) { if (sp->sptyp & PRECOMBATSPELL) {
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_precombat"), size); sbs_strcat(&sbs, LOC(lang, "sptype_precombat"));
} }
else if (sp->sptyp & COMBATSPELL) { else if (sp->sptyp & COMBATSPELL) {
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_combat"), size); sbs_strcat(&sbs, LOC(lang, "sptype_combat"));
} }
else if (sp->sptyp & POSTCOMBATSPELL) { else if (sp->sptyp & POSTCOMBATSPELL) {
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_postcombat"), size); sbs_strcat(&sbs, LOC(lang, "sptype_postcombat"));
} }
else { else {
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_normal"), size); sbs_strcat(&sbs, LOC(lang, "sptype_normal"));
} }
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
*bufp = 0;
paragraph(out, buf, 0, 0, 0); paragraph(out, buf, 0, 0, 0);
sprintf(buf, "%s %d", LOC(lang, "nr_spell_level"), sbe->level); sprintf(buf, "%s %d", LOC(lang, "nr_spell_level"), sbe->level);
@ -484,61 +476,38 @@ void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *la
itemanz = sp->components[k].amount; itemanz = sp->components[k].amount;
costtyp = sp->components[k].cost; costtyp = sp->components[k].cost;
if (itemanz > 0) { if (itemanz > 0) {
size = sizeof(buf) - 1; sbs_init(&sbs, buf, sizeof(buf));
bufp = buf;
if (sp->sptyp & SPELLLEVEL) { if (sp->sptyp & SPELLLEVEL) {
bytes = sbs_strcat(&sbs, " ");
snprintf(bufp, size, " %d %s", itemanz, LOC(lang, resourcename(rtype, sbs_strcat(&sbs, str_itoa(itemanz));
itemanz != 1))); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(lang, resourcename(rtype, itemanz != 1)));
WARN_STATIC_BUFFER();
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR) { if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR) {
bytes = snprintf(bufp, size, " * %s", LOC(lang, "nr_level")); sbs_strcat(&sbs, " * ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(lang, "nr_level"));
WARN_STATIC_BUFFER();
} }
} }
else { else {
bytes = snprintf(bufp, size, "%d %s", itemanz, LOC(lang, resourcename(rtype, itemanz != 1))); sbs_strcat(&sbs, str_itoa(itemanz));
if (wrptr(&bufp, &size, bytes) != 0) { sbs_strcat(&sbs, " ");
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, LOC(lang, resourcename(rtype, itemanz != 1)));
}
} }
*bufp = 0;
paragraph(out, buf, 2, 2, '-'); paragraph(out, buf, 2, 2, '-');
} }
} }
size = sizeof(buf) - 1; sbs_substr(&sbs, 0, 0);
bufp = buf; sbs_strcat(&sbs, LOC(lang, "nr_spell_modifiers"));
bytes = (int)str_strlcpy(buf, LOC(lang, "nr_spell_modifiers"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
startp = bufp; cont = false;
bytes = (int)write_spell_modifier(sp, FARCASTING, LOC(lang, "smod_far"), startp != bufp, bufp, size); cont = write_spell_modifier(sp, FARCASTING, LOC(lang, "smod_far"), cont, &sbs);
if (bytes && wrptr(&bufp, &size, bytes) != 0) { cont = write_spell_modifier(sp, OCEANCASTABLE, LOC(lang, "smod_sea"), cont, &sbs);
WARN_STATIC_BUFFER(); cont = write_spell_modifier(sp, ONSHIPCAST, LOC(lang, "smod_ship"), cont, &sbs);
cont = write_spell_modifier(sp, NOTFAMILIARCAST, LOC(lang, "smod_nofamiliar"), cont, &sbs);
if (!cont) {
write_spell_modifier(sp, NOTFAMILIARCAST, LOC(lang, "smod_none"), cont, &sbs);
} }
bytes = (int)write_spell_modifier(sp, OCEANCASTABLE, LOC(lang, "smod_sea"), startp != bufp, bufp, size);
if (bytes && wrptr(&bufp, &size, bytes) != 0) {
WARN_STATIC_BUFFER();
}
bytes = (int)write_spell_modifier(sp, ONSHIPCAST, LOC(lang, "smod_ship"), startp != bufp, bufp, size);
if (bytes && wrptr(&bufp, &size, bytes) != 0) {
WARN_STATIC_BUFFER();
}
bytes = (int)write_spell_modifier(sp, NOTFAMILIARCAST, LOC(lang, "smod_nofamiliar"), startp != bufp, bufp, size);
if (bytes && wrptr(&bufp, &size, bytes) != 0) {
WARN_STATIC_BUFFER();
}
if (startp == bufp) {
bytes = (int)write_spell_modifier(sp, NOTFAMILIARCAST, LOC(lang, "smod_none"), startp != bufp, bufp, size);
if (bytes && wrptr(&bufp, &size, bytes) != 0) {
WARN_STATIC_BUFFER();
}
}
*bufp = 0;
paragraph(out, buf, 0, 0, 0); paragraph(out, buf, 0, 0, 0);
paragraph(out, LOC(lang, "nr_spell_syntax"), 0, 0, 0); paragraph(out, LOC(lang, "nr_spell_syntax"), 0, 0, 0);
@ -776,14 +745,21 @@ static void rp_battles(struct stream *out, faction * f)
} }
} }
static void append_message(sbstring *sbp, message *m, const faction * f) {
/* FIXME: this is a bad hack, cause by how msg_message works. */
size_t size = sbp->size - sbs_length(sbp);
size = nr_render(m, f->locale, sbp->end, size, f);
sbp->end += size;
}
static void prices(struct stream *out, const region * r, const faction * f) static void prices(struct stream *out, const region * r, const faction * f)
{ {
const luxury_type *sale = NULL; const luxury_type *sale = NULL;
struct demand *dmd; struct demand *dmd;
message *m; message *m;
int bytes, n = 0; int n = 0;
char buf[4096], *bufp = buf; char buf[4096];
size_t size = sizeof(buf) - 1; sbstring sbs;
if (r->land == NULL || r->land->demands == NULL) if (r->land == NULL || r->land->demands == NULL)
return; return;
@ -797,64 +773,37 @@ static void prices(struct stream *out, const region * r, const faction * f)
m = msg_message("nr_market_sale", "product price", m = msg_message("nr_market_sale", "product price",
sale->itype->rtype, sale->price); sale->itype->rtype, sale->price);
nr_render(m, f->locale, buf, sizeof(buf), f);
bytes = (int)nr_render(m, f->locale, bufp, size, f);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
msg_release(m); msg_release(m);
sbs_adopt(&sbs, buf, sizeof(buf));
if (n > 0) { if (n > 0) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, "nr_trade_intro"));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " ");
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_intro"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
for (dmd = r->land->demands; dmd; dmd = dmd->next) { for (dmd = r->land->demands; dmd; dmd = dmd->next) {
if (dmd->value > 0) { if (dmd->value > 0) {
m = msg_message("nr_market_price", "product price", m = msg_message("nr_market_price", "product price",
dmd->type->itype->rtype, dmd->value * dmd->type->price); dmd->type->itype->rtype, dmd->value * dmd->type->price);
bytes = (int)nr_render(m, f->locale, bufp, size, f); append_message(&sbs, m, f);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
msg_release(m); msg_release(m);
n--; n--;
if (n == 0) { if (n == 0) {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_end"), sbs_strcat(&sbs, LOC(f->locale, "nr_trade_end"));
size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
else if (n == 1) { else if (n == 1) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, "nr_trade_final"));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " ");
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_final"),
size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
else { else {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_next"), sbs_strcat(&sbs, LOC(f->locale, "nr_trade_next"));
size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
} }
} }
} }
/* Schreibe Paragraphen */
*bufp = 0;
paragraph(out, buf, 0, 0, 0); paragraph(out, buf, 0, 0, 0);
} }
@ -880,130 +829,87 @@ bool see_border(const connection * b, const faction * f, const region * r)
#define MAX_EDGES 16 #define MAX_EDGES 16
void report_region(struct stream *out, const region * r, faction * f) struct edge {
char *name;
bool transparent;
bool block;
bool exist[MAXDIRECTIONS];
direction_t lastd;
};
static void report_region_resource(sbstring *sbp, const struct locale *lang, const struct resource_type *rtype, int n) {
if (n != 0) {
sbs_strcat(sbp, ", ");
sbs_strcat(sbp, str_itoa(n));
sbs_strcat(sbp, " ");
sbs_strcat(sbp, LOC(lang, resourcename(rtype, (n != 1) ? GR_PLURAL : 0)));
}
}
static void report_region_description(struct stream *out, const region * r, faction * f, const bool see[])
{ {
int n; int n;
bool dh; bool dh;
direction_t d;
int trees; int trees;
int saplings; int saplings;
attrib *a; attrib *a;
const char *tname; const char *tname;
struct edge { char buf[4096];
char *name; sbstring sbs;
bool transparent;
bool block;
bool exist[MAXDIRECTIONS];
direction_t lastd;
} edges[MAX_EDGES];
int ne = 0;
bool see[MAXDIRECTIONS];
char buf[8192];
char *bufp = buf;
size_t size = sizeof(buf);
int bytes;
assert(out); f_regionid(r, f, buf, sizeof(buf));
assert(f); sbs_adopt(&sbs, buf, sizeof(buf));
assert(r);
memset(edges, 0, sizeof(edges));
for (d = 0; d != MAXDIRECTIONS; d++) {
/* Nachbarregionen, die gesehen werden, ermitteln */
region *r2 = rconnect(r, d);
connection *b;
see[d] = true;
if (!r2)
continue;
for (b = get_borders(r, r2); b;) {
int e;
struct edge *match = NULL;
bool transparent = b->type->transparent(b, f);
const char *name = border_name(b, r, f, GF_DETAILED | GF_ARTICLE);
if (!transparent) {
see[d] = false;
}
if (!see_border(b, f, r)) {
b = b->next;
continue;
}
for (e = 0; e!=ne; ++e) {
struct edge *edg = edges + e;
if (edg->transparent == transparent && 0 == strcmp(name, edg->name)) {
match = edg;
break;
}
}
if (match == NULL) {
match = edges + ne;
match->name = str_strdup(name);
match->transparent = transparent;
++ne;
assert(ne < MAX_EDGES);
}
match->lastd = d;
match->exist[d] = true;
b = b->next;
}
}
bytes = (int)f_regionid(r, f, bufp, size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (r->seen.mode == seen_travel) { if (r->seen.mode == seen_travel) {
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_travel")); sbs_strcat(&sbs, " (");
sbs_strcat(&sbs, LOC(f->locale, "see_travel"));
sbs_strcat(&sbs, ")");
} }
else if (r->seen.mode == seen_neighbour) { else if (r->seen.mode == seen_neighbour) {
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_neighbour")); sbs_strcat(&sbs, " (");
sbs_strcat(&sbs, LOC(f->locale, "see_neighbour"));
sbs_strcat(&sbs, ")");
} }
else if (r->seen.mode == seen_lighthouse) { else if (r->seen.mode == seen_lighthouse) {
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_lighthouse")); sbs_strcat(&sbs, " (");
sbs_strcat(&sbs, LOC(f->locale, "see_lighthouse"));
sbs_strcat(&sbs, ")");
} }
else {
bytes = 0;
}
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
/* Terrain */ /* Terrain */
bytes = (int)str_strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
tname = terrain_name(r); tname = terrain_name(r);
bytes = (int)str_strlcpy(bufp, LOC(f->locale, tname), size); sbs_strcat(&sbs, ", ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, tname));
WARN_STATIC_BUFFER(); pump_paragraph(&sbs, out, REPORTWIDTH, false);
/* Trees */ /* Trees */
trees = rtrees(r, 2); trees = rtrees(r, 2);
saplings = rtrees(r, 1); saplings = rtrees(r, 1);
if (max_production(r)) { if (max_production(r)) {
if (trees > 0 || saplings > 0) { if (trees > 0 || saplings > 0) {
bytes = snprintf(bufp, size, ", %d/%d ", trees, saplings); sbs_strcat(&sbs, ", ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, str_itoa(trees));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, "/");
sbs_strcat(&sbs, str_itoa(saplings));
sbs_strcat(&sbs, " ");
if (fval(r, RF_MALLORN)) { if (fval(r, RF_MALLORN)) {
if (trees == 1) { if (trees == 1) {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mallorntree"), size); sbs_strcat(&sbs, LOC(f->locale, "nr_mallorntree"));
} }
else { else {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mallorntree_p"), size); sbs_strcat(&sbs, LOC(f->locale, "nr_mallorntree_p"));
} }
} }
else if (trees == 1) { else if (trees == 1) {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "tree"), size); sbs_strcat(&sbs, LOC(f->locale, "tree"));
} }
else { else {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "tree_p"), size); sbs_strcat(&sbs, LOC(f->locale, "tree_p"));
} }
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
} }
pump_paragraph(&sbs, out, REPORTWIDTH, false);
/* iron & stone */ /* iron & stone */
if (r->seen.mode >= seen_unit) { if (r->seen.mode >= seen_unit) {
@ -1012,123 +918,84 @@ void report_region(struct stream *out, const region * r, faction * f)
for (n = 0; n < numresults; ++n) { for (n = 0; n < numresults; ++n) {
if (result[n].number >= 0 && result[n].level >= 0) { if (result[n].number >= 0 && result[n].level >= 0) {
const char * name = resourcename(result[n].rtype, result[n].number!=1); const char * name = resourcename(result[n].rtype, result[n].number != 1);
bytes = snprintf(bufp, size, ", %d %s/%d", result[n].number, sbs_strcat(&sbs, ", ");
LOC(f->locale, name), result[n].level); sbs_strcat(&sbs, str_itoa(result[n].number));
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, " ");
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, LOC(f->locale, name));
sbs_strcat(&sbs, "/");
sbs_strcat(&sbs, str_itoa(result[n].level));
} }
} }
} }
/* peasants & silver */ /* peasants & silver */
if (rpeasants(r)) { n = rpeasants(r);
int p = rpeasants(r); if (n) {
bytes = snprintf(bufp, size, ", %d", p); sbs_strcat(&sbs, ", ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, str_itoa(n));
WARN_STATIC_BUFFER();
if (r->land->ownership) { if (r->land->ownership) {
const char *str = const char *str =
LOC(f->locale, mkname("morale", itoa10(region_get_morale(r)))); LOC(f->locale, mkname("morale", itoa10(region_get_morale(r))));
bytes = snprintf(bufp, size, " %s", str); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, str);
WARN_STATIC_BUFFER();
} }
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, n != 1 ? "peasant_p" : "peasant"));
WARN_STATIC_BUFFER();
bytes =
(int)str_strlcpy(bufp, LOC(f->locale, p == 1 ? "peasant" : "peasant_p"),
size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (is_mourning(r, turn + 1)) { if (is_mourning(r, turn + 1)) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, "nr_mourning"));
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mourning"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
} }
if (rmoney(r) && r->seen.mode >= seen_travel) { if (r->seen.mode >= seen_travel) {
bytes = snprintf(bufp, size, ", %d ", rmoney(r)); report_region_resource(&sbs, f->locale, get_resourcetype(R_SILVER), rmoney(r));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(get_resourcetype(R_SILVER),
rmoney(r) != 1)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
/* Pferde */ /* Pferde */
report_region_resource(&sbs, f->locale, get_resourcetype(R_HORSE), rhorses(r));
if (rhorses(r)) { sbs_strcat(&sbs, ".");
bytes = snprintf(bufp, size, ", %d ", rhorses(r));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(get_resourcetype(R_HORSE),
(rhorses(r) > 1) ? GR_PLURAL : 0)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
bytes = (int)str_strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (r->land && r->land->display && r->land->display[0]) { if (r->land && r->land->display && r->land->display[0]) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, r->land->display);
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, r->land->display, size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
n = r->land->display[strlen(r->land->display) - 1]; n = r->land->display[strlen(r->land->display) - 1];
if (n != '!' && n != '?' && n != '.') { if (n != '!' && n != '?' && n != '.') {
bytes = (int)str_strlcpy(bufp, ".", size); sbs_strcat(&sbs, ".");
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
} }
if (rule_region_owners()) { if (rule_region_owners()) {
const faction *owner = region_get_owner(r); const faction *owner = region_get_owner(r);
message *msg;
if (owner != NULL) { if (owner != NULL) {
bytes = (int)str_strlcpy(bufp, " ", size); message *msg;
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " ");
msg = msg_message("nr_region_owner", "faction", owner); msg = msg_message("nr_region_owner", "faction", owner);
bytes = (int)nr_render(msg, f->locale, bufp, size, f); append_message(&sbs, msg, f);
msg_release(msg); msg_release(msg);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
} }
a = a_find(r->attribs, &at_overrideroads);
pump_paragraph(&sbs, out, REPORTWIDTH, false);
a = a_find(r->attribs, &at_overrideroads);
if (a) { if (a) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, (const char *)a->data.v);
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, ".");
bytes = (int)str_strlcpy(bufp, (char *)a->data.v, size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
else { else {
int nrd = 0; int d, nrd = 0;
/* Nachbarregionen, die gesehen werden, ermitteln */ /* Nachbarregionen, die gesehen werden, ermitteln */
for (d = 0; d != MAXDIRECTIONS; d++) { for (d = 0; d != MAXDIRECTIONS; d++) {
if (see[d] && rconnect(r, d)) if (see[d] && rconnect(r, d))
nrd++; nrd++;
} }
/* list directions */
/* list directions */
dh = false; dh = false;
for (d = 0; d != MAXDIRECTIONS; d++) { for (d = 0; d != MAXDIRECTIONS; d++) {
if (see[d]) { if (see[d]) {
@ -1137,67 +1004,80 @@ void report_region(struct stream *out, const region * r, faction * f)
continue; continue;
nrd--; nrd--;
if (dh) { if (dh) {
char regname[4096]; char regname[128], trail[256];
if (nrd == 0) { if (nrd == 0) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, "nr_nb_final"));
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_nb_final"), size);
} }
else { else {
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_nb_next"), size); sbs_strcat(&sbs, LOC(f->locale, "nr_nb_next"));
} }
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, directions[d]));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " ");
bytes = (int)str_strlcpy(bufp, LOC(f->locale, directions[d]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
f_regionid(r2, f, regname, sizeof(regname)); f_regionid(r2, f, regname, sizeof(regname));
bytes = snprintf(bufp, size, trailinto(r2, f->locale), regname); snprintf(trail, sizeof(trail), trailinto(r2, f->locale), regname);
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, trail);
WARN_STATIC_BUFFER();
} }
else { else {
bytes = (int)str_strlcpy(bufp, " ", size); message * msg = msg_message("nr_vicinitystart", "dir region", d, r2);
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, " ");
WARN_STATIC_BUFFER(); append_message(&sbs, msg, f);
MSG(("nr_vicinitystart", "dir region", d, r2), bufp, size, f->locale, msg_release(msg);
f);
bufp += strlen(bufp);
dh = true; dh = true;
} }
} }
} }
if (dh) {
sbs_strcat(&sbs, ".");
}
/* Spezielle Richtungen */ /* Spezielle Richtungen */
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction; for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) { a = a->next) {
spec_direction *spd = (spec_direction *)(a->data.v); spec_direction *spd = (spec_direction *)(a->data.v);
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, spd->desc));
WARN_STATIC_BUFFER(); sbs_strcat(&sbs, " (\"");
bytes = (int)str_strlcpy(bufp, LOC(f->locale, spd->desc), size); sbs_strcat(&sbs, LOC(f->locale, spd->keyword));
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, "\").");
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, " (\"", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, LOC(f->locale, spd->keyword), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, "\")", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
dh = 1; dh = 1;
} }
} }
*bufp = 0; pump_paragraph(&sbs, out, REPORTWIDTH, true);
paragraph(out, buf, 0, 0, 0); }
/**
* Show roads and certain magic effects.
*/
static void report_region_edges(struct stream *out, const region * r, faction * f, struct edge edges[], int nedges) {
nr_curses(out, 0, f, TYP_REGION, r);
if (nedges > 0) {
int e;
newline(out);
for (e = 0; e != nedges; ++e) {
message *msg;
int d;
for (d = 0; d != MAXDIRECTIONS; ++d) {
if (edges[e].exist[d]) {
char buf[512];
msg = msg_message(edges[e].transparent ? "nr_border_transparent" : "nr_border_opaque",
"object dir", edges[e].name, d);
nr_render(msg, f->locale, buf, sizeof(buf), f);
msg_release(msg);
paragraph(out, buf, 0, 0, 0);
}
}
free(edges[e].name);
}
}
}
static void report_region_schemes(struct stream *out, const region * r, faction * f) {
char buf[4096];
char *bufp = buf;
size_t size = sizeof(buf);
int bytes;
if (r->seen.mode >= seen_unit && is_astral(r) && if (r->seen.mode >= seen_unit && is_astral(r) &&
!is_cursed(r->attribs, &ct_astralblock)) { !is_cursed(r->attribs, &ct_astralblock)) {
@ -1235,29 +1115,62 @@ void report_region(struct stream *out, const region * r, faction * f)
paragraph(out, buf, 0, 0, 0); paragraph(out, buf, 0, 0, 0);
} }
} }
}
/* Wirkungen permanenter Sprüche */ void report_region(struct stream *out, const region * r, faction * f)
nr_curses(out, 0, f, TYP_REGION, r); {
n = 0; int d, ne = 0;
bool see[MAXDIRECTIONS];
struct edge edges[MAX_EDGES];
if (ne > 0) { assert(out);
int e; assert(f);
newline(out); assert(r);
for (e = 0; e != ne; ++e) {
message *msg;
for (d = 0; d != MAXDIRECTIONS; ++d) { memset(edges, 0, sizeof(edges));
if (edges[e].exist[d]) { for (d = 0; d != MAXDIRECTIONS; d++) {
msg = msg_message(edges[e].transparent ? "nr_border_transparent" : "nr_border_opaque", /* Nachbarregionen, die gesehen werden, ermitteln */
"object dir", edges[e].name, d); region *r2 = rconnect(r, d);
nr_render(msg, f->locale, buf, sizeof(buf), f); connection *b;
msg_release(msg); see[d] = true;
paragraph(out, buf, 0, 0, 0); if (!r2)
continue;
for (b = get_borders(r, r2); b;) {
int e;
struct edge *match = NULL;
bool transparent = b->type->transparent(b, f);
const char *name = border_name(b, r, f, GF_DETAILED | GF_ARTICLE);
if (!transparent) {
see[d] = false;
}
if (!see_border(b, f, r)) {
b = b->next;
continue;
}
for (e = 0; e != ne; ++e) {
struct edge *edg = edges + e;
if (edg->transparent == transparent && 0 == strcmp(name, edg->name)) {
match = edg;
break;
} }
} }
free(edges[e].name); if (match == NULL) {
match = edges + ne;
match->name = str_strdup(name);
match->transparent = transparent;
++ne;
assert(ne < MAX_EDGES);
}
match->lastd = d;
match->exist[d] = true;
b = b->next;
} }
} }
report_region_description(out, r, f, see);
report_region_schemes(out, r, f);
report_region_edges(out, r, f, edges, ne);
} }
static void statistics(struct stream *out, const region * r, const faction * f) static void statistics(struct stream *out, const region * r, const faction * f)
@ -1555,15 +1468,19 @@ void pump_paragraph(sbstring *sbp, stream *out, size_t maxlen, bool isfinal)
return; return;
} }
else if (next > begin + maxlen) { else if (next > begin + maxlen) {
ptrdiff_t len = pos - begin; ptrdiff_t len;
if (pos == begin) {
/* there was no space before the break, line will be too long */
pos = next;
}
len = pos - begin;
swrite(begin, 1, len, out); swrite(begin, 1, len, out);
newline(out); newline(out);
while (*pos && IS_UTF8_SPACE(pos)) { while (*pos && IS_UTF8_SPACE(pos)) {
++pos; ++pos;
++len;
} }
sbs_substr(sbp, len, SIZE_MAX); sbs_substr(sbp, pos - begin, SIZE_MAX);
break; break;
} }
pos = next; pos = next;
@ -1664,7 +1581,7 @@ void report_allies(struct stream *out, size_t maxlen, const struct faction * f,
show.num_listed = 0; show.num_listed = 0;
show.maxlen = maxlen; show.maxlen = maxlen;
sbs_init(&show.sbs, buf, sizeof(buf)); sbs_init(&show.sbs, buf, sizeof(buf));
sbs_strcpy(&show.sbs, prefix); sbs_strcat(&show.sbs, prefix);
allies_walk(allies, show_allies_cb, &show); allies_walk(allies, show_allies_cb, &show);
} }
@ -2055,13 +1972,12 @@ report_plaintext(const char *filename, report_context * ctx,
attrib *a; attrib *a;
message *m; message *m;
unsigned char op; unsigned char op;
int maxh, bytes, ix = WANT_OPTION(O_STATISTICS); int maxh, ix = WANT_OPTION(O_STATISTICS);
int wants_stats = (f->options & ix); int wants_stats = (f->options & ix);
FILE *F = fopen(filename, "w"); FILE *F = fopen(filename, "w");
stream strm = { 0 }, *out = &strm; stream strm = { 0 }, *out = &strm;
char buf[8192]; char buf[1024];
char *bufp; sbstring sbs;
size_t size;
if (F == NULL) { if (F == NULL) {
perror(filename); perror(filename);
@ -2165,26 +2081,19 @@ report_plaintext(const char *filename, report_context * ctx,
centre(out, buf, true); centre(out, buf, true);
} }
bufp = buf; sbs_init(&sbs, buf, sizeof(buf));
size = sizeof(buf) - 1; sbs_strcat(&sbs, LOC(f->locale, "nr_options"));
bytes = snprintf(buf, size, "%s:", LOC(f->locale, "nr_options")); sbs_strcat(&sbs, ":");
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
for (op = 0; op != MAXOPTIONS; op++) { for (op = 0; op != MAXOPTIONS; op++) {
if (f->options & WANT_OPTION(op) && options[op]) { if (f->options & WANT_OPTION(op) && options[op]) {
bytes = (int)str_strlcpy(bufp, " ", size); sbs_strcat(&sbs, " ");
if (wrptr(&bufp, &size, bytes) != 0) sbs_strcat(&sbs, LOC(f->locale, options[op]));
WARN_STATIC_BUFFER();
bytes = (int)str_strlcpy(bufp, LOC(f->locale, options[op]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
flag++; ++flag;
} }
} }
if (flag > 0) { if (flag > 0) {
newline(out); newline(out);
*bufp = 0;
centre(out, buf, true); centre(out, buf, true);
} }
@ -2223,28 +2132,21 @@ report_plaintext(const char *filename, report_context * ctx,
centre(out, buf, true); centre(out, buf, true);
newline(out); newline(out);
bufp = buf; sbs_init(&sbs, buf, sizeof(buf));
size = sizeof(buf) - 1; sbs_strcat(&sbs, LOC(f->locale, "nr_herbsrequired"));
bytes = snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_herbsrequired")); sbs_strcat(&sbs, ":");
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (itype->construction) { if (itype->construction) {
requirement *rm = itype->construction->materials; requirement *rm = itype->construction->materials;
while (rm->number) { while (rm->number) {
bytes = sbs_strcat(&sbs, LOC(f->locale, resourcename(rm->rtype, 0)));
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
++rm; ++rm;
if (rm->number) if (rm->number) {
bytes = (int)str_strlcpy(bufp, ", ", size); sbs_strcat(&sbs, ", ");
if (wrptr(&bufp, &size, bytes) != 0) }
WARN_STATIC_BUFFER();
} }
assert(!rm->rtype); assert(!rm->rtype);
} }
*bufp = 0;
centre(out, buf, true); centre(out, buf, true);
newline(out); newline(out);
description = mkname("describe", pname); description = mkname("describe", pname);

View file

@ -106,12 +106,30 @@ static void test_report_region(CuTest *tc) {
rsettrees(r, 0, 1); rsettrees(r, 0, 1);
rsettrees(r, 1, 2); rsettrees(r, 1, 2);
rsettrees(r, 2, 3); rsettrees(r, 2, 3);
region_setname(r, "Hodor");
f = test_create_faction(NULL); f = test_create_faction(NULL);
f->locale = lang; f->locale = lang;
u = test_create_unit(f, r); u = test_create_unit(f, r);
set_level(u, SK_QUARRYING, 1); set_level(u, SK_QUARRYING, 1);
region_setname(r, "1234567890123456789012345678901234567890");
r->seen.mode = seen_travel;
report_region(&out, r, f);
out.api->rewind(out.handle);
len = out.api->read(out.handle, buf, sizeof(buf));
buf[len] = '\0';
CuAssertStrEquals(tc, "1234567890123456789012345678901234567890 (0,0) (durchgereist), Ebene, 3/2\nBlumen, 5 Bauern, 2 Silber, 7 Pferde.\n", buf);
out.api->rewind(out.handle);
region_setname(r, "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
r->seen.mode = seen_travel;
report_region(&out, r, f);
out.api->rewind(out.handle);
len = out.api->read(out.handle, buf, sizeof(buf));
buf[len] = '\0';
CuAssertStrEquals(tc, "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n(0,0) (durchgereist), Ebene, 3/2 Blumen, 5 Bauern, 2 Silber, 7 Pferde.\n", buf);
out.api->rewind(out.handle);
region_setname(r, "Hodor");
r->seen.mode = seen_travel; r->seen.mode = seen_travel;
report_region(&out, r, f); report_region(&out, r, f);
out.api->rewind(out.handle); out.api->rewind(out.handle);
@ -119,27 +137,40 @@ static void test_report_region(CuTest *tc) {
buf[len] = '\0'; buf[len] = '\0';
CuAssertStrEquals(tc, "Hodor (0,0) (durchgereist), Ebene, 3/2 Blumen, 5 Bauern, 2 Silber, 7 Pferde.\n", buf); CuAssertStrEquals(tc, "Hodor (0,0) (durchgereist), Ebene, 3/2 Blumen, 5 Bauern, 2 Silber, 7 Pferde.\n", buf);
r->seen.mode = seen_unit;
out.api->rewind(out.handle); out.api->rewind(out.handle);
r->seen.mode = seen_unit;
report_region(&out, r, f); report_region(&out, r, f);
out.api->rewind(out.handle); out.api->rewind(out.handle);
len = out.api->read(out.handle, buf, sizeof(buf)); len = out.api->read(out.handle, buf, sizeof(buf));
buf[len] = '\0'; buf[len] = '\0';
CuAssertStrEquals(tc, "Hodor (0,0), Ebene, 3/2 Blumen, 135 Steine/1, 5 Bauern, 2 Silber, 7 Pferde.\n", buf); CuAssertStrEquals(tc, "Hodor (0,0), Ebene, 3/2 Blumen, 135 Steine/1, 5 Bauern, 2 Silber, 7 Pferde.\n", buf);
out.api->rewind(out.handle);
r->resources->amount = 1; r->resources->amount = 1;
r->land->peasants = 1; r->land->peasants = 1;
r->land->horses = 1; r->land->horses = 1;
r->land->money = 1; r->land->money = 1;
r->seen.mode = seen_unit; r->seen.mode = seen_unit;
out.api->rewind(out.handle);
report_region(&out, r, f); report_region(&out, r, f);
out.api->rewind(out.handle); out.api->rewind(out.handle);
len = out.api->read(out.handle, buf, sizeof(buf)); len = out.api->read(out.handle, buf, sizeof(buf));
buf[len] = '\0'; buf[len] = '\0';
CuAssertStrEquals(tc, "Hodor (0,0), Ebene, 3/2 Blumen, 1 Stein/1, 1 Bauer, 1 Silber, 1 Pferd.\n", buf); CuAssertStrEquals(tc, "Hodor (0,0), Ebene, 3/2 Blumen, 1 Stein/1, 1 Bauer, 1 Silber, 1 Pferd.\n", buf);
r->land->peasants = 0;
r->land->horses = 0;
r->land->money = 0;
rsettrees(r, 0, 0);
rsettrees(r, 1, 0);
rsettrees(r, 2, 0);
out.api->rewind(out.handle);
report_region(&out, r, f);
out.api->rewind(out.handle);
len = out.api->read(out.handle, buf, sizeof(buf));
buf[len] = '\0';
CuAssertStrEquals(tc, "Hodor (0,0), Ebene, 1 Stein/1.\n", buf);
mstream_done(&out); mstream_done(&out);
test_teardown(); test_teardown();
} }

View file

@ -263,13 +263,23 @@ char *str_strdup(const char *s) {
void sbs_init(struct sbstring *sbs, char *buffer, size_t size) void sbs_init(struct sbstring *sbs, char *buffer, size_t size)
{ {
assert(sbs); assert(sbs);
assert(size>0); assert(size > 0);
sbs->begin = buffer; sbs->begin = buffer;
sbs->size = size; sbs->size = size;
sbs->end = buffer; sbs->end = buffer;
buffer[0] = '\0'; buffer[0] = '\0';
} }
void sbs_adopt(struct sbstring *sbs, char *buffer, size_t size)
{
size_t len = strlen(buffer);
assert(sbs);
assert(size > len);
sbs->begin = buffer;
sbs->size = size;
sbs->end = buffer + len;
}
void sbs_strncat(struct sbstring *sbs, const char *str, size_t size) void sbs_strncat(struct sbstring *sbs, const char *str, size_t size)
{ {
size_t len; size_t len;

View file

@ -50,6 +50,7 @@ extern "C" {
} sbstring; } sbstring;
void sbs_init(struct sbstring *sbs, char *buffer, size_t size); void sbs_init(struct sbstring *sbs, char *buffer, size_t size);
void sbs_adopt(struct sbstring *sbs, char *buffer, size_t size);
void sbs_strcat(struct sbstring *sbs, const char *str); void sbs_strcat(struct sbstring *sbs, const char *str);
void sbs_strncat(struct sbstring *sbs, const char *str, size_t size); void sbs_strncat(struct sbstring *sbs, const char *str, size_t size);
void sbs_strcpy(struct sbstring *sbs, const char *str); void sbs_strcpy(struct sbstring *sbs, const char *str);

View file

@ -157,6 +157,10 @@ static void test_sbstring(CuTest * tc)
CuAssertStrEquals(tc, "12345678901234", sbs.begin); CuAssertStrEquals(tc, "12345678901234", sbs.begin);
sbs_strncat(&sbs, "567890", 6); sbs_strncat(&sbs, "567890", 6);
CuAssertStrEquals(tc, "123456789012345", sbs.begin); CuAssertStrEquals(tc, "123456789012345", sbs.begin);
sbs_adopt(&sbs, buffer + 2, sizeof(buffer) - 2);
CuAssertStrEquals(tc, "3456789012345", sbs.begin);
CuAssertIntEquals(tc, 13, sbs_length(&sbs));
} }
static void test_sbs_strcat(CuTest * tc) static void test_sbs_strcat(CuTest * tc)