server/src/gamecode/report.c

2632 lines
70 KiB
C
Raw Normal View History

2010-08-08 10:06:34 +02:00
/*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#define ECHECK_VERSION "4.01"
#include <platform.h>
#include <kernel/config.h>
/* modules includes */
#include <modules/score.h>
/* attributes includes */
#include <attributes/overrideroads.h>
#include <attributes/otherfaction.h>
#include <attributes/alliance.h>
#include <attributes/reduceproduction.h>
/* gamecode includes */
#include "creport.h"
#include "economy.h"
#include "monster.h"
#include "laws.h"
/* kernel includes */
#include <kernel/alchemy.h>
#include <kernel/ally.h>
2010-08-08 10:06:34 +02:00
#include <kernel/connection.h>
#include <kernel/build.h>
#include <kernel/building.h>
#include <kernel/calendar.h>
2012-06-03 22:39:42 +02:00
#include <kernel/curse.h>
2010-08-08 10:06:34 +02:00
#include <kernel/faction.h>
#include <kernel/group.h>
#include <kernel/item.h>
#include <kernel/message.h>
#include <kernel/move.h>
#include <kernel/objtypes.h>
#include <kernel/order.h>
#include <kernel/plane.h>
#include <kernel/pool.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/render.h>
#include <kernel/reports.h>
#include <kernel/resources.h>
#include <kernel/save.h>
#include <kernel/ship.h>
#include <kernel/skill.h>
#include <kernel/spell.h>
#include <kernel/spellbook.h>
2010-08-08 10:06:34 +02:00
#include <kernel/teleport.h>
#include <kernel/terrain.h>
#include <kernel/terrainid.h>
#include <kernel/unit.h>
#include <kernel/alliance.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/bsdstring.h>
#include <util/goodies.h>
#include <util/language.h>
#include <util/lists.h>
#include <util/log.h>
#include <util/message.h>
#include <util/nrmessage.h>
#include <quicklist.h>
2010-08-08 10:06:34 +02:00
#include <util/rng.h>
#include <libxml/encoding.h>
/* libc includes */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#ifdef HAVE_STAT
#include <sys/types.h>
#include <sys/stat.h>
#endif
extern int verbosity;
extern int *storms;
2011-03-07 08:02:35 +01:00
extern int weeks_per_month;
extern int months_per_year;
static char *gamedate_season(const struct locale *lang)
2010-08-08 10:06:34 +02:00
{
static char buf[256];
gamedate gd;
get_gamedate(turn, &gd);
sprintf(buf, (const char *)LOC(lang, "nr_calendar_season"),
LOC(lang, weeknames[gd.week]),
LOC(lang, monthnames[gd.month]),
gd.year,
2011-03-07 08:02:35 +01:00
agename ? LOC(lang, agename) : "", LOC(lang, seasonnames[gd.season]));
2010-08-08 10:06:34 +02:00
return buf;
}
2011-03-07 08:02:35 +01:00
void rpc(FILE * F, char c, size_t num)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
while (num > 0) {
2010-08-08 10:06:34 +02:00
putc(c, F);
num--;
}
}
2011-03-07 08:02:35 +01:00
void rnl(FILE * F)
2010-08-08 10:06:34 +02:00
{
fputc('\n', F);
}
static void centre(FILE * F, const char *s, bool breaking)
2010-08-08 10:06:34 +02:00
{
/* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme
* geben. Seltsamerweise wird i dann auf MAXINT oder aehnlich
* initialisiert. Deswegen keine Strings die laenger als REPORTWIDTH
* sind! */
if (breaking && REPORTWIDTH < strlen(s)) {
strlist *T, *SP = 0;
sparagraph(&SP, s, 0, 0);
T = SP;
while (SP) {
centre(F, SP->s, false);
SP = SP->next;
}
freestrlist(T);
} else {
2011-03-07 08:02:35 +01:00
rpc(F, ' ', (REPORTWIDTH - strlen(s) + 1) / 2);
2010-08-08 10:06:34 +02:00
fputs(s, F);
putc('\n', F);
}
}
static void
2011-03-07 08:02:35 +01:00
rparagraph(FILE * F, const char *str, ptrdiff_t indent, int hanging_indent,
char mark)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
static const char *spaces = " ";
2010-08-08 10:06:34 +02:00
size_t length = REPORTWIDTH;
2011-03-07 08:02:35 +01:00
const char *end, *begin;
2010-08-08 10:06:34 +02:00
if (!str) return;
2010-08-08 10:06:34 +02:00
/* find out if there's a mark + indent already encoded in the string. */
if (!mark) {
2011-03-07 08:02:35 +01:00
const char *x = str;
while (*x == ' ')
++x;
2010-08-08 10:06:34 +02:00
indent += x - str;
2011-03-07 08:02:35 +01:00
if (x[0] && indent && x[1] == ' ') {
2010-08-08 10:06:34 +02:00
indent += 2;
mark = x[0];
str = x + 2;
hanging_indent -= 2;
}
}
begin = end = str;
do {
2011-03-07 08:02:35 +01:00
const char *last_space = begin;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
if (mark && indent >= 2) {
fwrite(spaces, sizeof(char), indent - 2, F);
2010-08-08 10:06:34 +02:00
fputc(mark, F);
fputc(' ', F);
mark = 0;
2011-03-07 08:02:35 +01:00
} else if (begin == str) {
2010-08-08 10:06:34 +02:00
fwrite(spaces, sizeof(char), indent, F);
} else {
2011-03-07 08:02:35 +01:00
fwrite(spaces, sizeof(char), indent + hanging_indent, F);
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
while (*end && end <= begin + length - indent) {
if (*end == ' ') {
2010-08-08 10:06:34 +02:00
last_space = end;
}
++end;
}
2011-03-07 08:02:35 +01:00
if (*end == 0)
last_space = end;
if (last_space == begin) {
2010-08-08 10:06:34 +02:00
/* there was no space in this line. clip it */
last_space = end;
}
2011-03-07 08:02:35 +01:00
fwrite(begin, sizeof(char), last_space - begin, F);
2010-08-08 10:06:34 +02:00
begin = last_space;
2011-03-07 08:02:35 +01:00
while (*begin == ' ') {
2010-08-08 10:06:34 +02:00
++begin;
}
2011-03-07 08:02:35 +01:00
if (begin > end)
begin = end;
2010-08-08 10:06:34 +02:00
fputc('\n', F);
} while (*begin);
}
static void nr_spell(FILE * F, spellbook_entry * sbe, const struct locale *lang)
2010-08-08 10:06:34 +02:00
{
int bytes, k, itemanz, costtyp;
int dh = 0;
char buf[4096];
2011-03-07 08:02:35 +01:00
char *bufp = buf;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buf) - 1;
spell * sp = sbe->sp;
2011-03-07 08:02:35 +01:00
const char *params = sp->parameter;
2010-08-08 10:06:34 +02:00
rnl(F);
centre(F, spell_name(sp, lang), true);
rnl(F);
rparagraph(F, LOC(lang, "nr_spell_description"), 0, 0, 0);
rparagraph(F, spell_info(sp, lang), 2, 0, 0);
bytes = (int)strlcpy(bufp, LOC(lang, "nr_spell_type"), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (size) {
*bufp++ = ' ';
--size;
}
2010-08-08 10:06:34 +02:00
if (sp->sptyp & PRECOMBATSPELL) {
bytes = (int)strlcpy(bufp, LOC(lang, "sptype_precombat"), size);
} else if (sp->sptyp & COMBATSPELL) {
bytes = (int)strlcpy(bufp, LOC(lang, "sptype_combat"), size);
} else if (sp->sptyp & POSTCOMBATSPELL) {
bytes = (int)strlcpy(bufp, LOC(lang, "sptype_postcombat"), size);
} else {
bytes = (int)strlcpy(bufp, LOC(lang, "sptype_normal"), size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
sprintf(buf, "%s %d", LOC(lang, "nr_spell_level"), sbe->level);
2010-08-08 10:06:34 +02:00
rparagraph(F, buf, 0, 0, 0);
sprintf(buf, "%s %d", LOC(lang, "nr_spell_rank"), sp->rank);
rparagraph(F, buf, 0, 0, 0);
rparagraph(F, LOC(lang, "nr_spell_components"), 0, 0, 0);
for (k = 0; sp->components[k].type; ++k) {
2011-03-07 08:02:35 +01:00
const resource_type *rtype = sp->components[k].type;
2010-08-08 10:06:34 +02:00
itemanz = sp->components[k].amount;
costtyp = sp->components[k].cost;
if (itemanz > 0) {
size = sizeof(buf) - 1;
bufp = buf;
if (sp->sptyp & SPELLLEVEL) {
2011-03-07 08:02:35 +01:00
bytes =
snprintf(bufp, size, " %d %s", itemanz, LOC(lang, resourcename(rtype,
itemanz != 1)));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR) {
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, " * %s", LOC(lang, "nr_level"));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
} else {
bytes = snprintf(bufp, size, "%d %s", itemanz, LOC(lang, resourcename(rtype, itemanz != 1)));
if (wrptr(&bufp, &size, bytes) != 0) {
2011-03-07 08:02:35 +01:00
WARN_STATIC_BUFFER();
}
2010-08-08 10:06:34 +02:00
}
*bufp = 0;
rparagraph(F, buf, 2, 2, '-');
}
}
size = sizeof(buf) - 1;
2011-03-07 08:02:35 +01:00
bufp = buf;
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(buf, LOC(lang, "nr_spell_modifiers"), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (sp->sptyp & FARCASTING) {
bytes = (int)strlcpy(bufp, " Fernzauber", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
dh = 1;
}
if (sp->sptyp & OCEANCASTABLE) {
if (dh == 1) {
bytes = (int)strlcpy(bufp, ",", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, " Seezauber", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
dh = 1;
}
if (sp->sptyp & ONSHIPCAST) {
2011-03-07 08:02:35 +01:00
if (dh == 1) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, ",", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, " Schiffszauber", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
dh = 1;
}
if (sp->sptyp & NOTFAMILIARCAST) {
if (dh == 1) {
bytes = (int)strlcpy(bufp, ", k", size);
} else {
bytes = (int)strlcpy(bufp, " K", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)strlcpy(bufp, "ann nicht vom Vertrauten gezaubert werden", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
dh = 1;
}
if (dh == 0) {
bytes = (int)strlcpy(bufp, " Keine", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
rparagraph(F, LOC(lang, "nr_spell_syntax"), 0, 0, 0);
bufp = buf;
size = sizeof(buf) - 1;
2011-03-07 08:02:35 +01:00
2010-08-08 10:06:34 +02:00
if (sp->sptyp & ISCOMBATSPELL) {
bytes = (int)strlcpy(bufp, LOC(lang, keywords[K_COMBATSPELL]), size);
} else {
bytes = (int)strlcpy(bufp, LOC(lang, keywords[K_CAST]), size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
/* Reihenfolge beachten: Erst REGION, dann STUFE! */
if (sp->sptyp & FARCASTING) {
bytes = snprintf(bufp, size, " [%s x y]", LOC(lang, parameters[P_REGION]));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (sp->sptyp & SPELLLEVEL) {
bytes = snprintf(bufp, size, " [%s n]", LOC(lang, parameters[P_LEVEL]));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)snprintf(bufp, size, " \"%s\"", spell_name(sp, lang));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
while (params && *params) {
typedef struct starget {
param_t param;
int flag;
2011-03-07 08:02:35 +01:00
const char *vars;
2010-08-08 10:06:34 +02:00
} starget;
2011-03-07 08:02:35 +01:00
starget targets[] = {
{P_REGION, REGIONSPELL, NULL},
{P_UNIT, UNITSPELL, "par_unit"},
{P_SHIP, SHIPSPELL, "par_ship"},
{P_BUILDING, BUILDINGSPELL, "par_building"},
{0, 0, NULL}
2010-08-08 10:06:34 +02:00
};
2011-03-07 08:02:35 +01:00
starget *targetp;
2010-08-08 10:06:34 +02:00
char cp = *params++;
int i, maxparam = 0;
2011-03-07 08:02:35 +01:00
const char *locp;
const char *syntaxp = sp->syntax;
if (cp == 'u') {
targetp = targets + 1;
2010-08-08 10:06:34 +02:00
locp = LOC(lang, targetp->vars);
bytes = (int)snprintf(bufp, size, " <%s>", locp);
2011-03-07 08:02:35 +01:00
if (*params == '+') {
2010-08-08 10:06:34 +02:00
++params;
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)snprintf(bufp, size, " [<%s> ...]", locp);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else if (cp == 's') {
targetp = targets + 2;
2010-08-08 10:06:34 +02:00
locp = LOC(lang, targetp->vars);
bytes = (int)snprintf(bufp, size, " <%s>", locp);
2011-03-07 08:02:35 +01:00
if (*params == '+') {
2010-08-08 10:06:34 +02:00
++params;
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)snprintf(bufp, size, " [<%s> ...]", locp);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else if (cp == 'r') {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " <x> <y>", size);
2011-03-07 08:02:35 +01:00
if (*params == '+') {
2010-08-08 10:06:34 +02:00
++params;
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " [<x> <y> ...]", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else if (cp == 'b') {
targetp = targets + 3;
2010-08-08 10:06:34 +02:00
locp = LOC(lang, targetp->vars);
bytes = (int)snprintf(bufp, size, " <%s>", locp);
2011-03-07 08:02:35 +01:00
if (*params == '+') {
2010-08-08 10:06:34 +02:00
++params;
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)snprintf(bufp, size, " [<%s> ...]", locp);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else if (cp == 'k') {
if (*params == 'c') {
2010-08-08 10:06:34 +02:00
/* skip over a potential id */
++params;
}
2011-03-07 08:02:35 +01:00
for (targetp = targets; targetp->flag; ++targetp) {
if (sp->sptyp & targetp->flag)
++maxparam;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (maxparam > 1) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
i = 0;
2011-03-07 08:02:35 +01:00
for (targetp = targets; targetp->flag; ++targetp) {
if (sp->sptyp & targetp->flag) {
if (i++ != 0) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " |", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (targetp->param) {
locp = LOC(lang, targetp->vars);
2011-03-07 08:02:35 +01:00
bytes =
(int)snprintf(bufp, size, " %s <%s>", parameters[targetp->param],
locp);
if (*params == '+') {
2010-08-08 10:06:34 +02:00
++params;
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)snprintf(bufp, size, " [<%s> ...]", locp);
}
} else {
2011-03-07 08:02:35 +01:00
bytes =
(int)snprintf(bufp, size, " %s", parameters[targetp->param]);
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
if (maxparam > 1) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " )", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
} else if (cp == 'i' || cp == 'c') {
const char *cstr;
2010-08-08 10:06:34 +02:00
assert(syntaxp);
cstr = strchr(syntaxp, ':');
if (!cstr) {
locp = LOC(lang, mkname("spellpar", syntaxp));
} else {
char substr[32];
2011-03-07 08:02:35 +01:00
strncpy(substr, syntaxp, cstr - syntaxp);
substr[cstr - syntaxp] = 0;
2010-08-08 10:06:34 +02:00
locp = LOC(lang, mkname("spellpar", substr));
syntaxp = substr + 1;
}
bytes = (int)snprintf(bufp, size, " <%s>", locp);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
*bufp = 0;
rparagraph(F, buf, 2, 0, 0);
rnl(F);
}
2011-03-07 08:02:35 +01:00
void sparagraph(strlist ** SP, const char *s, int indent, char mark)
2010-08-08 10:06:34 +02:00
{
/* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer
* mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf.
* Vgl. spunit (). */
int i, j, width;
int firstline;
static char buf[REPORTWIDTH + 1];
width = REPORTWIDTH - indent;
firstline = 1;
for (;;) {
i = 0;
do {
j = i;
while (s[j] && s[j] != ' ')
j++;
if (j > width) {
/* j zeigt auf das ende der aktuellen zeile, i zeigt auf den anfang der
* n<EFBFBD>chsten zeile. existiert ein wort am anfang der zeile, welches
* l<EFBFBD>nger als eine zeile ist, muss dieses hier abgetrennt werden. */
if (i == 0)
i = width - 1;
break;
}
i = j + 1;
}
while (s[j]);
for (j = 0; j != indent; j++)
buf[j] = ' ';
if (firstline && mark)
buf[indent - 2] = mark;
for (j = 0; j != i - 1; j++)
buf[indent + j] = s[j];
buf[indent + j] = 0;
addstrlist(SP, buf);
if (s[i - 1] == 0)
break;
s += i;
firstline = 0;
}
}
2011-03-07 08:02:35 +01:00
int hat_in_region(item_t it, region * r, faction * f)
2010-08-08 10:06:34 +02:00
{
unit *u;
for (u = r->units; u; u = u->next) {
if (u->faction == f && get_item(u, it) > 0) {
return 1;
}
}
return 0;
}
static void
nr_curses(FILE * F, const faction * viewer, const void *obj, objtype_t typ,
2011-03-07 08:02:35 +01:00
int indent)
2010-08-08 10:06:34 +02:00
{
attrib *a = NULL;
int self = 0;
region *r;
/* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei
* Geb<EFBFBD>uden und Schiffen je nach, ob man Besitzer ist, verschieden.
* Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer.
* Spezialf<EFBFBD>lle (besonderes Talent, verursachender Magier usw. werde
* bei jedem curse gesondert behandelt. */
2011-03-07 08:02:35 +01:00
if (typ == TYP_SHIP) {
ship *sh = (ship *) obj;
unit *owner = ship_owner(sh);
2010-08-08 10:06:34 +02:00
a = sh->attribs;
r = sh->region;
if (owner) {
2011-03-07 08:02:35 +01:00
if (owner->faction == viewer) {
2010-08-08 10:06:34 +02:00
self = 2;
2011-03-07 08:02:35 +01:00
} else { /* steht eine person der Partei auf dem Schiff? */
2010-08-08 10:06:34 +02:00
unit *u = NULL;
for (u = r->units; u; u = u->next) {
if (u->ship == sh) {
self = 1;
break;
}
}
}
}
} else if (typ == TYP_BUILDING) {
2011-03-07 08:02:35 +01:00
building *b = (building *) obj;
unit *owner;
2010-08-08 10:06:34 +02:00
a = b->attribs;
r = b->region;
2011-03-07 08:02:35 +01:00
if ((owner = building_owner(b)) != NULL) {
if (owner->faction == viewer) {
2010-08-08 10:06:34 +02:00
self = 2;
2011-03-07 08:02:35 +01:00
} else { /* steht eine Person der Partei in der Burg? */
2010-08-08 10:06:34 +02:00
unit *u = NULL;
for (u = r->units; u; u = u->next) {
if (u->building == b) {
self = 1;
break;
}
}
}
}
} else if (typ == TYP_UNIT) {
2011-03-07 08:02:35 +01:00
unit *u = (unit *) obj;
2010-08-08 10:06:34 +02:00
a = u->attribs;
r = u->region;
2011-03-07 08:02:35 +01:00
if (u->faction == viewer) {
2010-08-08 10:06:34 +02:00
self = 2;
}
} else if (typ == TYP_REGION) {
2011-03-07 08:02:35 +01:00
r = (region *) obj;
2010-08-08 10:06:34 +02:00
a = r->attribs;
} else {
/* fehler */
}
2011-03-07 08:02:35 +01:00
for (; a; a = a->next) {
2010-08-08 10:06:34 +02:00
char buf[4096];
if (fval(a->type, ATF_CURSE)) {
2011-03-07 08:02:35 +01:00
curse *c = (curse *) a->data.v;
message *msg;
2010-08-08 10:06:34 +02:00
if (c->type->cansee) {
self = c->type->cansee(viewer, obj, typ, c, self);
}
msg = msg_curse(c, obj, typ, self);
if (msg) {
rnl(F);
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
rparagraph(F, buf, indent, 2, 0);
msg_release(msg);
}
2011-03-07 08:02:35 +01:00
} else if (a->type == &at_effect && self) {
effect_data *data = (effect_data *) a->data.v;
if (data->value > 0) {
2010-08-08 10:06:34 +02:00
sprintf(buf, "Auf der Einheit lieg%s %d Wirkung%s %s.",
2011-03-07 08:02:35 +01:00
(data->value == 1 ? "t" : "en"),
2010-08-08 10:06:34 +02:00
data->value,
2011-03-07 08:02:35 +01:00
(data->value == 1 ? "" : "en"),
2010-08-08 10:06:34 +02:00
LOC(default_locale, resourcename(data->type->itype->rtype, 0)));
rnl(F);
rparagraph(F, buf, indent, 2, 0);
}
}
}
}
2011-03-07 08:02:35 +01:00
static void rps_nowrap(FILE * F, const char *s)
2010-08-08 10:06:34 +02:00
{
const char *x = s;
size_t indent = 0;
2011-03-07 08:02:35 +01:00
while (*x++ == ' ') ;
2010-08-08 10:06:34 +02:00
indent = x - s - 1;
if (*(x - 1) && indent && *x == ' ')
indent += 2;
x = s;
while (*s) {
if (s == x) {
x = strchr(x + 1, ' ');
if (!x)
x = s + strlen(s);
}
rpc(F, *s++, 1);
}
}
static void
nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
{
attrib *a_otherfaction;
char marker;
int dh;
bool isbattle = (bool) (mode == see_battle);
2010-08-08 10:06:34 +02:00
char buf[8192];
2011-03-07 08:02:35 +01:00
if (fval(u->race, RCF_INVISIBLE))
return;
2010-08-08 10:06:34 +02:00
{
rnl(F);
dh = bufunit(f, u, indent, mode, buf, sizeof(buf));
}
a_otherfaction = a_find(u->attribs, &at_otherfaction);
if (u->faction == f) {
marker = '*';
2011-03-07 08:02:35 +01:00
} else if ALLIED
(u->faction, f) {
2010-08-08 10:06:34 +02:00
marker = 'o';
2011-03-07 08:02:35 +01:00
} else if (a_otherfaction && f != u->faction
&& get_otherfaction(a_otherfaction) == f && !fval(u, UFL_ANON_FACTION)) {
2010-08-08 10:06:34 +02:00
marker = '!';
} else {
if (dh && !fval(u, UFL_ANON_FACTION)) {
marker = '+';
} else {
marker = '-';
}
}
rparagraph(F, buf, indent, 0, marker);
if (!isbattle) {
nr_curses(F, f, u, TYP_UNIT, indent);
}
}
static void
2011-03-07 08:02:35 +01:00
rp_messages(FILE * F, message_list * msgs, faction * viewer, int indent,
bool categorized)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
nrsection *section;
if (!msgs)
return;
for (section = sections; section; section = section->next) {
2010-08-08 10:06:34 +02:00
int k = 0;
2011-03-07 08:02:35 +01:00
struct mlist *m = msgs->begin;
2010-08-08 10:06:34 +02:00
while (m) {
/* messagetype * mt = m->type; */
2011-03-07 08:02:35 +01:00
if (!categorized || strcmp(nr_section(m->msg), section->name) == 0) {
2010-08-08 10:06:34 +02:00
char lbuf[8192];
if (!k && categorized) {
2011-03-07 08:02:35 +01:00
const char *section_title;
2010-08-08 10:06:34 +02:00
char cat_identifier[24];
rnl(F);
sprintf(cat_identifier, "section_%s", section->name);
section_title = LOC(viewer->locale, cat_identifier);
centre(F, section_title, true);
rnl(F);
k = 1;
}
nr_render(m->msg, viewer->locale, lbuf, sizeof(lbuf), viewer);
rparagraph(F, lbuf, indent, 2, 0);
}
m = m->next;
}
2011-03-07 08:02:35 +01:00
if (!categorized)
break;
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
static void rp_battles(FILE * F, faction * f)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
if (f->battles != NULL) {
struct bmsg *bm = f->battles;
2010-08-08 10:06:34 +02:00
rnl(F);
centre(F, LOC(f->locale, "section_battle"), false);
rnl(F);
while (bm) {
char buf[256];
RENDER(f, buf, sizeof(buf), ("battle::header", "region", bm->r));
rnl(F);
centre(F, buf, true);
rnl(F);
rp_messages(F, bm->msgs, f, 0, false);
bm = bm->next;
}
}
}
2011-03-07 08:02:35 +01:00
static void prices(FILE * F, const region * r, const faction * f)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
const luxury_type *sale = NULL;
struct demand *dmd;
message *m;
2010-08-08 10:06:34 +02:00
int bytes, n = 0;
2011-03-07 08:02:35 +01:00
char buf[4096], *bufp = buf;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buf) - 1;
2011-03-07 08:02:35 +01:00
if (r->land == NULL || r->land->demands == NULL)
return;
for (dmd = r->land->demands; dmd; dmd = dmd->next) {
if (dmd->value == 0)
sale = dmd->type;
else if (dmd->value > 0)
n++;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
assert(sale != NULL);
2010-08-08 10:06:34 +02:00
m = msg_message("nr_market_sale", "product price",
sale->itype->rtype, sale->price);
bytes = (int)nr_render(m, f->locale, bufp, size, f);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
msg_release(m);
if (n > 0) {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_intro"), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
for (dmd = r->land->demands; dmd; dmd = dmd->next)
if (dmd->value > 0) {
m = msg_message("nr_market_price", "product price",
dmd->type->itype->rtype, dmd->value * dmd->type->price);
bytes = (int)nr_render(m, f->locale, bufp, size, f);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
msg_release(m);
n--;
if (n == 0) {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_end"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else if (n == 1) {
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_final"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_next"), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
2010-08-08 10:06:34 +02:00
}
}
/* Schreibe Paragraphen */
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
}
bool see_border(const connection * b, const faction * f, const region * r)
2010-08-08 10:06:34 +02:00
{
bool cs = b->type->fvisible(b, f, r);
2010-08-08 10:06:34 +02:00
if (!cs) {
cs = b->type->rvisible(b, r);
if (!cs) {
2011-03-07 08:02:35 +01:00
const unit *us = r->units;
2010-08-08 10:06:34 +02:00
while (us && !cs) {
2011-03-07 08:02:35 +01:00
if (us->faction == f) {
2010-08-08 10:06:34 +02:00
cs = b->type->uvisible(b, us);
2011-03-07 08:02:35 +01:00
if (cs)
break;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
us = us->next;
2010-08-08 10:06:34 +02:00
}
}
}
return cs;
}
2011-03-07 08:02:35 +01:00
static void describe(FILE * F, const seen_region * sr, faction * f)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
const region *r = sr->r;
2010-08-08 10:06:34 +02:00
int n;
bool dh;
2010-08-08 10:06:34 +02:00
direction_t d;
int trees;
int saplings;
attrib *a;
const char *tname;
struct edge {
2011-03-07 08:02:35 +01:00
struct edge *next;
char *name;
bool transparent;
bool block;
bool exist[MAXDIRECTIONS];
2010-08-08 10:06:34 +02:00
direction_t lastd;
2011-03-07 08:02:35 +01:00
} *edges = NULL, *e;
bool see[MAXDIRECTIONS];
2010-08-08 10:06:34 +02:00
char buf[8192];
2011-03-07 08:02:35 +01:00
char *bufp = buf;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buf);
int bytes;
for (d = 0; d != MAXDIRECTIONS; d++) {
/* Nachbarregionen, die gesehen werden, ermitteln */
region *r2 = rconnect(r, d);
connection *b;
see[d] = true;
2011-03-07 08:02:35 +01:00
if (!r2)
continue;
for (b = get_borders(r, r2); b;) {
struct edge *e = edges;
bool transparent = b->type->transparent(b, f);
2011-03-07 08:02:35 +01:00
const char *name = b->type->name(b, r, f, GF_DETAILED | GF_ARTICLE);
if (!transparent)
see[d] = false;
2010-08-08 10:06:34 +02:00
if (!see_border(b, f, r)) {
b = b->next;
continue;
}
2011-03-07 08:02:35 +01:00
while (e && (e->transparent != transparent || strcmp(name, e->name)))
e = e->next;
2010-08-08 10:06:34 +02:00
if (!e) {
e = calloc(sizeof(struct edge), 1);
e->name = strdup(name);
e->transparent = transparent;
e->next = edges;
edges = e;
}
2011-03-07 08:02:35 +01:00
e->lastd = d;
2010-08-08 10:06:34 +02:00
e->exist[d] = true;
b = b->next;
}
}
bytes = (int)f_regionid(r, f, bufp, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (sr->mode == see_travel) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (durchgereist)", size);
2011-03-07 08:02:35 +01:00
} else if (sr->mode == see_neighbour) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (benachbart)", size);
2011-03-07 08:02:35 +01:00
} else if (sr->mode == see_lighthouse) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (vom Turm erblickt)", size);
} else {
bytes = 0;
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
/* Terrain */
bytes = (int)strlcpy(bufp, ", ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
tname = terrain_name(r);
bytes = (int)strlcpy(bufp, LOC(f->locale, tname), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
/* Trees */
2011-03-07 08:02:35 +01:00
trees = rtrees(r, 2);
saplings = rtrees(r, 1);
2010-08-08 10:06:34 +02:00
if (production(r)) {
if (trees > 0 || saplings > 0) {
bytes = snprintf(bufp, size, ", %d/%d ", trees, saplings);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (fval(r, RF_MALLORN)) {
if (trees == 1) {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_mallorntree"), size);
} else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_mallorntree_p"), size);
}
2011-03-07 08:02:35 +01:00
} else if (trees == 1) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_tree"), size);
} else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_tree_p"), size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
/* iron & stone */
2011-03-07 08:02:35 +01:00
if (sr->mode == see_unit && f != (faction *) NULL) {
2010-08-08 10:06:34 +02:00
resource_report result[MAX_RAWMATERIALS];
int n, numresults = report_resources(sr, result, MAX_RAWMATERIALS, f);
2011-03-07 08:02:35 +01:00
for (n = 0; n < numresults; ++n) {
if (result[n].number >= 0 && result[n].level >= 0) {
bytes = snprintf(bufp, size, ", %d %s/%d", result[n].number,
2010-08-08 10:06:34 +02:00
LOC(f->locale, result[n].name), result[n].level);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
}
/* peasants & silver */
if (rpeasants(r)) {
int n = rpeasants(r);
bytes = snprintf(bufp, size, ", %d", n);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (r->land->ownership) {
2011-03-07 08:02:35 +01:00
const char *str =
locale_string(f->locale, mkname("morale", itoa10(r->land->morale)));
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, " %s", str);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (fval(r, RF_ORCIFIED)) {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)strlcpy(bufp, LOC(f->locale, n == 1 ? "rc_orc" : "rc_orc_p"),
size);
2010-08-08 10:06:34 +02:00
} else {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)strlcpy(bufp, LOC(f->locale, n == 1 ? "peasant" : "peasant_p"),
size);
}
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (is_mourning(r, turn + 1)) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_mourning"), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
if (rmoney(r) && sr->mode >= see_travel) {
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, ", %d ", rmoney(r));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)strlcpy(bufp, LOC(f->locale, resourcename(oldresourcetype[R_SILVER],
rmoney(r) != 1)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
/* Pferde */
if (rhorses(r)) {
bytes = snprintf(bufp, size, ", %d ", rhorses(r));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes =
(int)strlcpy(bufp, LOC(f->locale, resourcename(oldresourcetype[R_HORSE],
(rhorses(r) > 1) ? GR_PLURAL : 0)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (r->display && r->display[0]) {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, r->display, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
n = r->display[strlen(r->display) - 1];
if (n != '!' && n != '?' && n != '.') {
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
if (rule_region_owners()) {
2011-03-07 08:02:35 +01:00
const faction *owner = region_get_owner(r);
if (owner != NULL) {
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, " Die Region ist im Besitz von %s.",
2011-03-07 08:02:35 +01:00
factionname(owner));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
a = a_find(r->attribs, &at_overrideroads);
if (a) {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, (char *)a->data.v, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
} else {
int nrd = 0;
/* Nachbarregionen, die gesehen werden, ermitteln */
for (d = 0; d != MAXDIRECTIONS; d++) {
2011-03-07 08:02:35 +01:00
if (see[d] && rconnect(r, d))
nrd++;
2010-08-08 10:06:34 +02:00
}
/* list directions */
dh = false;
2011-03-07 08:02:35 +01:00
for (d = 0; d != MAXDIRECTIONS; d++)
if (see[d]) {
region *r2 = rconnect(r, d);
if (!r2)
continue;
nrd--;
if (dh) {
char regname[4096];
if (nrd == 0) {
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_final"), size);
} else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_next"), size);
}
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, directions[d]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
f_regionid(r2, f, regname, sizeof(regname));
bytes = snprintf(bufp, size, trailinto(r2, f->locale), regname);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
MSG(("nr_vicinitystart", "dir region", d, r2), bufp, size, f->locale,
f);
bufp += strlen(bufp);
dh = true;
2010-08-08 10:06:34 +02:00
}
}
/* Spezielle Richtungen */
2011-03-07 08:02:35 +01:00
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) {
spec_direction *d = (spec_direction *) (a->data.v);
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, d->desc), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (\"", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, d->keyword), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, "\")", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
dh = 1;
}
}
rnl(F);
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
2011-03-07 08:02:35 +01:00
if (sr->mode == see_unit && is_astral(r) &&
!is_cursed(r->attribs, C_ASTRALBLOCK, 0)) {
2010-08-08 10:06:34 +02:00
/* Sonderbehandlung Teleport-Ebene */
region_list *rl = astralregions(r, inhabitable);
region_list *rl2;
if (rl) {
bufp = buf;
size = sizeof(buf) - 1;
bytes = (int)strlcpy(bufp, "Schemen der Regionen ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
rl2 = rl;
while (rl2) {
bytes = (int)f_regionid(rl2->data, f, bufp, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
rl2 = rl2->next;
if (rl2) {
bytes = (int)strlcpy(bufp, ", ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
bytes = (int)strlcpy(bufp, " sind erkennbar.", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
free_regionlist(rl);
/* Schreibe Paragraphen */
rnl(F);
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
}
}
n = 0;
/* Wirkungen permanenter Spr<70>che */
2011-03-07 08:02:35 +01:00
nr_curses(F, f, r, TYP_REGION, 0);
2010-08-08 10:06:34 +02:00
/* Produktionsreduktion */
a = a_find(r->attribs, &at_reduceproduction);
if (a) {
2011-03-07 08:02:35 +01:00
const char *str = LOC(f->locale, "nr_reduced_production");
2010-08-08 10:06:34 +02:00
rparagraph(F, str, 0, 0, 0);
}
2011-03-07 08:02:35 +01:00
if (edges)
rnl(F);
for (e = edges; e; e = e->next) {
bool first = true;
2010-08-08 10:06:34 +02:00
bufp = buf;
size = sizeof(buf) - 1;
2011-03-07 08:02:35 +01:00
for (d = 0; d != MAXDIRECTIONS; ++d) {
if (!e->exist[d])
continue;
if (first)
bytes = (int)strlcpy(bufp, "Im ", size);
else if (e->lastd == d)
bytes = (int)strlcpy(bufp, " und im ", size);
else
bytes = (int)strlcpy(bufp, ", im ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, directions[d]), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
first = false;
}
2011-03-07 08:02:35 +01:00
if (!e->transparent)
bytes = (int)strlcpy(bufp, " versperrt ", size);
else
bytes = (int)strlcpy(bufp, " befindet sich ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, e->name, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (!e->transparent)
bytes = (int)strlcpy(bufp, " die Sicht.", size);
else
bytes = (int)strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
}
if (edges) {
while (edges) {
e = edges->next;
free(edges->name);
free(edges);
edges = e;
}
}
}
2011-03-07 08:02:35 +01:00
static void statistics(FILE * F, const region * r, const faction * f)
2010-08-08 10:06:34 +02:00
{
const unit *u;
int number = 0, p = rpeasants(r);
2011-03-07 08:02:35 +01:00
message *m;
2010-08-08 10:06:34 +02:00
item *itm, *items = NULL;
char buf[4096];
/* count */
for (u = r->units; u; u = u->next) {
if (u->faction == f && !fval(u->race, RCF_INVISIBLE)) {
2011-03-07 08:02:35 +01:00
for (itm = u->items; itm; itm = itm->next) {
2010-08-08 10:06:34 +02:00
i_change(&items, itm->type, itm->number);
}
number += u->number;
}
}
/* print */
rnl(F);
m = msg_message("nr_stat_header", "region", r);
nr_render(m, f->locale, buf, sizeof(buf), f);
msg_release(m);
rparagraph(F, buf, 0, 0, 0);
rnl(F);
/* Region */
2011-03-07 08:02:35 +01:00
if (skill_enabled[SK_ENTERTAINMENT] && fval(r->terrain, LAND_REGION)
&& rmoney(r)) {
2010-08-08 10:06:34 +02:00
m = msg_message("nr_stat_maxentertainment", "max", entertainmoney(r));
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
}
2011-03-07 08:02:35 +01:00
if (production(r) && (!fval(r->terrain, SEA_REGION)
|| f->race == new_race[RC_AQUARIAN])) {
if (markets_module()) { /* hack */
m =
msg_message("nr_stat_salary_new", "max", wage(r, NULL, NULL, turn + 1));
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
m = msg_message("nr_stat_salary", "max", wage(r, f, f->race, turn + 1));
2010-08-08 10:06:34 +02:00
}
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
}
if (p) {
m = msg_message("nr_stat_recruits", "max", p / RECRUITFRACTION);
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
if (!markets_module()) {
if (buildingtype_exists(r, bt_find("caravan"), true)) {
2011-03-07 08:02:35 +01:00
m = msg_message("nr_stat_luxuries", "max", (p * 2) / TRADE_FRACTION);
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
m = msg_message("nr_stat_luxuries", "max", p / TRADE_FRACTION);
2010-08-08 10:06:34 +02:00
}
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
}
if (r->land->ownership) {
m = msg_message("nr_stat_morale", "morale", r->land->morale);
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
}
}
/* info about units */
m = msg_message("nr_stat_people", "max", number);
nr_render(m, f->locale, buf, sizeof(buf), f);
rparagraph(F, buf, 2, 2, 0);
msg_release(m);
2011-03-07 08:02:35 +01:00
for (itm = items; itm; itm = itm->next) {
2010-08-08 10:06:34 +02:00
sprintf(buf, "%s: %d",
2011-03-07 08:02:35 +01:00
LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number);
2010-08-08 10:06:34 +02:00
rparagraph(F, buf, 2, 2, 0);
}
2011-03-07 08:02:35 +01:00
while (items)
i_free(i_remove(&items, items));
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void durchreisende(FILE * F, const region * r, const faction * f)
2010-08-08 10:06:34 +02:00
{
if (fval(r, RF_TRAVELUNIT)) {
attrib *abegin = a_find(r->attribs, &at_travelunit), *a;
int counter = 0, maxtravel = 0;
char buf[8192];
2011-03-07 08:02:35 +01:00
char *bufp = buf;
2010-08-08 10:06:34 +02:00
int bytes;
size_t size = sizeof(buf) - 1;
/* How many are we listing? For grammar. */
2011-03-07 08:02:35 +01:00
for (a = abegin; a && a->type == &at_travelunit; a = a->next) {
unit *u = (unit *) a->data.v;
2010-08-08 10:06:34 +02:00
if (r != u->region && (!u->ship || ship_owner(u->ship)==u)) {
2010-08-08 10:06:34 +02:00
if (cansee_durchgezogen(f, r, u, 0)) {
++maxtravel;
}
}
}
2011-03-07 08:02:35 +01:00
if (maxtravel == 0) {
2010-08-08 10:06:34 +02:00
return;
}
/* Auflisten. */
rnl(F);
2011-03-07 08:02:35 +01:00
for (a = abegin; a && a->type == &at_travelunit; a = a->next) {
unit *u = (unit *) a->data.v;
2010-08-08 10:06:34 +02:00
if (r != u->region && (!u->ship || ship_owner(u->ship)==u)) {
2010-08-08 10:06:34 +02:00
if (cansee_durchgezogen(f, r, u, 0)) {
++counter;
if (u->ship != NULL) {
if (counter == 1) {
bytes = (int)strlcpy(bufp, "Die ", size);
} else {
bytes = (int)strlcpy(bufp, "die ", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0) {
2010-08-08 10:06:34 +02:00
WARN_STATIC_BUFFER();
break;
}
bytes = (int)strlcpy(bufp, shipname(u->ship), size);
} else {
bytes = (int)strlcpy(bufp, unitname(u), size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0) {
2010-08-08 10:06:34 +02:00
WARN_STATIC_BUFFER();
break;
}
2011-03-07 08:02:35 +01:00
2010-08-08 10:06:34 +02:00
if (counter + 1 < maxtravel) {
bytes = (int)strlcpy(bufp, ", ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0) {
2010-08-08 10:06:34 +02:00
WARN_STATIC_BUFFER();
break;
}
} else if (counter + 1 == maxtravel) {
bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0) {
2010-08-08 10:06:34 +02:00
WARN_STATIC_BUFFER();
break;
}
}
}
}
}
/* TODO: finish localization */
if (maxtravel == 1) {
bytes = (int)strlcpy(bufp, " hat die Region durchquert.", size);
} else {
bytes = (int)strlcpy(bufp, " haben die Region durchquert.", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
}
}
2011-03-07 08:02:35 +01:00
static int buildingmaintenance(const building * b, const resource_type * rtype)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
const building_type *bt = b->type;
int c, cost = 0;
static bool init = false;
2011-03-07 08:02:35 +01:00
static const curse_type *nocost_ct;
if (!init) {
init = true;
nocost_ct = ct_find("nocostbuilding");
}
2010-08-08 10:06:34 +02:00
if (curse_active(get_curse(b->attribs, nocost_ct))) {
return 0;
}
2011-03-07 08:02:35 +01:00
for (c = 0; bt->maintenance && bt->maintenance[c].number; ++c) {
const maintenance *m = bt->maintenance + c;
if (m->rtype == rtype) {
2010-08-08 10:06:34 +02:00
if (fval(m, MTF_VARIABLE))
cost += (b->size * m->number);
else
cost += m->number;
}
}
return cost;
}
static int
2011-03-07 08:02:35 +01:00
report_template(const char *filename, report_context * ctx, const char *charset)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
faction *f = ctx->f;
2010-08-08 10:06:34 +02:00
region *r;
2011-03-07 08:02:35 +01:00
FILE *F = fopen(filename, "wt");
seen_region *sr = NULL;
char buf[8192], *bufp;
2010-08-08 10:06:34 +02:00
size_t size;
int bytes;
2011-03-07 08:02:35 +01:00
2010-08-08 10:06:34 +02:00
int enc = xmlParseCharEncoding(charset);
2011-03-07 08:02:35 +01:00
if (F == NULL) {
2010-08-08 10:06:34 +02:00
perror(filename);
return -1;
}
2011-03-07 08:02:35 +01:00
if (enc == XML_CHAR_ENCODING_UTF8) {
2011-03-08 07:31:06 +01:00
const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 };
2010-08-08 10:06:34 +02:00
fwrite(utf8_bom, 1, 3, F);
}
rps_nowrap(F, "");
rnl(F);
rps_nowrap(F, LOC(f->locale, "nr_template"));
rnl(F);
rps_nowrap(F, "");
rnl(F);
2011-03-07 08:02:35 +01:00
sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f),
LOC(f->locale, "enterpasswd"));
2010-08-08 10:06:34 +02:00
rps_nowrap(F, buf);
rnl(F);
rps_nowrap(F, "");
rnl(F);
2011-03-07 08:02:35 +01:00
sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost,
ECHECK_VERSION);
2010-08-08 10:06:34 +02:00
/* -v3.4: ECheck Version 3.4.x */
rps_nowrap(F, buf);
rnl(F);
2011-03-07 08:02:35 +01:00
for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) {
2010-08-08 10:06:34 +02:00
sr = find_seen(ctx->seen, r);
}
2011-03-07 08:02:35 +01:00
for (; sr != NULL; sr = sr->next) {
region *r = sr->r;
2010-08-08 10:06:34 +02:00
unit *u;
int dh = 0;
2011-03-07 08:02:35 +01:00
if (sr->mode < see_unit)
continue;
2010-08-08 10:06:34 +02:00
for (u = r->units; u; u = u->next) {
if (u->faction == f && !fval(u->race, RCF_INVISIBLE)) {
2011-03-07 08:02:35 +01:00
order *ord;
2010-08-08 10:06:34 +02:00
if (!dh) {
2011-03-07 08:02:35 +01:00
plane *pl = getplane(r);
2010-08-08 10:06:34 +02:00
int nx = r->x, ny = r->y;
pnormalize(&nx, &ny, pl);
adjust_coordinates(f, &nx, &ny, pl, r);
rps_nowrap(F, "");
rnl(F);
if (pl && pl->id != 0) {
2011-03-07 08:02:35 +01:00
sprintf(buf, "%s %d,%d,%d ; %s", LOC(f->locale,
parameters[P_REGION]), nx, ny, pl->id, rname(r, f->locale));
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
sprintf(buf, "%s %d,%d ; %s", LOC(f->locale, parameters[P_REGION]),
2010-08-08 10:06:34 +02:00
nx, ny, rname(r, f->locale));
}
rps_nowrap(F, buf);
rnl(F);
2011-03-07 08:02:35 +01:00
sprintf(buf, "; ECheck Lohn %d", wage(r, f, f->race, turn + 1));
2010-08-08 10:06:34 +02:00
rps_nowrap(F, buf);
rnl(F);
rps_nowrap(F, "");
rnl(F);
}
dh = 1;
bufp = buf;
size = sizeof(buf) - 1;
bytes = snprintf(bufp, size, "%s %s; %s [%d,%d$",
2011-03-07 08:02:35 +01:00
LOC(u->faction->locale, parameters[P_UNIT]),
unitid(u), u->name, u->number, get_money(u));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
if (u->building && building_owner(u->building)==u) {
2011-03-07 08:02:35 +01:00
building *b = u->building;
2010-08-08 10:06:34 +02:00
int cost = buildingmaintenance(b, r_silver);
if (cost > 0) {
bytes = (int)strlcpy(bufp, ",U", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, itoa10(cost), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
} else if (u->ship) {
if (ship_owner(u->ship)==u) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, ",S", size);
} else {
bytes = (int)strlcpy(bufp, ",s", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, shipid(u->ship), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (lifestyle(u) == 0) {
bytes = (int)strlcpy(bufp, ",I", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, "]", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
*bufp = 0;
rps_nowrap(F, buf);
rnl(F);
for (ord = u->old_orders; ord; ord = ord->next) {
/* this new order will replace the old defaults */
strcpy(buf, " ");
2011-03-07 08:02:35 +01:00
write_order(ord, buf + 2, sizeof(buf) - 2);
2010-08-08 10:06:34 +02:00
rps_nowrap(F, buf);
rnl(F);
}
for (ord = u->orders; ord; ord = ord->next) {
2011-03-07 08:02:35 +01:00
if (u->old_orders && is_repeated(ord))
continue; /* unit has defaults */
2010-08-08 10:06:34 +02:00
if (is_persistent(ord)) {
strcpy(buf, " ");
2011-03-07 08:02:35 +01:00
write_order(ord, buf + 2, sizeof(buf) - 2);
2010-08-08 10:06:34 +02:00
rps_nowrap(F, buf);
rnl(F);
}
}
/* If the lastorder begins with an @ it should have
2011-03-07 08:02:35 +01:00
* been printed in the loop before. */
2010-08-08 10:06:34 +02:00
}
}
}
rps_nowrap(F, "");
rnl(F);
strcpy(buf, LOC(f->locale, parameters[P_NEXT]));
rps_nowrap(F, buf);
rnl(F);
fclose(F);
return 0;
}
static void
2011-03-07 08:02:35 +01:00
show_allies(const faction * f, const ally * allies, char *buf, size_t size)
2010-08-08 10:06:34 +02:00
{
int allierte = 0;
2011-03-07 08:02:35 +01:00
int i = 0, h, hh = 0;
2010-08-08 10:06:34 +02:00
int bytes, dh = 0;
2011-03-07 08:02:35 +01:00
const ally *sf;
char *bufp = buf; /* buf already contains data */
--size; /* leave room for a null-terminator */
2010-08-08 10:06:34 +02:00
for (sf = allies; sf; sf = sf->next) {
int mode = alliedgroup(NULL, f, sf->faction, sf, HELP_ALL);
2011-03-07 08:02:35 +01:00
if (mode > 0)
++allierte;
2010-08-08 10:06:34 +02:00
}
for (sf = allies; sf; sf = sf->next) {
int mode = alliedgroup(NULL, f, sf->faction, sf, HELP_ALL);
2011-03-07 08:02:35 +01:00
if (mode <= 0)
continue;
2010-08-08 10:06:34 +02:00
i++;
if (dh) {
if (i == allierte) {
bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size);
} else {
bytes = (int)strlcpy(bufp, ", ", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
dh = 1;
hh = 0;
bytes = (int)strlcpy(bufp, factionname(sf->faction), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " (", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if ((mode & HELP_ALL) == HELP_ALL) {
bytes = (int)strlcpy(bufp, "Alles", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
} else {
for (h = 1; h < HELP_ALL; h *= 2) {
int p = MAXPARAMS;
if ((mode & h) == h) {
switch (h) {
2011-03-07 08:02:35 +01:00
case HELP_TRAVEL:
p = P_TRAVEL;
break;
case HELP_MONEY:
p = P_MONEY;
break;
case HELP_FIGHT:
p = P_FIGHT;
break;
case HELP_GIVE:
p = P_GIVE;
break;
case HELP_GUARD:
p = P_GUARD;
break;
case HELP_FSTEALTH:
p = P_FACTIONSTEALTH;
break;
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
if (p != MAXPARAMS) {
2010-08-08 10:06:34 +02:00
if (hh) {
bytes = (int)strlcpy(bufp, ", ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, parameters[p], size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
hh = 1;
}
}
}
bytes = (int)strlcpy(bufp, ")", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
*bufp = 0;
}
2011-03-07 08:02:35 +01:00
static void allies(FILE * F, const faction * f)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
const group *g = f->groups;
2010-08-08 10:06:34 +02:00
char buf[16384];
if (f->allies) {
int bytes;
size_t size = sizeof(buf);
if (!f->allies->next) {
bytes = (int)strlcpy(buf, "Wir helfen der Partei ", size);
} else {
bytes = (int)strlcpy(buf, "Wir helfen den Parteien ", size);
}
size -= bytes;
show_allies(f, f->allies, buf + bytes, size);
rparagraph(F, buf, 0, 0, 0);
rnl(F);
}
while (g) {
if (g->allies) {
int bytes;
size_t size = sizeof(buf);
if (!g->allies->next) {
bytes = snprintf(buf, size, "%s hilft der Partei ", g->name);
} else {
bytes = snprintf(buf, size, "%s hilft den Parteien ", g->name);
}
size -= bytes;
show_allies(f, g->allies, buf + bytes, size);
rparagraph(F, buf, 0, 0, 0);
rnl(F);
}
g = g->next;
}
}
2011-03-07 08:02:35 +01:00
static void guards(FILE * F, const region * r, const faction * see)
2010-08-08 10:06:34 +02:00
{
/* die Partei see sieht dies; wegen
* "unbekannte Partei", wenn man es selbst ist... */
2011-03-07 08:02:35 +01:00
faction *guardians[512];
2010-08-08 10:06:34 +02:00
int nextguard = 0;
unit *u;
int i;
bool tarned = false;
2010-08-08 10:06:34 +02:00
/* Bewachung */
for (u = r->units; u; u = u->next) {
2011-03-07 08:02:35 +01:00
if (is_guard(u, GUARD_ALL) != 0) {
faction *f = u->faction;
2010-08-08 10:06:34 +02:00
faction *fv = visible_faction(see, u);
2011-03-07 08:02:35 +01:00
if (fv != f && see != fv) {
2010-08-08 10:06:34 +02:00
f = fv;
}
if (f != see && fval(u, UFL_ANON_FACTION)) {
2011-03-07 08:02:35 +01:00
tarned = true;
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
for (i = 0; i != nextguard; ++i)
if (guardians[i] == f)
break;
if (i == nextguard) {
2010-08-08 10:06:34 +02:00
guardians[nextguard++] = f;
}
}
}
}
if (nextguard || tarned) {
char buf[8192];
2011-03-07 08:02:35 +01:00
char *bufp = buf;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buf) - 1;
int bytes;
2011-03-07 08:02:35 +01:00
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, "Die Region wird von ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
for (i = 0; i != nextguard + (tarned ? 1 : 0); ++i) {
if (i != 0) {
if (i == nextguard - (tarned ? 0 : 1)) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(see->locale, "list_and"), size);
} else {
bytes = (int)strlcpy(bufp, ", ", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (i < nextguard) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, factionname(guardians[i]), size);
} else {
bytes = (int)strlcpy(bufp, "unbekannten Einheiten", size);
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
bytes = (int)strlcpy(bufp, " bewacht.", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
rnl(F);
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
}
}
2011-03-07 08:02:35 +01:00
static void rpline(FILE * F)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
static char line[REPORTWIDTH + 1];
if (line[0] != '-') {
2010-08-08 10:06:34 +02:00
memset(line, '-', sizeof(line));
line[REPORTWIDTH] = '\n';
}
fwrite(line, sizeof(char), sizeof(line), F);
}
2011-03-07 08:02:35 +01:00
static void list_address(FILE * F, const faction * uf, quicklist * seenfactions)
2010-08-08 10:06:34 +02:00
{
int qi = 0;
2011-03-07 08:02:35 +01:00
quicklist *flist = seenfactions;
2010-08-08 10:06:34 +02:00
centre(F, LOC(uf->locale, "nr_addresses"), false);
rnl(F);
2011-03-07 08:02:35 +01:00
while (flist != NULL) {
const faction *f = (const faction *)ql_get(flist, qi);
2010-08-08 10:06:34 +02:00
if (!is_monsters(f)) {
char buf[8192];
char label = '-';
2011-03-07 08:02:35 +01:00
sprintf(buf, "%s: %s; %s", factionname(f), f->email,
f->banner ? f->banner : "");
if (uf == f)
label = '*';
else if (ALLIED(uf, f))
label = 'o';
else if (alliedfaction(NULL, uf, f, HELP_ALL))
label = '+';
2010-08-08 10:06:34 +02:00
rparagraph(F, buf, 4, 0, label);
}
ql_advance(&flist, &qi, 1);
2010-08-08 10:06:34 +02:00
}
rnl(F);
rpline(F);
}
static void
2011-03-07 08:02:35 +01:00
nr_ship(FILE * F, const seen_region * sr, const ship * sh, const faction * f,
const unit * captain)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
const region *r = sr->r;
char buffer[8192], *bufp = buffer;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buffer) - 1;
int bytes;
char ch;
rnl(F);
if (captain && captain->faction == f) {
int n = 0, p = 0;
getshipweight(sh, &n, &p);
2011-03-07 08:02:35 +01:00
n = (n + 99) / 100; /* 1 Silber = 1 GE */
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, "%s, %s, (%d/%d)", shipname(sh),
LOC(f->locale, sh->type->name[0]), n, shipcapacity(sh) / 100);
} else {
2011-03-07 08:02:35 +01:00
bytes =
snprintf(bufp, size, "%s, %s", shipname(sh), LOC(f->locale,
sh->type->name[0]));
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */
if (sh->size != sh->type->construction->maxsize) {
2010-08-08 10:06:34 +02:00
bytes = snprintf(bufp, size, ", %s (%d/%d)",
LOC(f->locale, "nr_undercons"), sh->size,
sh->type->construction->maxsize);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (sh->damage) {
2011-03-07 08:02:35 +01:00
int percent =
(sh->damage * 100 + DAMAGE_SCALE - 1) / (sh->size * DAMAGE_SCALE);
bytes =
snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
if (!fval(r->terrain, SEA_REGION)) {
if (sh->coast != NODIRECTION) {
bytes = (int)strlcpy(bufp, ", ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, coasts[sh->coast]), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
ch = 0;
if (sh->display && sh->display[0]) {
bytes = (int)strlcpy(bufp, "; ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, sh->display, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
ch = sh->display[strlen(sh->display) - 1];
}
if (ch != '!' && ch != '?' && ch != '.') {
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
*bufp = 0;
rparagraph(F, buffer, 2, 0, 0);
nr_curses(F, f, sh, TYP_SHIP, 4);
}
static void
2011-03-07 08:02:35 +01:00
nr_building(FILE * F, const seen_region * sr, const building * b,
const faction * f)
2010-08-08 10:06:34 +02:00
{
int i, bytes;
2011-03-07 08:02:35 +01:00
const char *name, *bname, *billusion = NULL;
const struct locale *lang = NULL;
char buffer[8192], *bufp = buffer;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buffer) - 1;
rnl(F);
2011-03-07 08:02:35 +01:00
if (f)
lang = f->locale;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
bytes =
snprintf(bufp, size, "%s, %s %d, ", buildingname(b), LOC(f->locale,
"nr_size"), b->size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
report_building(b, &bname, &billusion);
2011-03-07 08:02:35 +01:00
name = LOC(lang, billusion ? billusion : bname);
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, name, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (billusion) {
2011-03-07 08:02:35 +01:00
unit *owner = building_owner(b);
if (owner && owner->faction == f) {
2010-08-08 10:06:34 +02:00
/* illusion. report real type */
name = LOC(lang, bname);
bytes = snprintf(bufp, size, " (%s)", name);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
if (b->size < b->type->maxsize) {
bytes = (int)strlcpy(bufp, " (im Bau)", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (b->besieged > 0 && sr->mode >= see_lighthouse) {
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, ", belagert von ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, itoa10(b->besieged), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, " Personen ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (b->besieged >= b->size * SIEGEFACTOR) {
bytes = (int)strlcpy(bufp, "(abgeschnitten)", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
i = 0;
if (b->display && b->display[0]) {
bytes = (int)strlcpy(bufp, "; ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, b->display, size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
i = b->display[strlen(b->display) - 1];
}
#ifdef WDW_PYRAMID
if (i != '!' && i != '?' && i != '.') {
scat(", ");
}
if (b->type == bt_find("pyramid")) {
2011-03-07 08:02:35 +01:00
unit *owner = building_owner(b);
2010-08-08 10:06:34 +02:00
scat("Gr<EFBFBD><EFBFBD>enstufe ");
icat(wdw_pyramid_level(b));
scat(".");
2011-03-07 08:02:35 +01:00
if (owner && owner->faction == f) {
2010-08-08 10:06:34 +02:00
const construction *ctype = b->type->construction;
int completed = b->size;
int c;
scat(" Baukosten pro Gr<47><72>enpunkt: ");
2011-03-07 08:02:35 +01:00
while (ctype->improvement != NULL &&
ctype->improvement != ctype &&
ctype->maxsize > 0 && ctype->maxsize <= completed) {
2010-08-08 10:06:34 +02:00
completed -= ctype->maxsize;
ctype = ctype->improvement;
}
assert(ctype->materials != NULL);
2011-03-07 08:02:35 +01:00
for (c = 0; ctype->materials[c].number; c++) {
const resource_type *rtype = ctype->materials[c].rtype;
2010-08-08 10:06:34 +02:00
int number = ctype->materials[c].number;
2011-03-07 08:02:35 +01:00
if (c > 0) {
2010-08-08 10:06:34 +02:00
scat(", ");
}
icat(number);
scat(" ");
2011-03-07 08:02:35 +01:00
scat(locale_string(lang, resourcename(rtype,
number != 1 ? GR_PLURAL : 0)));
2010-08-08 10:06:34 +02:00
}
scat(".");
scat(" Erforderlicher Talentwert: ");
icat(b->type->construction->minskill);
scat(".");
}
}
#else
if (i != '!' && i != '?' && i != '.') {
bytes = (int)strlcpy(bufp, ".", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
#endif
*bufp = 0;
rparagraph(F, buffer, 2, 0, 0);
2011-03-07 08:02:35 +01:00
if (sr->mode < see_lighthouse)
return;
2010-08-08 10:06:34 +02:00
nr_curses(F, f, b, TYP_BUILDING, 4);
}
2011-03-07 08:02:35 +01:00
static void nr_paragraph(FILE * F, message * m, faction * f)
2010-08-08 10:06:34 +02:00
{
int bytes;
2011-03-07 08:02:35 +01:00
char buf[4096], *bufp = buf;
2010-08-08 10:06:34 +02:00
size_t size = sizeof(buf) - 1;
bytes = (int)nr_render(m, f->locale, bufp, size, f);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
msg_release(m);
rparagraph(F, buf, 0, 0, 0);
}
int
2011-03-07 08:02:35 +01:00
report_plaintext(const char *filename, report_context * ctx,
const char *charset)
2010-08-08 10:06:34 +02:00
{
int flag = 0;
char ch;
int anyunits, no_units, no_people;
const struct region *r;
2011-03-07 08:02:35 +01:00
faction *f = ctx->f;
2010-08-08 10:06:34 +02:00
unit *u;
char pzTime[64];
attrib *a;
2011-03-07 08:02:35 +01:00
message *m;
2010-08-08 10:06:34 +02:00
unsigned char op;
int bytes, ix = want(O_STATISTICS);
int wants_stats = (f->options & ix);
2011-03-07 08:02:35 +01:00
FILE *F = fopen(filename, "wt");
seen_region *sr = NULL;
2010-08-08 10:06:34 +02:00
char buf[8192];
2011-03-07 08:02:35 +01:00
char *bufp;
2010-08-08 10:06:34 +02:00
int enc = xmlParseCharEncoding(charset);
size_t size;
/* static variables can cope with writing for different turns */
static int thisseason = -1;
static int nextseason = -1;
static int gamecookie = -1;
2011-03-07 08:02:35 +01:00
if (gamecookie != global.cookie) {
2010-08-08 10:06:34 +02:00
gamedate date;
2011-03-07 08:02:35 +01:00
get_gamedate(turn + 1, &date);
2010-08-08 10:06:34 +02:00
thisseason = date.season;
2011-03-07 08:02:35 +01:00
get_gamedate(turn + 2, &date);
2010-08-08 10:06:34 +02:00
nextseason = date.season;
gamecookie = global.cookie;
}
2011-03-07 08:02:35 +01:00
if (F == NULL) {
2010-08-08 10:06:34 +02:00
perror(filename);
return -1;
}
2011-03-07 08:02:35 +01:00
if (enc == XML_CHAR_ENCODING_UTF8) {
2011-03-08 07:31:06 +01:00
const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 };
2010-08-08 10:06:34 +02:00
fwrite(utf8_bom, 1, 3, F);
}
strftime(pzTime, 64, "%A, %d. %B %Y, %H:%M", localtime(&ctx->report_time));
m = msg_message("nr_header_date", "game date", global.gamename, pzTime);
nr_render(m, f->locale, buf, sizeof(buf), f);
msg_release(m);
centre(F, buf, true);
centre(F, gamedate_season(f->locale), true);
rnl(F);
sprintf(buf, "%s, %s/%s (%s)", factionname(f),
2011-03-07 08:02:35 +01:00
LOC(f->locale, rc_name(f->race, 1)),
LOC(f->locale, mkname("school", magic_school[f->magiegebiet])), f->email);
2010-08-08 10:06:34 +02:00
centre(F, buf, true);
if (f_get_alliance(f)) {
centre(F, alliancename(f->alliance), true);
}
if (f->age <= 2) {
2011-03-07 08:02:35 +01:00
const char *s;
2010-08-08 10:06:34 +02:00
if (f->age <= 1) {
2011-03-07 08:02:35 +01:00
ADDMSG(&f->msgs, msg_message("changepasswd", "value", f->passw));
2010-08-08 10:06:34 +02:00
}
RENDER(f, buf, sizeof(buf), ("newbie_password", "password", f->passw));
rnl(F);
centre(F, buf, true);
s = locale_getstring(f->locale, "newbie_info_1");
if (s) {
rnl(F);
centre(F, s, true);
}
s = locale_getstring(f->locale, "newbie_info_2");
if (s) {
rnl(F);
centre(F, s, true);
}
if ((f->options & want(O_COMPUTER)) == 0) {
f->options |= want(O_COMPUTER);
s = locale_getstring(f->locale, "newbie_info_3");
if (s) {
rnl(F);
centre(F, s, true);
}
}
}
rnl(F);
#if SCORE_MODULE
if (f->options & want(O_SCORE) && f->age > DISPLAYSCORE) {
2011-03-07 08:02:35 +01:00
RENDER(f, buf, sizeof(buf), ("nr_score", "score average", f->score,
average_score_of_age(f->age, f->age / 24 + 1)));
2010-08-08 10:06:34 +02:00
centre(F, buf, true);
}
#endif
#ifdef COUNT_AGAIN
no_units = 0;
no_people = 0;
2011-03-07 08:02:35 +01:00
for (u = f->units; u; u = u->nextF) {
2010-08-08 10:06:34 +02:00
if (playerrace(u->race)) {
++no_people;
no_units += u->number;
2011-03-07 08:02:35 +01:00
assert(f == u->faction);
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
if (no_units != f->no_units) {
2010-08-08 10:06:34 +02:00
f->no_units = no_units;
}
2011-03-07 08:02:35 +01:00
if (no_people != f->num_people) {
2010-08-08 10:06:34 +02:00
f->num_people = no_people;
}
#else
no_units = f->no_units;
no_people = f->num_people;
#endif
m = msg_message("nr_population", "population units", no_people, no_units);
nr_render(m, f->locale, buf, sizeof(buf), f);
msg_release(m);
centre(F, buf, true);
if (f->race == new_race[RC_HUMAN]) {
int maxmig = count_maxmigrants(f);
2011-03-07 08:02:35 +01:00
if (maxmig > 0) {
m =
msg_message("nr_migrants", "units maxunits", count_migrants(f), maxmig);
2010-08-08 10:06:34 +02:00
nr_render(m, f->locale, buf, sizeof(buf), f);
msg_release(m);
centre(F, buf, true);
}
}
if (f_get_alliance(f)) {
2011-03-07 08:02:35 +01:00
m =
msg_message("nr_alliance", "leader name id age",
alliance_get_leader(f->alliance), f->alliance->name, f->alliance->id,
turn - f->alliance_joindate);
2010-08-08 10:06:34 +02:00
nr_render(m, f->locale, buf, sizeof(buf), f);
msg_release(m);
centre(F, buf, true);
}
{
int maxh = maxheroes(f);
if (maxh) {
2011-03-07 08:02:35 +01:00
message *msg =
msg_message("nr_heroes", "units maxunits", countheroes(f), maxh);
2010-08-08 10:06:34 +02:00
nr_render(msg, f->locale, buf, sizeof(buf), f);
msg_release(msg);
centre(F, buf, true);
}
}
2011-03-07 08:02:35 +01:00
if (f->items != NULL) {
message *msg = msg_message("nr_claims", "items", f->items);
2010-08-08 10:06:34 +02:00
nr_render(msg, f->locale, buf, sizeof(buf), f);
msg_release(msg);
rnl(F);
centre(F, buf, true);
}
/* Insekten-Winter-Warnung */
if (f->race == new_race[RC_INSECT]) {
if (thisseason == 0) {
centre(F, LOC(f->locale, "nr_insectwinter"), true);
rnl(F);
} else {
if (nextseason == 0) {
centre(F, LOC(f->locale, "nr_insectfall"), true);
rnl(F);
}
}
}
bufp = buf;
size = sizeof(buf) - 1;
2011-03-07 08:02:35 +01:00
bytes = snprintf(buf, size, "%s:", LOC(f->locale, "nr_options"));
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
for (op = 0; op != MAXOPTIONS; op++) {
if (f->options & want(op) && options[op]) {
bytes = (int)strlcpy(bufp, " ", size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
bytes = (int)strlcpy(bufp, LOC(f->locale, options[op]), size);
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
flag++;
}
}
if (flag > 0) {
rnl(F);
*bufp = 0;
centre(F, buf, true);
}
rp_messages(F, f->msgs, f, 0, true);
rp_battles(F, f);
a = a_find(f->attribs, &at_reportspell);
if (a) {
rnl(F);
centre(F, LOC(f->locale, "section_newspells"), true);
2011-03-07 08:02:35 +01:00
while (a && a->type == &at_reportspell) {
spellbook_entry *sbe = (spellbook_entry *) a->data.v;
nr_spell(F, sbe, f->locale);
2010-08-08 10:06:34 +02:00
a = a->next;
}
}
ch = 0;
2011-03-07 08:02:35 +01:00
for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;
a = a->next) {
const potion_type *ptype =
resource2potion(((const item_type *)a->data.v)->rtype);
const char *description = NULL;
if (ptype != NULL) {
const char *pname = resourcename(ptype->itype->rtype, 0);
if (ch == 0) {
2010-08-08 10:06:34 +02:00
rnl(F);
centre(F, LOC(f->locale, "section_newpotions"), true);
ch = 1;
}
rnl(F);
centre(F, LOC(f->locale, pname), true);
2011-03-07 08:02:35 +01:00
snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"),
ptype->level);
2010-08-08 10:06:34 +02:00
centre(F, buf, true);
rnl(F);
2011-03-07 08:02:35 +01:00
2010-08-08 10:06:34 +02:00
bufp = buf;
size = sizeof(buf) - 1;
bytes = snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_herbsrequired"));
2011-03-07 08:02:35 +01:00
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
if (ptype->itype->construction) {
2011-03-07 08:02:35 +01:00
requirement *m = ptype->itype->construction->materials;
2010-08-08 10:06:34 +02:00
while (m->number) {
2011-03-07 08:02:35 +01:00
bytes =
(int)strlcpy(bufp, LOC(f->locale, resourcename(m->rtype, 0)), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
++m;
if (m->number)
2011-03-07 08:02:35 +01:00
bytes = (int)strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
2010-08-08 10:06:34 +02:00
}
}
*bufp = 0;
centre(F, buf, true);
rnl(F);
2011-03-07 08:02:35 +01:00
if (description == NULL) {
const char *potiontext = mkname("potion", pname);
2010-08-08 10:06:34 +02:00
description = LOC(f->locale, potiontext);
}
centre(F, description, true);
}
}
rnl(F);
centre(F, LOC(f->locale, "nr_alliances"), false);
rnl(F);
allies(F, f);
rpline(F);
anyunits = 0;
2011-03-07 08:02:35 +01:00
for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) {
2010-08-08 10:06:34 +02:00
sr = find_seen(ctx->seen, r);
}
2011-03-07 08:02:35 +01:00
for (; sr != NULL; sr = sr->next) {
region *r = sr->r;
2010-08-08 10:06:34 +02:00
int stealthmod = stealth_modifier(sr->mode);
2011-03-07 08:02:35 +01:00
building *b = r->buildings;
ship *sh = r->ships;
if (sr->mode < see_lighthouse)
continue;
2010-08-08 10:06:34 +02:00
/* Beschreibung */
2011-03-07 08:02:35 +01:00
if (sr->mode == see_unit) {
2010-08-08 10:06:34 +02:00
anyunits = 1;
describe(F, sr, f);
if (markets_module() && r->land) {
2011-03-07 08:02:35 +01:00
const item_type *lux = r_luxury(r);
const item_type *herb = r->land->herbtype;
message *m = 0;
2010-08-08 10:06:34 +02:00
if (herb && lux) {
m = msg_message("nr_market_info_p", "p1 p2",
2011-03-07 08:02:35 +01:00
lux ? lux->rtype : 0, herb ? herb->rtype : 0);
2010-08-08 10:06:34 +02:00
} else if (lux || herb) {
m = msg_message("nr_market_info_s", "p1",
2011-03-07 08:02:35 +01:00
lux ? lux->rtype : herb->rtype);
2010-08-08 10:06:34 +02:00
}
if (m) {
rnl(F);
nr_paragraph(F, m, f);
}
2011-03-07 17:26:50 +01:00
/* */
2010-08-08 10:06:34 +02:00
} else {
2011-03-07 08:02:35 +01:00
if (!fval(r->terrain, SEA_REGION) && rpeasants(r) / TRADE_FRACTION > 0) {
2010-08-08 10:06:34 +02:00
rnl(F);
prices(F, r, f);
}
}
guards(F, r, f);
durchreisende(F, r, f);
2011-03-07 08:02:35 +01:00
} else {
if (sr->mode == see_far) {
2010-08-08 10:06:34 +02:00
describe(F, sr, f);
guards(F, r, f);
durchreisende(F, r, f);
2011-03-07 08:02:35 +01:00
} else if (sr->mode == see_lighthouse) {
2010-08-08 10:06:34 +02:00
describe(F, sr, f);
durchreisende(F, r, f);
} else {
describe(F, sr, f);
durchreisende(F, r, f);
}
}
/* Statistik */
2011-03-07 08:02:35 +01:00
if (wants_stats && sr->mode == see_unit)
statistics(F, r, f);
2010-08-08 10:06:34 +02:00
/* Nachrichten an REGION in der Region */
2011-03-07 08:02:35 +01:00
if (sr->mode == see_unit || sr->mode == see_travel) {
message_list *mlist = r_getmessages(r, f);
2010-08-08 10:06:34 +02:00
rp_messages(F, r->msgs, f, 0, true);
2011-03-07 08:02:35 +01:00
if (mlist)
rp_messages(F, mlist, f, 0, true);
2010-08-08 10:06:34 +02:00
}
/* report all units. they are pre-sorted in an efficient manner */
u = r->units;
while (b) {
2011-03-07 08:02:35 +01:00
while (b && (!u || u->building != b)) {
2010-08-08 10:06:34 +02:00
nr_building(F, sr, b, f);
b = b->next;
}
if (b) {
nr_building(F, sr, b, f);
2011-03-07 08:02:35 +01:00
while (u && u->building == b) {
2010-08-08 10:06:34 +02:00
nr_unit(F, f, u, 6, sr->mode);
u = u->next;
}
b = b->next;
}
}
while (u && !u->ship) {
2011-03-07 08:02:35 +01:00
if (stealthmod > INT_MIN) {
2010-08-08 10:06:34 +02:00
if (u->faction == f || cansee(f, r, u, stealthmod)) {
nr_unit(F, f, u, 4, sr->mode);
}
}
assert(!u->building);
u = u->next;
}
while (sh) {
2011-03-07 08:02:35 +01:00
while (sh && (!u || u->ship != sh)) {
2010-08-08 10:06:34 +02:00
nr_ship(F, sr, sh, f, NULL);
sh = sh->next;
}
if (sh) {
nr_ship(F, sr, sh, f, u);
2011-03-07 08:02:35 +01:00
while (u && u->ship == sh) {
2010-08-08 10:06:34 +02:00
nr_unit(F, f, u, 6, sr->mode);
u = u->next;
}
sh = sh->next;
}
}
assert(!u);
rnl(F);
rpline(F);
}
if (!is_monsters(f)) {
if (!anyunits) {
rnl(F);
rparagraph(F, LOC(f->locale, "nr_youaredead"), 0, 2, 0);
} else {
list_address(F, f, ctx->addresses);
}
}
fclose(F);
return 0;
}
2011-03-07 08:02:35 +01:00
void base36conversion(void)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
region *r;
for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) {
2010-08-08 10:06:34 +02:00
if (forbiddenid(u->no)) {
uunhash(u);
u->no = newunitid();
uhash(u);
}
}
}
}
#define FMAXHASH 1021
struct fsee {
2011-03-07 08:02:35 +01:00
struct fsee *nexthash;
faction *f;
2010-08-08 10:06:34 +02:00
struct see {
2011-03-07 08:02:35 +01:00
struct see *next;
faction *seen;
unit *proof;
} *see;
} *fsee[FMAXHASH];
2010-08-08 10:06:34 +02:00
#define REPORT_NR (1 << O_REPORT)
#define REPORT_CR (1 << O_COMPUTER)
#define REPORT_ZV (1 << O_ZUGVORLAGE)
#define REPORT_ZIP (1 << O_COMPRESS)
#define REPORT_BZIP2 (1 << O_BZIP2)
2011-03-07 08:02:35 +01:00
unit *can_find(faction * f, faction * f2)
2010-08-08 10:06:34 +02:00
{
int key = f->no % FMAXHASH;
2011-03-07 08:02:35 +01:00
struct fsee *fs = fsee[key];
struct see *ss;
if (f == f2)
return f->units;
while (fs && fs->f != f)
fs = fs->nexthash;
if (!fs)
return NULL;
ss = fs->see;
while (ss && ss->seen != f2)
ss = ss->next;
2010-08-08 10:06:34 +02:00
if (ss) {
/* bei TARNE PARTEI yxz muss die Partei von unit proof nicht
* wirklich Partei f2 sein! */
/* assert(ss->proof->faction==f2); */
return ss->proof;
}
return NULL;
}
2011-03-07 08:02:35 +01:00
static void add_find(faction * f, unit * u, faction * f2)
2010-08-08 10:06:34 +02:00
{
/* faction f sees f2 through u */
int key = f->no % FMAXHASH;
2011-03-07 08:02:35 +01:00
struct fsee **fp = &fsee[key];
struct fsee *fs;
struct see **sp;
struct see *ss;
while (*fp && (*fp)->f != f)
fp = &(*fp)->nexthash;
2010-08-08 10:06:34 +02:00
if (!*fp) {
fs = *fp = calloc(sizeof(struct fsee), 1);
fs->f = f;
2011-03-07 08:02:35 +01:00
} else
fs = *fp;
2010-08-08 10:06:34 +02:00
sp = &fs->see;
2011-03-07 08:02:35 +01:00
while (*sp && (*sp)->seen != f2)
sp = &(*sp)->next;
2010-08-08 10:06:34 +02:00
if (!*sp) {
ss = *sp = calloc(sizeof(struct see), 1);
ss->proof = u;
ss->seen = f2;
2011-03-07 08:02:35 +01:00
} else
ss = *sp;
2010-08-08 10:06:34 +02:00
ss->proof = u;
}
2011-03-07 08:02:35 +01:00
static void update_find(void)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
region *r;
static bool initial = true;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
if (initial)
for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) {
faction *lastf = u->faction;
unit *u2;
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction == lastf || u2->faction == u->faction)
continue;
if (seefaction(u->faction, r, u2, 0)) {
faction *fv = visible_faction(u->faction, u2);
lastf = fv;
add_find(u->faction, u2, fv);
}
2010-08-08 10:06:34 +02:00
}
}
}
initial = false;
}
bool kann_finden(faction * f1, faction * f2)
2010-08-08 10:06:34 +02:00
{
update_find();
return (bool) (can_find(f1, f2) != NULL);
2010-08-08 10:06:34 +02:00
}
/******* end summary ******/
2011-03-07 08:02:35 +01:00
void register_nr(void)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
if (!nocr)
register_reporttype("nr", &report_plaintext, 1 << O_REPORT);
if (!nonr)
register_reporttype("txt", &report_template, 1 << O_ZUGVORLAGE);
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
void report_cleanup(void)
2010-08-08 10:06:34 +02:00
{
int i;
2011-03-07 08:02:35 +01:00
for (i = 0; i != FMAXHASH; ++i) {
2010-08-08 10:06:34 +02:00
while (fsee[i]) {
2011-03-07 08:02:35 +01:00
struct fsee *fs = fsee[i]->nexthash;
2010-08-08 10:06:34 +02:00
free(fsee[i]);
fsee[i] = fs;
}
}
}