2016-11-01 17:25:52 +01:00
|
|
|
/*
|
2015-01-30 22:10:29 +01:00
|
|
|
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
2014-08-17 00:14:50 +02:00
|
|
|
Katja Zedel <katze@felidae.kn-bremen.de
|
|
|
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
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.
|
|
|
|
**/
|
|
|
|
|
2017-12-29 06:13:28 +01:00
|
|
|
#ifdef _MSC_VER
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <platform.h>
|
2017-12-29 06:13:28 +01:00
|
|
|
#endif
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
#include "report.h"
|
2014-08-27 06:40:18 +02:00
|
|
|
#include "reports.h"
|
2016-11-01 22:11:10 +01:00
|
|
|
#include "guard.h"
|
2014-11-01 12:09:56 +01:00
|
|
|
#include "laws.h"
|
2016-11-16 22:30:59 +01:00
|
|
|
#include "market.h"
|
2016-12-23 18:05:38 +01:00
|
|
|
#include "monsters.h"
|
2016-11-16 22:30:59 +01:00
|
|
|
#include "travelthru.h"
|
2014-11-11 16:53:56 +01:00
|
|
|
|
2017-08-21 20:48:00 +02:00
|
|
|
#include <spells/regioncurse.h>
|
|
|
|
#include <spells/buildingcurse.h>
|
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
/* modules includes */
|
|
|
|
#include <modules/score.h>
|
|
|
|
|
|
|
|
/* attributes includes */
|
|
|
|
#include <attributes/overrideroads.h>
|
|
|
|
#include <attributes/otherfaction.h>
|
|
|
|
#include <attributes/reduceproduction.h>
|
2018-02-08 18:33:58 +01:00
|
|
|
#include <attributes/seenspell.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* gamecode includes */
|
2014-08-31 08:58:55 +02:00
|
|
|
#include "alchemy.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
#include "economy.h"
|
2014-08-27 06:40:18 +02:00
|
|
|
#include "move.h"
|
2014-08-31 08:58:55 +02:00
|
|
|
#include "upkeep.h"
|
2014-08-27 21:09:39 +02:00
|
|
|
#include "vortex.h"
|
2016-01-28 12:25:16 +01:00
|
|
|
#include "teleport.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* kernel includes */
|
2018-09-29 19:32:39 +02:00
|
|
|
#include "kernel/alliance.h"
|
2018-02-14 20:00:48 +01:00
|
|
|
#include "kernel/ally.h"
|
2018-09-29 19:32:39 +02:00
|
|
|
#include "kernel/attrib.h"
|
2018-02-14 20:00:48 +01:00
|
|
|
#include "kernel/calendar.h"
|
2018-09-29 19:32:39 +02:00
|
|
|
#include "kernel/config.h"
|
2018-02-14 20:00:48 +01:00
|
|
|
#include "kernel/connection.h"
|
|
|
|
#include "kernel/build.h"
|
|
|
|
#include "kernel/building.h"
|
|
|
|
#include "kernel/curse.h"
|
|
|
|
#include "kernel/faction.h"
|
|
|
|
#include "kernel/group.h"
|
|
|
|
#include "kernel/item.h"
|
|
|
|
#include "kernel/messages.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/resources.h"
|
|
|
|
#include "kernel/ship.h"
|
|
|
|
#include "kernel/spell.h"
|
|
|
|
#include "kernel/spellbook.h"
|
|
|
|
#include "kernel/terrain.h"
|
|
|
|
#include "kernel/terrainid.h"
|
|
|
|
#include "kernel/unit.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
#include <util/base36.h>
|
2018-06-09 21:22:02 +02:00
|
|
|
#include "util/bsdstring.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/goodies.h>
|
|
|
|
#include <util/language.h>
|
|
|
|
#include <util/lists.h>
|
|
|
|
#include <util/log.h>
|
|
|
|
#include <util/message.h>
|
|
|
|
#include <util/nrmessage.h>
|
2018-09-29 19:32:39 +02:00
|
|
|
#include "util/param.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/rng.h>
|
2017-12-28 18:29:40 +01:00
|
|
|
#include <util/strings.h>
|
|
|
|
|
|
|
|
#include <selist.h>
|
2015-05-13 04:25:50 +02:00
|
|
|
#include <filestream.h>
|
2016-11-13 19:40:38 +01:00
|
|
|
#include <stream.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2017-12-29 06:13:28 +01:00
|
|
|
#define ECHECK_VERSION "4.01"
|
2015-09-26 14:01:01 +02:00
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
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
|
|
|
{
|
2017-02-18 21:15:14 +01:00
|
|
|
static char buf[256]; /* FIXME: static return value */
|
2014-08-17 00:14:50 +02:00
|
|
|
gamedate gd;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2017-05-07 17:46:51 +02:00
|
|
|
assert(weeknames);
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
get_gamedate(turn, &gd);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
sprintf(buf, (const char *)LOC(lang, "nr_calendar_season"),
|
2017-05-07 17:46:51 +02:00
|
|
|
LOC(lang, mkname("calendar", weeknames[gd.week])),
|
|
|
|
LOC(lang, mkname("calendar", calendar_month(gd.month))),
|
2014-08-17 00:14:50 +02:00
|
|
|
gd.year,
|
2017-05-07 17:46:51 +02:00
|
|
|
LOC(lang, mkname("calendar", calendar_era())), LOC(lang, mkname("calendar", seasonnames[gd.season])));
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
return buf;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
void newline(struct stream *out) {
|
2015-05-13 04:25:50 +02:00
|
|
|
sputs("", out);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
void write_spaces(struct stream *out, size_t num) {
|
2015-05-19 08:26:44 +02:00
|
|
|
static const char spaces[REPORTWIDTH] = " ";
|
|
|
|
while (num > 0) {
|
|
|
|
size_t bytes = (num > REPORTWIDTH) ? REPORTWIDTH : num;
|
|
|
|
swrite(spaces, sizeof(char), bytes, out);
|
|
|
|
num -= bytes;
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void centre(struct stream *out, const char *s, bool breaking)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +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) {
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, SP->s, false);
|
2014-08-17 00:14:50 +02:00
|
|
|
SP = SP->next;
|
|
|
|
}
|
|
|
|
freestrlist(T);
|
|
|
|
}
|
|
|
|
else {
|
2015-05-19 08:26:44 +02:00
|
|
|
write_spaces(out, (REPORTWIDTH - strlen(s) + 1) / 2);
|
2015-05-13 05:36:00 +02:00
|
|
|
sputs(s, out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2015-08-19 14:37:51 +02:00
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_indent,
|
2016-09-16 18:03:28 +02:00
|
|
|
char marker)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
size_t length = REPORTWIDTH;
|
2018-04-28 15:57:51 +02:00
|
|
|
const char *handle_end, *begin, *mark = 0;
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
if (!str) return;
|
|
|
|
/* find out if there's a mark + indent already encoded in the string. */
|
2015-05-13 04:25:50 +02:00
|
|
|
if (!marker) {
|
2014-08-17 00:14:50 +02:00
|
|
|
const char *x = str;
|
|
|
|
while (*x == ' ')
|
|
|
|
++x;
|
|
|
|
indent += x - str;
|
|
|
|
if (x[0] && indent && x[1] == ' ') {
|
|
|
|
indent += 2;
|
2015-05-13 04:25:50 +02:00
|
|
|
mark = x;
|
2014-08-17 00:14:50 +02:00
|
|
|
str = x + 2;
|
|
|
|
hanging_indent -= 2;
|
|
|
|
}
|
2015-08-18 17:08:02 +02:00
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
else {
|
|
|
|
mark = ▮
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
begin = handle_end = str;
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
do {
|
|
|
|
const char *last_space = begin;
|
|
|
|
|
|
|
|
if (mark && indent >= 2) {
|
2015-05-19 08:26:44 +02:00
|
|
|
write_spaces(out, indent - 2);
|
2015-05-13 04:25:50 +02:00
|
|
|
swrite(mark, sizeof(char), 1, out);
|
2015-05-19 08:26:44 +02:00
|
|
|
write_spaces(out, 1);
|
2014-08-17 00:14:50 +02:00
|
|
|
mark = 0;
|
|
|
|
}
|
|
|
|
else if (begin == str) {
|
2015-05-19 08:26:44 +02:00
|
|
|
write_spaces(out, indent);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2015-05-19 08:26:44 +02:00
|
|
|
write_spaces(out, indent + hanging_indent);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
while (*handle_end && handle_end <= begin + length - indent) {
|
|
|
|
if (*handle_end == ' ') {
|
|
|
|
last_space = handle_end;
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
++handle_end;
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
if (*handle_end == 0)
|
|
|
|
last_space = handle_end;
|
2014-08-17 00:14:50 +02:00
|
|
|
if (last_space == begin) {
|
|
|
|
/* there was no space in this line. clip it */
|
2018-04-28 15:57:51 +02:00
|
|
|
last_space = handle_end;
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
swrite(begin, sizeof(char), last_space - begin, out);
|
2014-08-17 00:14:50 +02:00
|
|
|
begin = last_space;
|
|
|
|
while (*begin == ' ') {
|
|
|
|
++begin;
|
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
if (begin > handle_end)
|
|
|
|
begin = handle_end;
|
2015-05-13 04:25:50 +02:00
|
|
|
sputs("", out);
|
2014-08-17 00:14:50 +02:00
|
|
|
} while (*begin);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2017-02-02 16:52:32 +01:00
|
|
|
static size_t write_spell_modifier(const spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) {
|
2014-08-17 00:14:50 +02:00
|
|
|
if (sp->sptyp & flag) {
|
|
|
|
size_t bytes = 0;
|
|
|
|
if (cont) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = str_strlcpy(bufp, ", ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = str_strlcpy(bufp, " ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes += str_strlcpy(bufp + bytes, str, size - bytes);
|
2014-08-17 00:14:50 +02:00
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
return 0;
|
2012-07-09 00:40:37 +02:00
|
|
|
}
|
|
|
|
|
2018-06-03 13:29:54 +02:00
|
|
|
void nr_spell_syntax(char *buf, size_t size, spellbook_entry * sbe, const struct locale *lang)
|
2015-11-12 22:29:56 +01:00
|
|
|
{
|
2018-05-05 07:38:11 +02:00
|
|
|
const spell *sp = spellref_get(&sbe->spref);
|
2015-11-12 22:29:56 +01:00
|
|
|
const char *params = sp->parameter;
|
2018-06-03 13:29:54 +02:00
|
|
|
const char *spname;
|
|
|
|
sbstring sbs;
|
2015-11-12 22:29:56 +01:00
|
|
|
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_init(&sbs, buf, size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (sp->sptyp & ISCOMBATSPELL) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcpy(&sbs, LOC(lang, keyword(K_COMBATSPELL)));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcpy(&sbs, LOC(lang, keyword(K_CAST)));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reihenfolge beachten: Erst REGION, dann STUFE! */
|
|
|
|
if (sp->sptyp & FARCASTING) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [");
|
|
|
|
sbs_strcat(&sbs, LOC(lang, parameters[P_REGION]));
|
|
|
|
sbs_strcat(&sbs, " x y]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (sp->sptyp & SPELLLEVEL) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [");
|
|
|
|
sbs_strcat(&sbs, LOC(lang, parameters[P_LEVEL]));
|
|
|
|
sbs_strcat(&sbs, " n]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
2018-06-03 13:29:54 +02:00
|
|
|
spname = spell_name(sp, lang);
|
|
|
|
if (strchr(spname, ' ') != NULL) {
|
|
|
|
/* contains spaces, needs quotes */
|
|
|
|
sbs_strcat(&sbs, " '");
|
|
|
|
sbs_strcat(&sbs, spname);
|
|
|
|
sbs_strcat(&sbs, "'");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sbs_strcat(&sbs, " ");
|
|
|
|
sbs_strcat(&sbs, spname);
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
while (params && *params) {
|
|
|
|
typedef struct starget {
|
|
|
|
param_t param;
|
|
|
|
int flag;
|
|
|
|
const char *vars;
|
|
|
|
} starget;
|
|
|
|
starget targets[] = {
|
2015-01-30 20:37:14 +01:00
|
|
|
{ P_REGION, REGIONSPELL, NULL },
|
|
|
|
{ P_UNIT, UNITSPELL, "par_unit" },
|
|
|
|
{ P_SHIP, SHIPSPELL, "par_ship" },
|
|
|
|
{ P_BUILDING, BUILDINGSPELL, "par_building" },
|
|
|
|
{ 0, 0, NULL }
|
2014-08-17 00:14:50 +02:00
|
|
|
};
|
|
|
|
starget *targetp;
|
|
|
|
char cp = *params++;
|
|
|
|
const char *locp;
|
|
|
|
const char *syntaxp = sp->syntax;
|
|
|
|
|
|
|
|
if (cp == 'u') {
|
|
|
|
targetp = targets + 1;
|
|
|
|
locp = LOC(lang, targetp->vars);
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " <");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">");
|
2014-08-17 00:14:50 +02:00
|
|
|
if (*params == '+') {
|
|
|
|
++params;
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, "> ...]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cp == 's') {
|
|
|
|
targetp = targets + 2;
|
2010-08-08 10:06:34 +02:00
|
|
|
locp = LOC(lang, targetp->vars);
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " <");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">");
|
2014-08-17 00:14:50 +02:00
|
|
|
if (*params == '+') {
|
|
|
|
++params;
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, "> ...]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cp == 'r') {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " <x> <y>");
|
2011-03-07 08:02:35 +01:00
|
|
|
if (*params == '+') {
|
2014-08-17 00:14:50 +02:00
|
|
|
++params;
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<x> <y> ...]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cp == 'b') {
|
|
|
|
targetp = targets + 3;
|
|
|
|
locp = LOC(lang, targetp->vars);
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " <");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">");
|
2014-08-17 00:14:50 +02:00
|
|
|
if (*params == '+') {
|
|
|
|
++params;
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, "> ...]");
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else if (cp == 'k') {
|
2018-02-11 16:14:00 +01:00
|
|
|
int i, maxparam = 0;
|
2015-11-12 22:29:56 +01:00
|
|
|
bool multi = false;
|
|
|
|
if (params && *params == 'c') {
|
2014-08-17 00:14:50 +02:00
|
|
|
/* skip over a potential id */
|
|
|
|
++params;
|
|
|
|
}
|
2015-11-12 22:29:56 +01:00
|
|
|
if (params && *params == '+') {
|
|
|
|
++params;
|
|
|
|
multi = true;
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
for (targetp = targets; targetp->flag; ++targetp) {
|
|
|
|
if (sp->sptyp & targetp->flag)
|
|
|
|
++maxparam;
|
|
|
|
}
|
2015-01-13 22:03:09 +01:00
|
|
|
if (!maxparam || maxparam > 1) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " (");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
i = 0;
|
|
|
|
for (targetp = targets; targetp->flag; ++targetp) {
|
2015-01-13 22:03:09 +01:00
|
|
|
if (!maxparam || sp->sptyp & targetp->flag) {
|
2014-08-17 00:14:50 +02:00
|
|
|
if (i++ != 0) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " |");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-01-13 22:03:09 +01:00
|
|
|
if (targetp->param && targetp->vars) {
|
2014-08-17 00:14:50 +02:00
|
|
|
locp = LOC(lang, targetp->vars);
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " ");
|
|
|
|
sbs_strcat(&sbs, parameters[targetp->param]);
|
|
|
|
sbs_strcat(&sbs, " <");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">");
|
2015-11-12 22:29:56 +01:00
|
|
|
if (multi) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, "> ...]");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " ");
|
|
|
|
sbs_strcat(&sbs, parameters[targetp->param]);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-13 22:03:09 +01:00
|
|
|
if (!maxparam || maxparam > 1) {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " )");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cp == 'i' || cp == 'c') {
|
|
|
|
const char *cstr;
|
|
|
|
assert(syntaxp);
|
|
|
|
cstr = strchr(syntaxp, ':');
|
|
|
|
if (!cstr) {
|
|
|
|
locp = LOC(lang, mkname("spellpar", syntaxp));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char substr[32];
|
2017-01-06 21:37:52 +01:00
|
|
|
size_t len = cstr - syntaxp;
|
|
|
|
assert(sizeof(substr) > len);
|
|
|
|
memcpy(substr, syntaxp, len);
|
|
|
|
substr[len] = 0;
|
2014-08-17 00:14:50 +02:00
|
|
|
locp = LOC(lang, mkname("spellpar", substr));
|
|
|
|
syntaxp = substr + 1;
|
|
|
|
}
|
2015-12-06 12:48:13 +01:00
|
|
|
if (*params == '?') {
|
|
|
|
++params;
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " [<");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">]");
|
2015-12-06 12:48:13 +01:00
|
|
|
}
|
|
|
|
else {
|
2018-06-03 13:29:54 +02:00
|
|
|
sbs_strcat(&sbs, " <");
|
|
|
|
sbs_strcat(&sbs, locp);
|
|
|
|
sbs_strcat(&sbs, ">");
|
2015-12-06 12:48:13 +01:00
|
|
|
}
|
2016-09-13 20:13:26 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
log_error("unknown spell parameter %c for spell %s", cp, sp->sname);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *lang)
|
2016-09-13 20:13:26 +02:00
|
|
|
{
|
|
|
|
int bytes, k, itemanz, costtyp;
|
|
|
|
char buf[4096];
|
|
|
|
char *startp, *bufp = buf;
|
|
|
|
size_t size = sizeof(buf) - 1;
|
2018-05-05 07:38:11 +02:00
|
|
|
const spell *sp = spellref_get(&sbe->spref);
|
2016-09-13 20:13:26 +02:00
|
|
|
|
|
|
|
newline(out);
|
|
|
|
centre(out, spell_name(sp, lang), true);
|
|
|
|
newline(out);
|
|
|
|
paragraph(out, LOC(lang, "nr_spell_description"), 0, 0, 0);
|
|
|
|
paragraph(out, spell_info(sp, lang), 2, 0, 0);
|
|
|
|
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(lang, "nr_spell_type"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
if (size) {
|
|
|
|
*bufp++ = ' ';
|
|
|
|
--size;
|
|
|
|
}
|
|
|
|
if (sp->sptyp & PRECOMBATSPELL) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_precombat"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
}
|
|
|
|
else if (sp->sptyp & COMBATSPELL) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_combat"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
}
|
|
|
|
else if (sp->sptyp & POSTCOMBATSPELL) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_postcombat"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(lang, "sptype_normal"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
*bufp = 0;
|
|
|
|
paragraph(out, buf, 0, 0, 0);
|
|
|
|
|
|
|
|
sprintf(buf, "%s %d", LOC(lang, "nr_spell_level"), sbe->level);
|
|
|
|
paragraph(out, buf, 0, 0, 0);
|
|
|
|
|
|
|
|
sprintf(buf, "%s %d", LOC(lang, "nr_spell_rank"), sp->rank);
|
|
|
|
paragraph(out, buf, 0, 0, 0);
|
|
|
|
|
|
|
|
paragraph(out, LOC(lang, "nr_spell_components"), 0, 0, 0);
|
|
|
|
for (k = 0; sp->components[k].type; ++k) {
|
|
|
|
const resource_type *rtype = sp->components[k].type;
|
|
|
|
itemanz = sp->components[k].amount;
|
|
|
|
costtyp = sp->components[k].cost;
|
|
|
|
if (itemanz > 0) {
|
|
|
|
size = sizeof(buf) - 1;
|
|
|
|
bufp = buf;
|
|
|
|
if (sp->sptyp & SPELLLEVEL) {
|
|
|
|
bytes =
|
2017-01-10 16:31:05 +01:00
|
|
|
snprintf(bufp, size, " %d %s", itemanz, LOC(lang, resourcename(rtype,
|
2016-09-13 20:13:26 +02:00
|
|
|
itemanz != 1)));
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, " * %s", LOC(lang, "nr_level"));
|
2016-09-13 20:13:26 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, "%d %s", itemanz, LOC(lang, resourcename(rtype, itemanz != 1)));
|
2016-09-13 20:13:26 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0) {
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*bufp = 0;
|
|
|
|
paragraph(out, buf, 2, 2, '-');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size = sizeof(buf) - 1;
|
|
|
|
bufp = buf;
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(buf, LOC(lang, "nr_spell_modifiers"), size);
|
2016-09-13 20:13:26 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
startp = bufp;
|
|
|
|
bytes = (int)write_spell_modifier(sp, FARCASTING, LOC(lang, "smod_far"), startp != bufp, bufp, size);
|
|
|
|
if (bytes && wrptr(&bufp, &size, bytes) != 0) {
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
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, LOC(lang, "nr_spell_syntax"), 0, 0, 0);
|
|
|
|
|
2018-06-03 13:29:54 +02:00
|
|
|
nr_spell_syntax(buf, sizeof(buf), sbe, lang);
|
|
|
|
paragraph(out, buf, 2, 0, 0);
|
2016-09-13 20:13:26 +02:00
|
|
|
|
|
|
|
newline(out);
|
|
|
|
}
|
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
nr_curses_i(struct stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj, attrib *a, int self)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-05-13 04:25:50 +02:00
|
|
|
for (; a; a = a->next) {
|
|
|
|
char buf[4096];
|
2015-08-07 16:17:11 +02:00
|
|
|
message *msg = 0;
|
2015-05-13 04:25:50 +02:00
|
|
|
|
2017-08-25 21:11:01 +02:00
|
|
|
if (a->type == &at_curse) {
|
2015-05-13 04:25:50 +02:00
|
|
|
curse *c = (curse *)a->data.v;
|
|
|
|
|
2015-08-07 15:52:10 +02:00
|
|
|
self = curse_cansee(c, viewer, typ, obj, self);
|
2015-05-13 04:25:50 +02:00
|
|
|
msg = msg_curse(c, obj, typ, self);
|
|
|
|
}
|
|
|
|
else if (a->type == &at_effect && self) {
|
|
|
|
effect_data *data = (effect_data *)a->data.v;
|
|
|
|
if (data->value > 0) {
|
|
|
|
msg = msg_message("nr_potion_effect", "potion left",
|
2018-01-12 09:17:01 +01:00
|
|
|
data->type->rtype, data->value);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-08-07 16:17:11 +02:00
|
|
|
if (msg) {
|
|
|
|
newline(out);
|
|
|
|
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
|
|
|
|
paragraph(out, buf, indent, 2, 0);
|
|
|
|
msg_release(msg);
|
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void nr_curses(struct stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
int self = 0;
|
2015-05-13 04:25:50 +02:00
|
|
|
attrib *a = NULL;
|
2014-08-17 00:14:50 +02:00
|
|
|
region *r;
|
|
|
|
|
|
|
|
/* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei
|
2015-07-06 21:31:27 +02:00
|
|
|
* Gebäuden und Schiffen je nach, ob man Besitzer ist, verschieden.
|
2015-05-13 04:25:50 +02:00
|
|
|
* Bei Einheiten sieht man Wirkungen auf eigene Einheiten immer.
|
2015-07-06 21:31:27 +02:00
|
|
|
* Spezialfälle (besonderes Talent, verursachender Magier usw. werde
|
2015-05-13 04:25:50 +02:00
|
|
|
* bei jedem curse gesondert behandelt. */
|
2014-08-17 00:14:50 +02:00
|
|
|
if (typ == TYP_SHIP) {
|
|
|
|
ship *sh = (ship *)obj;
|
|
|
|
unit *owner = ship_owner(sh);
|
|
|
|
a = sh->attribs;
|
|
|
|
r = sh->region;
|
|
|
|
if (owner) {
|
|
|
|
if (owner->faction == viewer) {
|
|
|
|
self = 2;
|
|
|
|
}
|
|
|
|
else { /* steht eine person der Partei auf dem Schiff? */
|
|
|
|
unit *u = NULL;
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
if (u->ship == sh) {
|
|
|
|
self = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
else if (typ == TYP_BUILDING) {
|
|
|
|
building *b = (building *)obj;
|
|
|
|
unit *owner;
|
|
|
|
a = b->attribs;
|
|
|
|
r = b->region;
|
|
|
|
if ((owner = building_owner(b)) != NULL) {
|
|
|
|
if (owner->faction == viewer) {
|
|
|
|
self = 2;
|
|
|
|
}
|
|
|
|
else { /* steht eine Person der Partei in der Burg? */
|
|
|
|
unit *u = NULL;
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
if (u->building == b) {
|
|
|
|
self = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
else if (typ == TYP_UNIT) {
|
|
|
|
unit *u = (unit *)obj;
|
|
|
|
a = u->attribs;
|
|
|
|
r = u->region;
|
|
|
|
if (u->faction == viewer) {
|
|
|
|
self = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (typ == TYP_REGION) {
|
|
|
|
r = (region *)obj;
|
|
|
|
a = r->attribs;
|
|
|
|
}
|
|
|
|
else {
|
2015-05-13 04:25:50 +02:00
|
|
|
log_error("get_attribs: invalid object type %d", typ);
|
|
|
|
assert(!"invalid object type");
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2015-05-13 13:12:46 +02:00
|
|
|
nr_curses_i(out, indent, viewer, typ, obj, a, self);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void rps_nowrap(struct stream *out, const char *s)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
const char *x = s;
|
|
|
|
size_t indent = 0;
|
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
if (!x || !*x) return;
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
while (*x++ == ' ');
|
|
|
|
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);
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
swrite(s++, sizeof(char), 1, out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
nr_unit(struct stream *out, const faction * f, const unit * u, int indent, seen_mode mode)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
char marker;
|
|
|
|
int dh;
|
2018-03-11 14:40:38 +01:00
|
|
|
bool isbattle = (mode == seen_battle);
|
2014-08-17 00:14:50 +02:00
|
|
|
char buf[8192];
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (fval(u_race(u), RCF_INVISIBLE))
|
|
|
|
return;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-05-13 04:25:50 +02:00
|
|
|
newline(out);
|
2018-11-24 12:26:52 +01:00
|
|
|
dh = bufunit_depr(f, u, mode, buf, sizeof(buf));
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
if (u->faction == f) {
|
|
|
|
marker = '*';
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2014-12-09 14:14:35 +01:00
|
|
|
else if (is_allied(u->faction, f)) {
|
2014-08-17 00:14:50 +02:00
|
|
|
marker = 'o';
|
|
|
|
}
|
2017-03-06 21:35:48 +01:00
|
|
|
else if (u->attribs && f != u->faction
|
|
|
|
&& !fval(u, UFL_ANON_FACTION) && get_otherfaction(u) == f) {
|
2014-08-17 00:14:50 +02:00
|
|
|
marker = '!';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (dh && !fval(u, UFL_ANON_FACTION)) {
|
|
|
|
marker = '+';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
marker = '-';
|
|
|
|
}
|
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
paragraph(out, buf, indent, 0, marker);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (!isbattle) {
|
2015-05-13 04:25:50 +02:00
|
|
|
nr_curses(out, indent, f, TYP_UNIT, u);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
rp_messages(struct stream *out, message_list * msgs, faction * viewer, int indent,
|
2016-09-16 18:03:28 +02:00
|
|
|
bool categorized)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-05-18 19:58:49 +02:00
|
|
|
int i;
|
|
|
|
if (!msgs) {
|
2014-08-17 00:14:50 +02:00
|
|
|
return;
|
2018-05-18 19:58:49 +02:00
|
|
|
}
|
|
|
|
for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
|
|
|
|
const char * section = sections[i];
|
2014-08-17 00:14:50 +02:00
|
|
|
int k = 0;
|
|
|
|
struct mlist *m = msgs->begin;
|
|
|
|
while (m) {
|
2018-05-20 17:11:29 +02:00
|
|
|
/* categorized messages need a section: */
|
|
|
|
assert(!categorized || (m->msg->type->section != NULL));
|
|
|
|
if (!categorized || m->msg->type->section == section) {
|
2014-08-17 00:14:50 +02:00
|
|
|
char lbuf[8192];
|
|
|
|
|
|
|
|
if (!k && categorized) {
|
|
|
|
const char *section_title;
|
|
|
|
char cat_identifier[24];
|
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2018-05-18 19:58:49 +02:00
|
|
|
sprintf(cat_identifier, "section_%s", section);
|
2014-08-17 00:14:50 +02:00
|
|
|
section_title = LOC(viewer->locale, cat_identifier);
|
2017-12-22 11:15:17 +01:00
|
|
|
if (section_title) {
|
|
|
|
centre(out, section_title, true);
|
|
|
|
newline(out);
|
|
|
|
}
|
|
|
|
else {
|
2018-05-18 19:58:49 +02:00
|
|
|
log_error("no title defined for section %s in locale %s", section, locale_name(viewer->locale));
|
2017-12-22 11:15:17 +01:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
k = 1;
|
|
|
|
}
|
|
|
|
nr_render(m->msg, viewer->locale, lbuf, sizeof(lbuf), viewer);
|
2018-05-17 22:47:16 +02:00
|
|
|
/* Hack: some messages should start a new paragraph with a newline: */
|
|
|
|
if (strncmp("para_", m->msg->type->name, 5) == 0) {
|
|
|
|
newline(out);
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, lbuf, indent, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
m = m->next;
|
|
|
|
}
|
|
|
|
if (!categorized)
|
|
|
|
break;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void rp_battles(struct stream *out, faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
if (f->battles != NULL) {
|
|
|
|
struct bmsg *bm = f->battles;
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, LOC(f->locale, "section_battle"), false);
|
|
|
|
newline(out);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
while (bm) {
|
|
|
|
char buf[256];
|
2017-10-16 20:38:52 +02:00
|
|
|
RENDER(f, buf, sizeof(buf), ("header_battle", "region", bm->r));
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
|
|
|
newline(out);
|
|
|
|
rp_messages(out, bm->msgs, f, 0, false);
|
2014-08-17 00:14:50 +02:00
|
|
|
bm = bm->next;
|
2018-06-11 20:42:28 +02:00
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void prices(struct stream *out, const region * r, const faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
const luxury_type *sale = NULL;
|
|
|
|
struct demand *dmd;
|
|
|
|
message *m;
|
|
|
|
int bytes, n = 0;
|
|
|
|
char buf[4096], *bufp = buf;
|
|
|
|
size_t size = sizeof(buf) - 1;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02: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++;
|
|
|
|
}
|
|
|
|
assert(sale != NULL);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
m = msg_message("nr_market_sale", "product price",
|
|
|
|
sale->itype->rtype, sale->price);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
bytes = (int)nr_render(m, f->locale, bufp, size, f);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2014-08-17 00:14:50 +02:00
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
msg_release(m);
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (n > 0) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_intro"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
for (dmd = r->land->demands; dmd; dmd = dmd->next) {
|
2014-08-17 00:14:50 +02:00
|
|
|
if (dmd->value > 0) {
|
2015-01-30 20:37:14 +01:00
|
|
|
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);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2015-01-30 20:37:14 +01:00
|
|
|
msg_release(m);
|
|
|
|
n--;
|
|
|
|
if (n == 0) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_end"),
|
2015-01-30 20:43:40 +01:00
|
|
|
size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
else if (n == 1) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_final"),
|
2015-01-30 20:43:40 +01:00
|
|
|
size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_trade_next"),
|
2015-01-30 20:43:40 +01:00
|
|
|
size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2015-01-30 20:37:14 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-02-01 12:24:19 +01:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
/* Schreibe Paragraphen */
|
|
|
|
*bufp = 0;
|
2015-05-13 04:57:08 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2012-06-24 07:41:07 +02:00
|
|
|
bool see_border(const connection * b, const faction * f, const region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
bool cs = b->type->fvisible(b, f, r);
|
2010-08-08 10:06:34 +02:00
|
|
|
if (!cs) {
|
2014-08-17 00:14:50 +02:00
|
|
|
cs = b->type->rvisible(b, r);
|
|
|
|
if (!cs) {
|
|
|
|
const unit *us = r->units;
|
|
|
|
while (us && !cs) {
|
|
|
|
if (us->faction == f) {
|
|
|
|
cs = b->type->uvisible(b, us);
|
|
|
|
if (cs)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
us = us->next;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
return cs;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-10-19 20:49:58 +02:00
|
|
|
#define MAX_EDGES 16
|
|
|
|
|
2017-03-05 16:55:11 +01:00
|
|
|
void report_region(struct stream *out, const region * r, faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
int n;
|
|
|
|
bool dh;
|
|
|
|
direction_t d;
|
|
|
|
int trees;
|
|
|
|
int saplings;
|
|
|
|
attrib *a;
|
|
|
|
const char *tname;
|
|
|
|
struct edge {
|
|
|
|
char *name;
|
|
|
|
bool transparent;
|
|
|
|
bool block;
|
|
|
|
bool exist[MAXDIRECTIONS];
|
|
|
|
direction_t lastd;
|
2018-10-19 20:49:58 +02:00
|
|
|
} edges[MAX_EDGES];
|
|
|
|
int ne = 0;
|
2014-08-17 00:14:50 +02:00
|
|
|
bool see[MAXDIRECTIONS];
|
|
|
|
char buf[8192];
|
|
|
|
char *bufp = buf;
|
|
|
|
size_t size = sizeof(buf);
|
|
|
|
int bytes;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-07-07 00:49:12 +02:00
|
|
|
assert(out);
|
|
|
|
assert(f);
|
2016-09-13 20:13:26 +02:00
|
|
|
assert(r);
|
2015-07-07 00:49:12 +02:00
|
|
|
|
2018-10-29 16:19:29 +01:00
|
|
|
memset(edges, 0, sizeof(edges));
|
2014-08-17 00:14:50 +02:00
|
|
|
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;) {
|
2018-10-19 20:49:58 +02:00
|
|
|
int e;
|
|
|
|
struct edge *match = NULL;
|
2014-08-17 00:14:50 +02:00
|
|
|
bool transparent = b->type->transparent(b, f);
|
2016-08-06 14:36:54 +02:00
|
|
|
const char *name = border_name(b, r, f, GF_DETAILED | GF_ARTICLE);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2016-11-23 18:56:40 +01:00
|
|
|
if (!transparent) {
|
2014-08-17 00:14:50 +02:00
|
|
|
see[d] = false;
|
2016-11-23 18:56:40 +01:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
if (!see_border(b, f, r)) {
|
|
|
|
b = b->next;
|
|
|
|
continue;
|
|
|
|
}
|
2018-10-19 20:49:58 +02:00
|
|
|
for (e = 0; e!=ne; ++e) {
|
|
|
|
struct edge *edg = edges + e;
|
|
|
|
if (edg->transparent == transparent && 0 == strcmp(name, edg->name)) {
|
|
|
|
match = edg;
|
|
|
|
break;
|
|
|
|
}
|
2016-11-23 18:56:40 +01:00
|
|
|
}
|
2018-10-19 20:49:58 +02:00
|
|
|
if (match == NULL) {
|
|
|
|
match = edges + ne;
|
|
|
|
match->name = str_strdup(name);
|
|
|
|
match->transparent = transparent;
|
|
|
|
++ne;
|
|
|
|
assert(ne < MAX_EDGES);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-10-19 20:49:58 +02:00
|
|
|
match->lastd = d;
|
|
|
|
match->exist[d] = true;
|
2014-08-17 00:14:50 +02:00
|
|
|
b = b->next;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
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();
|
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
if (r->seen.mode == seen_travel) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_travel"));
|
2011-03-07 08:02:35 +01:00
|
|
|
}
|
2016-09-16 18:03:28 +02:00
|
|
|
else if (r->seen.mode == seen_neighbour) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_neighbour"));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2016-09-16 18:03:28 +02:00
|
|
|
else if (r->seen.mode == seen_lighthouse) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, " (%s)", LOC(f->locale, "see_lighthouse"));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
bytes = 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2014-08-17 00:14:50 +02:00
|
|
|
WARN_STATIC_BUFFER();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Terrain */
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ", ", size);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2014-08-17 00:14:50 +02:00
|
|
|
WARN_STATIC_BUFFER();
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
tname = terrain_name(r);
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_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
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Trees */
|
|
|
|
trees = rtrees(r, 2);
|
|
|
|
saplings = rtrees(r, 1);
|
2017-12-04 19:20:48 +01:00
|
|
|
if (max_production(r)) {
|
2014-08-17 00:14:50 +02:00
|
|
|
if (trees > 0 || saplings > 0) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, ", %d/%d ", trees, saplings);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
if (fval(r, RF_MALLORN)) {
|
|
|
|
if (trees == 1) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mallorntree"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mallorntree_p"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (trees == 1) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "tree"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "tree_p"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* iron & stone */
|
2016-09-25 13:01:51 +02:00
|
|
|
if (r->seen.mode >= seen_unit) {
|
2014-08-17 00:14:50 +02:00
|
|
|
resource_report result[MAX_RAWMATERIALS];
|
2017-12-29 06:13:28 +01:00
|
|
|
int numresults = report_resources(r, result, MAX_RAWMATERIALS, f, true);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
for (n = 0; n < numresults; ++n) {
|
|
|
|
if (result[n].number >= 0 && result[n].level >= 0) {
|
2017-03-05 18:25:15 +01:00
|
|
|
const char * name = resourcename(result[n].rtype, result[n].number!=1);
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, ", %d %s/%d", result[n].number,
|
2017-03-05 18:25:15 +01:00
|
|
|
LOC(f->locale, name), result[n].level);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* peasants & silver */
|
|
|
|
if (rpeasants(r)) {
|
2017-12-29 06:13:28 +01:00
|
|
|
int p = rpeasants(r);
|
|
|
|
bytes = snprintf(bufp, size, ", %d", p);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
if (r->land->ownership) {
|
|
|
|
const char *str =
|
2015-12-07 17:59:50 +01:00
|
|
|
LOC(f->locale, mkname("morale", itoa10(region_get_morale(r))));
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, " %s", str);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2016-11-13 17:13:59 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
bytes =
|
2017-12-30 19:49:21 +01:00
|
|
|
(int)str_strlcpy(bufp, LOC(f->locale, p == 1 ? "peasant" : "peasant_p"),
|
2016-11-13 17:13:59 +01:00
|
|
|
size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
if (is_mourning(r, turn + 1)) {
|
2018-05-19 13:34:00 +02:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_mourning"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
2016-09-16 18:03:28 +02:00
|
|
|
if (rmoney(r) && r->seen.mode >= seen_travel) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, ", %d ", rmoney(r));
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
bytes =
|
2017-12-30 19:49:21 +01:00
|
|
|
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(get_resourcetype(R_SILVER),
|
2016-09-16 18:03:28 +02:00
|
|
|
rmoney(r) != 1)), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
/* Pferde */
|
|
|
|
|
|
|
|
if (rhorses(r)) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, ", %d ", rhorses(r));
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
bytes =
|
2017-12-30 19:49:21 +01:00
|
|
|
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(get_resourcetype(R_HORSE),
|
2014-08-17 00:14:50 +02:00
|
|
|
(rhorses(r) > 1) ? GR_PLURAL : 0)), size);
|
|
|
|
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
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ".", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2011-03-07 08:02:35 +01:00
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2017-09-16 07:58:57 +02:00
|
|
|
if (r->land && r->land->display && r->land->display[0]) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, r->land->display, size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
2017-09-16 07:58:57 +02:00
|
|
|
n = r->land->display[strlen(r->land->display) - 1];
|
2014-08-17 00:14:50 +02:00
|
|
|
if (n != '!' && n != '?' && n != '.') {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ".", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (rule_region_owners()) {
|
|
|
|
const faction *owner = region_get_owner(r);
|
2015-01-30 20:43:40 +01:00
|
|
|
message *msg;
|
2015-01-14 16:13:08 +01:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (owner != NULL) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2017-10-06 04:14:07 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2015-01-30 20:43:40 +01:00
|
|
|
msg = msg_message("nr_region_owner", "faction", owner);
|
|
|
|
bytes = (int)nr_render(msg, f->locale, bufp, size, f);
|
|
|
|
msg_release(msg);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a = a_find(r->attribs, &at_overrideroads);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (a) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, (char *)a->data.v, size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int nrd = 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Nachbarregionen, die gesehen werden, ermitteln */
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++) {
|
|
|
|
if (see[d] && rconnect(r, d))
|
|
|
|
nrd++;
|
|
|
|
}
|
|
|
|
/* list directions */
|
|
|
|
|
|
|
|
dh = false;
|
2014-08-27 21:09:39 +02:00
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++) {
|
2014-08-17 00:14:50 +02:00
|
|
|
if (see[d]) {
|
2014-08-27 21:09:39 +02:00
|
|
|
region *r2 = rconnect(r, d);
|
|
|
|
if (!r2)
|
|
|
|
continue;
|
|
|
|
nrd--;
|
|
|
|
if (dh) {
|
|
|
|
char regname[4096];
|
|
|
|
if (nrd == 0) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-27 21:09:39 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_nb_final"), size);
|
2014-08-27 21:09:39 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_nb_next"), size);
|
2014-08-27 21:09:39 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, directions[d]), size);
|
2014-08-27 21:09:39 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-27 21:09:39 +02:00
|
|
|
f_regionid(r2, f, regname, sizeof(regname));
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, trailinto(r2, f->locale), regname);
|
2014-08-27 21:09:39 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-27 21:09:39 +02:00
|
|
|
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;
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-27 21:09:39 +02:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Spezielle Richtungen */
|
|
|
|
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
|
|
|
|
a = a->next) {
|
2017-12-29 06:13:28 +01:00
|
|
|
spec_direction *spd = (spec_direction *)(a->data.v);
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, spd->desc), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " (\"", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, spd->keyword), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, "\")", size);
|
2018-11-25 09:38:58 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
bytes = (int)str_strlcpy(bufp, ".", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
dh = 1;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
*bufp = 0;
|
2015-05-13 04:57:08 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2016-09-25 13:01:51 +02:00
|
|
|
if (r->seen.mode >= seen_unit && is_astral(r) &&
|
2017-08-21 20:48:00 +02:00
|
|
|
!is_cursed(r->attribs, &ct_astralblock)) {
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Sonderbehandlung Teleport-Ebene */
|
|
|
|
region_list *rl = astralregions(r, inhabitable);
|
|
|
|
region_list *rl2;
|
|
|
|
|
|
|
|
if (rl) {
|
|
|
|
bufp = buf;
|
|
|
|
size = sizeof(buf) - 1;
|
2015-01-14 16:13:08 +01:00
|
|
|
|
2017-02-18 21:15:14 +01:00
|
|
|
/* this localization might not work for every language but is fine for de and en */
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_schemes_prefix"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
rl2 = rl;
|
|
|
|
while (rl2) {
|
|
|
|
bytes = (int)f_regionid(rl2->data, f, bufp, size);
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
rl2 = rl2->next;
|
|
|
|
if (rl2) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ", ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, "nr_schemes_postfix"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
free_regionlist(rl);
|
|
|
|
/* Schreibe Paragraphen */
|
2015-05-13 04:57:08 +02:00
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
*bufp = 0;
|
2015-05-13 04:57:08 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-06 21:31:27 +02:00
|
|
|
/* Wirkungen permanenter Sprüche */
|
2015-05-13 04:25:50 +02:00
|
|
|
nr_curses(out, 0, f, TYP_REGION, r);
|
|
|
|
n = 0;
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2018-10-19 20:49:58 +02:00
|
|
|
if (ne > 0) {
|
|
|
|
int e;
|
2015-05-13 04:57:08 +02:00
|
|
|
newline(out);
|
2018-10-19 20:49:58 +02:00
|
|
|
for (e = 0; e != ne; ++e) {
|
|
|
|
message *msg;
|
|
|
|
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
|
|
|
if (edges[e].exist[d]) {
|
|
|
|
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);
|
|
|
|
}
|
2018-06-11 20:42:28 +02:00
|
|
|
}
|
2018-10-19 20:49:58 +02:00
|
|
|
free(edges[e].name);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void statistics(struct stream *out, const region * r, const faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
const unit *u;
|
|
|
|
int number = 0, p = rpeasants(r);
|
|
|
|
message *m;
|
|
|
|
item *itm, *items = NULL;
|
|
|
|
char buf[4096];
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* count */
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
if (u->faction == f && !fval(u_race(u), RCF_INVISIBLE)) {
|
|
|
|
for (itm = u->items; itm; itm = itm->next) {
|
|
|
|
i_change(&items, itm->type, itm->number);
|
|
|
|
}
|
|
|
|
number += u->number;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* print */
|
|
|
|
m = msg_message("nr_stat_header", "region", r);
|
2010-08-08 10:06:34 +02:00
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
|
|
|
newline(out);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
/* Region */
|
|
|
|
if (skill_enabled(SK_ENTERTAINMENT) && fval(r->terrain, LAND_REGION)
|
|
|
|
&& rmoney(r)) {
|
|
|
|
m = msg_message("nr_stat_maxentertainment", "max", entertainmoney(r));
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2017-12-04 19:20:48 +01:00
|
|
|
if (max_production(r) && (!fval(r->terrain, SEA_REGION)
|
2014-08-17 00:14:50 +02:00
|
|
|
|| f->race == get_race(RC_AQUARIAN))) {
|
|
|
|
if (markets_module()) { /* hack */
|
|
|
|
m =
|
|
|
|
msg_message("nr_stat_salary_new", "max", wage(r, NULL, NULL, turn + 1));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m = msg_message("nr_stat_salary", "max", wage(r, f, f->race, turn + 1));
|
|
|
|
}
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (p) {
|
|
|
|
m = msg_message("nr_stat_recruits", "max", p / RECRUITFRACTION);
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
|
|
|
|
|
|
|
if (!markets_module()) {
|
|
|
|
if (buildingtype_exists(r, bt_find("caravan"), true)) {
|
|
|
|
m = msg_message("nr_stat_luxuries", "max", (p * 2) / TRADE_FRACTION);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m = msg_message("nr_stat_luxuries", "max", p / TRADE_FRACTION);
|
|
|
|
}
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r->land->ownership) {
|
2015-12-07 17:59:50 +01:00
|
|
|
m = msg_message("nr_stat_morale", "morale", region_get_morale(r));
|
2014-08-17 00:14:50 +02:00
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
/* info about units */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
m = msg_message("nr_stat_people", "max", number);
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
|
|
|
|
|
|
|
for (itm = items; itm; itm = itm->next) {
|
|
|
|
sprintf(buf, "%s: %d",
|
|
|
|
LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number);
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 2, 2, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
while (items)
|
|
|
|
i_free(i_remove(&items, items));
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
|
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
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
const building_type *bt = b->type;
|
|
|
|
int c, cost = 0;
|
2016-08-21 17:19:22 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
for (c = 0; bt->maintenance && bt->maintenance[c].number; ++c) {
|
|
|
|
const maintenance *m = bt->maintenance + c;
|
|
|
|
if (m->rtype == rtype) {
|
|
|
|
if (fval(m, MTF_VARIABLE))
|
|
|
|
cost += (b->size * m->number);
|
|
|
|
else
|
|
|
|
cost += m->number;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
return cost;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2016-11-25 20:15:11 +01:00
|
|
|
report_template(const char *filename, report_context * ctx, const char *bom)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-06-24 16:42:45 +02:00
|
|
|
const resource_type *rsilver = get_resourcetype(R_SILVER);
|
2017-10-08 17:07:42 +02:00
|
|
|
const faction *f = ctx->f;
|
|
|
|
const struct locale *lang = f->locale;
|
2014-08-17 00:14:50 +02:00
|
|
|
region *r;
|
2016-02-05 23:10:05 +01:00
|
|
|
FILE *F = fopen(filename, "w");
|
2015-05-13 05:36:00 +02:00
|
|
|
stream strm = { 0 }, *out = &strm;
|
2014-08-17 00:14:50 +02:00
|
|
|
char buf[8192], *bufp;
|
|
|
|
size_t size;
|
|
|
|
int bytes;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (F == NULL) {
|
|
|
|
perror(filename);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
fstream_init(&strm, F);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-11-25 20:15:11 +01:00
|
|
|
if (bom) {
|
|
|
|
swrite(bom, 1, strlen(bom), out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2017-10-08 17:07:42 +02:00
|
|
|
rps_nowrap(out, LOC(lang, "nr_template"));
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
newline(out);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2017-10-08 17:07:42 +02:00
|
|
|
sprintf(buf, "%s %s \"password\"", LOC(lang, parameters[P_FACTION]), itoa36(f->no));
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost,
|
|
|
|
ECHECK_VERSION);
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
for (r = ctx->first; r != ctx->last; r = r->next) {
|
2014-08-17 00:14:50 +02:00
|
|
|
unit *u;
|
|
|
|
int dh = 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
if (r->seen.mode < seen_unit)
|
2014-08-17 00:14:50 +02:00
|
|
|
continue;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
if (u->faction == f && !fval(u_race(u), RCF_INVISIBLE)) {
|
|
|
|
order *ord;
|
|
|
|
if (!dh) {
|
|
|
|
plane *pl = getplane(r);
|
|
|
|
int nx = r->x, ny = r->y;
|
|
|
|
|
|
|
|
pnormalize(&nx, &ny, pl);
|
2015-05-19 08:02:32 +02:00
|
|
|
adjust_coordinates(f, &nx, &ny, pl);
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (pl && pl->id != 0) {
|
2017-10-08 17:07:42 +02:00
|
|
|
sprintf(buf, "%s %d,%d,%d ; %s", LOC(lang,
|
|
|
|
parameters[P_REGION]), nx, ny, pl->id, rname(r, lang));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-10-08 17:07:42 +02:00
|
|
|
sprintf(buf, "%s %d,%d ; %s", LOC(lang, parameters[P_REGION]),
|
|
|
|
nx, ny, rname(r, lang));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
sprintf(buf, "; ECheck Lohn %d", wage(r, f, f->race, turn + 1));
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
dh = 1;
|
|
|
|
|
|
|
|
bufp = buf;
|
|
|
|
size = sizeof(buf) - 1;
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, "%s %s; %s [%d,%d$",
|
2014-08-17 00:14:50 +02:00
|
|
|
LOC(u->faction->locale, parameters[P_UNIT]),
|
2016-11-17 21:27:19 +01:00
|
|
|
itoa36(u->no), unit_getname(u), u->number, get_money(u));
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
if (u->building && building_owner(u->building) == u) {
|
|
|
|
building *b = u->building;
|
2017-08-21 19:43:35 +02:00
|
|
|
if (!curse_active(get_curse(b->attribs, &ct_nocostbuilding))) {
|
2016-08-21 17:19:22 +02:00
|
|
|
int cost = buildingmaintenance(b, rsilver);
|
|
|
|
if (cost > 0) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ",U", size);
|
2016-08-21 17:19:22 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, itoa10(cost), size);
|
2016-08-21 17:19:22 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (u->ship) {
|
|
|
|
if (ship_owner(u->ship) == u) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ",S", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ",s", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, itoa36(u->ship->no), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
if (lifestyle(u) == 0) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ",I", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, "]", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
*bufp = 0;
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
for (ord = u->old_orders; ord; ord = ord->next) {
|
|
|
|
/* this new order will replace the old defaults */
|
|
|
|
strcpy(buf, " ");
|
2017-10-08 17:07:42 +02:00
|
|
|
write_order(ord, lang, buf + 2, sizeof(buf) - 2);
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
2015-08-04 22:47:55 +02:00
|
|
|
keyword_t kwd = getkeyword(ord);
|
|
|
|
if (u->old_orders && is_repeated(kwd))
|
2014-08-17 00:14:50 +02:00
|
|
|
continue; /* unit has defaults */
|
|
|
|
if (is_persistent(ord)) {
|
|
|
|
strcpy(buf, " ");
|
2017-10-08 17:07:42 +02:00
|
|
|
write_order(ord, lang, buf + 2, sizeof(buf) - 2);
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the lastorder begins with an @ it should have
|
|
|
|
* been printed in the loop before. */
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2017-12-30 19:49:21 +01:00
|
|
|
str_strlcpy(buf, LOC(lang, parameters[P_NEXT]), sizeof(buf));
|
2015-05-13 05:36:00 +02:00
|
|
|
rps_nowrap(out, buf);
|
|
|
|
newline(out);
|
|
|
|
fstream_done(&strm);
|
2014-08-17 00:14:50 +02:00
|
|
|
return 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-10-31 17:54:40 +01:00
|
|
|
static int count_allies_cb(struct allies *all, faction *af, int status, void *udata) {
|
2018-10-26 21:49:58 +02:00
|
|
|
int *num = (int *)udata;
|
|
|
|
if (status > 0) {
|
|
|
|
++*num;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2018-10-26 21:49:58 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2018-10-26 21:49:58 +02:00
|
|
|
struct show_s {
|
|
|
|
sbstring sbs;
|
2018-11-26 22:01:18 +01:00
|
|
|
stream *out;
|
2018-10-26 21:49:58 +02:00
|
|
|
const faction *f;
|
|
|
|
int num_allies;
|
2018-11-26 22:01:18 +01:00
|
|
|
int num_listed;
|
|
|
|
size_t maxlen;
|
2018-10-26 21:49:58 +02:00
|
|
|
};
|
|
|
|
|
2018-11-26 22:01:18 +01:00
|
|
|
void pump_paragraph(sbstring *sbp, stream *out, size_t maxlen, bool isfinal)
|
|
|
|
{
|
|
|
|
while (sbs_length(sbp) > maxlen) {
|
|
|
|
char *pos, *begin = sbp->begin;
|
|
|
|
while (*begin && isspace(*begin)) {
|
|
|
|
/* eat whitespace */
|
|
|
|
++begin;
|
|
|
|
}
|
|
|
|
pos = begin;
|
|
|
|
while (pos) {
|
|
|
|
char *next = strchr(pos+1, ' ');
|
|
|
|
if (next == NULL) {
|
|
|
|
if (isfinal) {
|
|
|
|
swrite(begin, 1, sbp->end - begin, out);
|
|
|
|
newline(out);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (next > begin + maxlen) {
|
|
|
|
size_t len = pos - begin;
|
|
|
|
swrite(begin, 1, len, out);
|
|
|
|
newline(out);
|
|
|
|
|
|
|
|
while (*pos && isspace(*pos)) {
|
|
|
|
++pos;
|
|
|
|
++len;
|
|
|
|
}
|
|
|
|
assert(len <= INT_MAX);
|
|
|
|
sbs_cut(sbp, (int)len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pos = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isfinal) {
|
|
|
|
char *pos = sbp->begin;
|
|
|
|
while (*pos && isspace(*pos)) {
|
|
|
|
/* eat whitespace */
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
swrite(pos, 1, sbp->end - pos, out);
|
|
|
|
newline(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-31 17:54:40 +01:00
|
|
|
static int show_allies_cb(struct allies *all, faction *af, int status, void *udata) {
|
2018-10-26 21:49:58 +02:00
|
|
|
struct show_s * show = (struct show_s *)udata;
|
|
|
|
const faction * f = show->f;
|
2018-11-26 22:01:18 +01:00
|
|
|
sbstring *sbp = &show->sbs;
|
2018-10-26 21:49:58 +02:00
|
|
|
int mode = alliance_status(f, af, status);
|
2018-11-26 22:01:18 +01:00
|
|
|
|
|
|
|
if (show->num_listed++ != 0) {
|
|
|
|
if (show->num_listed == show->num_allies) {
|
|
|
|
/* last entry */
|
|
|
|
sbs_strcat(sbp, LOC(f->locale, "list_and"));
|
2018-10-26 21:49:58 +02:00
|
|
|
}
|
|
|
|
else {
|
2018-11-26 22:01:18 +01:00
|
|
|
/* neither first entry nor last*/
|
|
|
|
sbs_strcat(sbp, ", ");
|
2018-10-26 21:49:58 +02:00
|
|
|
}
|
|
|
|
}
|
2018-11-26 22:01:18 +01:00
|
|
|
sbs_strcat(sbp, factionname(af));
|
|
|
|
sbs_strcat(sbp, " (");
|
2018-10-26 21:49:58 +02:00
|
|
|
if ((mode & HELP_ALL) == HELP_ALL) {
|
2018-11-26 22:01:18 +01:00
|
|
|
sbs_strcat(sbp, LOC(f->locale, parameters[P_ANY]));
|
2018-10-26 21:49:58 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int h, hh = 0;
|
|
|
|
for (h = 1; h <= HELP_TRAVEL; h *= 2) {
|
|
|
|
int p = MAXPARAMS;
|
|
|
|
if ((mode & h) == h) {
|
|
|
|
switch (h) {
|
|
|
|
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;
|
2018-10-26 14:13:00 +02:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-10-26 21:49:58 +02:00
|
|
|
if (p != MAXPARAMS) {
|
|
|
|
if (hh) {
|
2018-11-26 22:01:18 +01:00
|
|
|
sbs_strcat(sbp, ", ");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-11-26 22:01:18 +01:00
|
|
|
sbs_strcat(sbp, LOC(f->locale, parameters[p]));
|
2018-10-26 21:49:58 +02:00
|
|
|
hh = 1;
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-26 21:49:58 +02:00
|
|
|
}
|
2018-11-26 22:01:18 +01:00
|
|
|
if (show->num_allies == show->num_listed) {
|
|
|
|
sbs_strcat(sbp, ").");
|
|
|
|
pump_paragraph(sbp, show->out, show->maxlen, true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sbs_strcat(sbp, ")");
|
|
|
|
pump_paragraph(sbp, show->out, show->maxlen, false);
|
|
|
|
}
|
2018-10-26 21:49:58 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-26 22:01:18 +01:00
|
|
|
void report_allies(struct stream *out, size_t maxlen, const struct faction * f, struct allies * allies, const char *prefix)
|
2018-10-26 21:49:58 +02:00
|
|
|
{
|
|
|
|
int num_allies = 0;
|
2018-11-26 22:01:18 +01:00
|
|
|
|
|
|
|
assert(maxlen <= REPORTWIDTH);
|
2018-10-31 17:54:40 +01:00
|
|
|
allies_walk(allies, count_allies_cb, &num_allies);
|
2018-10-26 21:49:58 +02:00
|
|
|
|
|
|
|
if (num_allies > 0) {
|
|
|
|
struct show_s show;
|
2018-11-26 22:01:18 +01:00
|
|
|
char buf[REPORTWIDTH * 2];
|
2018-10-26 21:49:58 +02:00
|
|
|
show.f = f;
|
2018-11-26 22:01:18 +01:00
|
|
|
show.out = out;
|
2018-10-26 21:49:58 +02:00
|
|
|
show.num_allies = num_allies;
|
2018-11-26 22:01:18 +01:00
|
|
|
show.num_listed = 0;
|
|
|
|
show.maxlen = maxlen;
|
|
|
|
sbs_init(&show.sbs, buf, sizeof(buf));
|
|
|
|
sbs_strcpy(&show.sbs, prefix);
|
2018-10-26 21:49:58 +02:00
|
|
|
|
2018-10-31 17:54:40 +01:00
|
|
|
allies_walk(allies, show_allies_cb, &show);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void allies(struct stream *out, const faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
const group *g = f->groups;
|
2018-11-26 22:01:18 +01:00
|
|
|
char prefix[64];
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
if (f->allies) {
|
2018-11-26 22:01:18 +01:00
|
|
|
snprintf(prefix, sizeof(prefix), "%s ", LOC(f->locale, "faction_help"));
|
|
|
|
report_allies(out, REPORTWIDTH, f, f->allies, prefix);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
while (g) {
|
|
|
|
if (g->allies) {
|
2018-11-26 22:01:18 +01:00
|
|
|
snprintf(prefix, sizeof(prefix), "%s %s ", g->name, LOC(f->locale, "group_help"));
|
|
|
|
report_allies(out, REPORTWIDTH, f, g->allies, prefix);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
g = g->next;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void guards(struct stream *out, const region * r, const faction * see)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
/* die Partei see sieht dies; wegen
|
|
|
|
* "unbekannte Partei", wenn man es selbst ist... */
|
|
|
|
faction *guardians[512];
|
|
|
|
int nextguard = 0;
|
|
|
|
unit *u;
|
|
|
|
int i;
|
|
|
|
bool tarned = false;
|
|
|
|
/* Bewachung */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
for (u = r->units; u; u = u->next) {
|
2016-10-31 07:45:06 +01:00
|
|
|
if (is_guard(u) != 0) {
|
2014-08-17 00:14:50 +02:00
|
|
|
faction *f = u->faction;
|
|
|
|
faction *fv = visible_faction(see, u);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (fv != f && see != fv) {
|
|
|
|
f = fv;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (f != see && fval(u, UFL_ANON_FACTION)) {
|
|
|
|
tarned = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (i = 0; i != nextguard; ++i)
|
|
|
|
if (guardians[i] == f)
|
|
|
|
break;
|
|
|
|
if (i == nextguard) {
|
|
|
|
guardians[nextguard++] = f;
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (nextguard || tarned) {
|
|
|
|
char buf[8192];
|
|
|
|
char *bufp = buf;
|
|
|
|
size_t size = sizeof(buf) - 1;
|
|
|
|
int bytes;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(see->locale, "nr_guarding_prefix"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
for (i = 0; i != nextguard + (tarned ? 1 : 0); ++i) {
|
|
|
|
if (i != 0) {
|
|
|
|
if (i == nextguard - (tarned ? 0 : 1)) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(see->locale, "list_and"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ", ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
if (i < nextguard) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, factionname(guardians[i]), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(see->locale, "nr_guarding_unknown"), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(see->locale, "nr_guarding_postfix"), size);
|
2011-03-07 08:02:35 +01:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
2014-08-17 00:14:50 +02:00
|
|
|
WARN_STATIC_BUFFER();
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
*bufp = 0;
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void rpline(struct stream *out)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
static char line[REPORTWIDTH + 1];
|
|
|
|
if (line[0] != '-') {
|
|
|
|
memset(line, '-', sizeof(line));
|
|
|
|
line[REPORTWIDTH] = '\n';
|
|
|
|
}
|
2016-11-20 19:08:39 +01:00
|
|
|
swrite(line, sizeof(line), 1, out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
2017-01-26 17:41:21 +01:00
|
|
|
static void list_address(struct stream *out, const faction * uf, selist * seenfactions)
|
2014-08-17 00:14:50 +02:00
|
|
|
{
|
|
|
|
int qi = 0;
|
2017-01-26 17:41:21 +01:00
|
|
|
selist *flist = seenfactions;
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, LOC(uf->locale, "nr_addresses"), false);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
while (flist != NULL) {
|
2017-01-26 17:41:21 +01:00
|
|
|
const faction *f = (const faction *)selist_get(flist, qi);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (!is_monsters(f)) {
|
2018-10-24 19:54:07 +02:00
|
|
|
const char *str;
|
2014-08-17 00:14:50 +02:00
|
|
|
char buf[8192];
|
|
|
|
char label = '-';
|
|
|
|
|
2018-10-24 19:54:07 +02:00
|
|
|
str = faction_getbanner(f);
|
2017-11-14 16:20:31 +01:00
|
|
|
sprintf(buf, "%s: %s; %s", factionname(f), faction_getemail(f),
|
2018-10-24 19:54:07 +02:00
|
|
|
str ? str : "");
|
2014-08-17 00:14:50 +02:00
|
|
|
if (uf == f)
|
|
|
|
label = '*';
|
2018-10-26 19:47:50 +02:00
|
|
|
else if (is_allied(uf, f)) {
|
2014-08-17 00:14:50 +02:00
|
|
|
label = 'o';
|
2018-10-26 19:47:50 +02:00
|
|
|
}
|
|
|
|
else if (alliedfaction(uf, f, HELP_ALL))
|
2014-08-17 00:14:50 +02:00
|
|
|
label = '+';
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 4, 0, label);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2017-01-26 17:41:21 +01:00
|
|
|
selist_advance(&flist, &qi, 1);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
rpline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
nr_ship(struct stream *out, const region *r, const ship * sh, const faction * f,
|
2016-09-16 18:03:28 +02:00
|
|
|
const unit * captain)
|
2014-08-17 00:14:50 +02:00
|
|
|
{
|
|
|
|
char buffer[8192], *bufp = buffer;
|
|
|
|
size_t size = sizeof(buffer) - 1;
|
|
|
|
int bytes;
|
|
|
|
char ch;
|
|
|
|
|
2015-05-13 04:57:08 +02:00
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
|
|
|
if (captain && captain->faction == f) {
|
|
|
|
int n = 0, p = 0;
|
|
|
|
getshipweight(sh, &n, &p);
|
|
|
|
n = (n + 99) / 100; /* 1 Silber = 1 GE */
|
|
|
|
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, "%s, %s, (%d/%d)", shipname(sh),
|
2014-08-17 00:14:50 +02:00
|
|
|
LOC(f->locale, sh->type->_name), n, shipcapacity(sh) / 100);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bytes =
|
2017-01-10 16:31:05 +01:00
|
|
|
snprintf(bufp, size, "%s, %s", shipname(sh), LOC(f->locale,
|
2016-09-16 18:03:28 +02:00
|
|
|
sh->type->_name));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
if (sh->size != sh->type->construction->maxsize) {
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, ", %s (%d/%d)",
|
2014-08-17 00:14:50 +02:00
|
|
|
LOC(f->locale, "nr_undercons"), sh->size,
|
|
|
|
sh->type->construction->maxsize);
|
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
if (sh->damage) {
|
2015-11-17 15:47:43 +01:00
|
|
|
int percent = ship_damage_percent(sh);
|
2014-08-17 00:14:50 +02:00
|
|
|
bytes =
|
2017-01-10 16:31:05 +01:00
|
|
|
snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
if (!fval(r->terrain, SEA_REGION)) {
|
|
|
|
if (sh->coast != NODIRECTION) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ", ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, coasts[sh->coast]), size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ch = 0;
|
|
|
|
if (sh->display && sh->display[0]) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, "; ", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, sh->display, size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
ch = sh->display[strlen(sh->display) - 1];
|
|
|
|
}
|
|
|
|
if (ch != '!' && ch != '?' && ch != '.') {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ".", size);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
|
|
|
*bufp = 0;
|
2015-05-13 04:57:08 +02:00
|
|
|
paragraph(out, buffer, 2, 0, 0);
|
2014-08-17 00:14:50 +02:00
|
|
|
|
2015-05-13 04:25:50 +02:00
|
|
|
nr_curses(out, 4, f, TYP_SHIP, sh);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
static void
|
2016-11-13 19:40:38 +01:00
|
|
|
nr_building(struct stream *out, const region *r, const building *b, const faction *f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-06-09 21:22:02 +02:00
|
|
|
int i;
|
2014-08-17 00:14:50 +02:00
|
|
|
const char *name, *bname, *billusion = NULL;
|
2015-11-04 12:14:12 +01:00
|
|
|
const struct locale *lang;
|
2018-06-09 21:22:02 +02:00
|
|
|
char buffer[8192];
|
|
|
|
size_t size;
|
|
|
|
sbstring sbs;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-11-04 12:14:12 +01:00
|
|
|
assert(f);
|
|
|
|
lang = f->locale;
|
2015-05-13 04:57:08 +02:00
|
|
|
newline(out);
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_init(&sbs, buffer, sizeof(buffer));
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
report_building(b, &bname, &billusion);
|
2018-06-09 21:22:02 +02:00
|
|
|
|
|
|
|
size = str_slprintf(buffer, sizeof(buffer), "%s, %s %d, ", buildingname(b),
|
|
|
|
LOC(lang, "nr_size"), b->size);
|
|
|
|
sbs.end += size;
|
2014-08-17 00:14:50 +02:00
|
|
|
name = LOC(lang, billusion ? billusion : bname);
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_strcat(&sbs, name);
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (billusion) {
|
|
|
|
unit *owner = building_owner(b);
|
|
|
|
if (owner && owner->faction == f) {
|
|
|
|
/* illusion. report real type */
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_strcat(&sbs, " (");
|
|
|
|
sbs_strcat(&sbs, LOC(lang, bname));
|
|
|
|
sbs_strcat(&sbs, ")");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-08-06 13:52:29 +02:00
|
|
|
if (!building_finished(b)) {
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_strcat(&sbs, " ");
|
|
|
|
sbs_strcat(&sbs, LOC(lang, "nr_building_inprogress"));
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
i = 0;
|
|
|
|
if (b->display && b->display[0]) {
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_strcat(&sbs, "; ");
|
|
|
|
sbs_strcat(&sbs, b->display);
|
2014-08-17 00:14:50 +02:00
|
|
|
i = b->display[strlen(b->display) - 1];
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2014-08-17 00:14:50 +02:00
|
|
|
if (i != '!' && i != '?' && i != '.') {
|
2018-06-09 21:22:02 +02:00
|
|
|
sbs_strcat(&sbs, ".");
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-05-13 04:57:08 +02:00
|
|
|
paragraph(out, buffer, 2, 0, 0);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
if (r->seen.mode >= seen_lighthouse) {
|
|
|
|
nr_curses(out, 4, f, TYP_BUILDING, b);
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void nr_paragraph(struct stream *out, message * m, faction * f)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-06-09 21:22:02 +02:00
|
|
|
char buf[4096];
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-11-04 12:14:12 +01:00
|
|
|
assert(f);
|
2018-06-09 21:22:02 +02:00
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
2014-08-17 00:14:50 +02:00
|
|
|
msg_release(m);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
paragraph(out, buf, 0, 0, 0);
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2015-08-19 14:37:51 +02:00
|
|
|
typedef struct cb_data {
|
2016-11-13 19:40:38 +01:00
|
|
|
struct stream *out;
|
2018-04-28 15:57:51 +02:00
|
|
|
char *handle_start, *writep;
|
2015-08-19 14:37:51 +02:00
|
|
|
size_t size;
|
|
|
|
const faction *f;
|
|
|
|
int maxtravel, counter;
|
|
|
|
} cb_data;
|
|
|
|
|
2016-11-13 19:40:38 +01:00
|
|
|
static void init_cb(cb_data *data, struct stream *out, char *buffer, size_t size, const faction *f) {
|
2015-08-19 14:37:51 +02:00
|
|
|
data->out = out;
|
|
|
|
data->writep = buffer;
|
2018-04-28 15:57:51 +02:00
|
|
|
data->handle_start = buffer;
|
2015-08-19 14:37:51 +02:00
|
|
|
data->size = size;
|
|
|
|
data->f = f;
|
|
|
|
data->maxtravel = 0;
|
|
|
|
data->counter = 0;
|
|
|
|
}
|
|
|
|
|
2016-09-17 08:28:33 +02:00
|
|
|
static void cb_write_travelthru(region *r, unit *u, void *cbdata) {
|
2015-08-19 14:37:51 +02:00
|
|
|
cb_data *data = (cb_data *)cbdata;
|
|
|
|
const faction *f = data->f;
|
|
|
|
|
|
|
|
if (data->counter >= data->maxtravel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (travelthru_cansee(r, f, u)) {
|
|
|
|
++data->counter;
|
|
|
|
do {
|
2018-04-28 15:57:51 +02:00
|
|
|
size_t len, size = data->size - (data->writep - data->handle_start);
|
2015-08-19 14:37:51 +02:00
|
|
|
const char *str;
|
|
|
|
char *writep = data->writep;
|
|
|
|
|
|
|
|
if (u->ship != NULL) {
|
|
|
|
str = shipname(u->ship);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
str = unitname(u);
|
|
|
|
}
|
|
|
|
len = strlen(str);
|
|
|
|
if (len < size && data->counter <= data->maxtravel) {
|
|
|
|
memcpy(writep, str, len);
|
|
|
|
writep += len;
|
|
|
|
size -= len;
|
|
|
|
if (data->counter == data->maxtravel) {
|
|
|
|
str = ".";
|
|
|
|
}
|
|
|
|
else if (data->counter + 1 == data->maxtravel) {
|
|
|
|
str = LOC(f->locale, "list_and");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
str = ", ";
|
|
|
|
}
|
|
|
|
len = strlen(str);
|
|
|
|
if (len < size) {
|
|
|
|
memcpy(writep, str, len);
|
|
|
|
writep += len;
|
|
|
|
size -= len;
|
|
|
|
data->writep = writep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (len >= size || data->counter == data->maxtravel) {
|
2017-02-18 21:15:14 +01:00
|
|
|
/* buffer is full */
|
2015-08-19 14:37:51 +02:00
|
|
|
*writep = 0;
|
2018-04-28 15:57:51 +02:00
|
|
|
paragraph(data->out, data->handle_start, 0, 0, 0);
|
|
|
|
data->writep = data->handle_start;
|
2015-08-19 14:37:51 +02:00
|
|
|
if (data->counter == data->maxtravel) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-04-28 15:57:51 +02:00
|
|
|
} while (data->writep == data->handle_start);
|
2015-08-19 14:37:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 16:55:11 +01:00
|
|
|
void report_travelthru(struct stream *out, region *r, const faction *f)
|
2015-08-19 14:37:51 +02:00
|
|
|
{
|
|
|
|
int maxtravel;
|
|
|
|
char buf[8192];
|
|
|
|
|
|
|
|
assert(r);
|
|
|
|
assert(f);
|
|
|
|
if (!fval(r, RF_TRAVELUNIT)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* How many are we listing? For grammar. */
|
|
|
|
maxtravel = count_travelthru(r, f);
|
|
|
|
if (maxtravel > 0) {
|
|
|
|
cb_data cbdata;
|
|
|
|
|
|
|
|
init_cb(&cbdata, out, buf, sizeof(buf), f);
|
|
|
|
cbdata.maxtravel = maxtravel;
|
2016-09-16 18:03:28 +02:00
|
|
|
cbdata.writep +=
|
2017-12-30 19:49:21 +01:00
|
|
|
str_strlcpy(buf, LOC(f->locale, "travelthru_header"), sizeof(buf));
|
2015-08-19 14:37:51 +02:00
|
|
|
travelthru_map(r, cb_write_travelthru, &cbdata);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
int
|
2011-03-07 08:02:35 +01:00
|
|
|
report_plaintext(const char *filename, report_context * ctx,
|
2016-11-25 20:15:11 +01:00
|
|
|
const char *bom)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
int flag = 0;
|
|
|
|
char ch;
|
|
|
|
int anyunits, no_units, no_people;
|
2016-09-17 08:28:33 +02:00
|
|
|
region *r;
|
2014-08-17 00:14:50 +02:00
|
|
|
faction *f = ctx->f;
|
|
|
|
unit *u;
|
|
|
|
char pzTime[64];
|
|
|
|
attrib *a;
|
|
|
|
message *m;
|
|
|
|
unsigned char op;
|
2018-02-03 14:49:35 +01:00
|
|
|
int maxh, bytes, ix = WANT_OPTION(O_STATISTICS);
|
2014-08-17 00:14:50 +02:00
|
|
|
int wants_stats = (f->options & ix);
|
2016-02-05 23:10:05 +01:00
|
|
|
FILE *F = fopen(filename, "w");
|
2015-05-13 05:36:00 +02:00
|
|
|
stream strm = { 0 }, *out = &strm;
|
2014-08-17 00:14:50 +02:00
|
|
|
char buf[8192];
|
|
|
|
char *bufp;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
if (F == NULL) {
|
|
|
|
perror(filename);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
fstream_init(&strm, F);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
2016-11-25 20:15:11 +01:00
|
|
|
if (bom) {
|
|
|
|
fwrite(bom, 1, strlen(bom), F);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
strftime(pzTime, 64, "%A, %d. %B %Y, %H:%M", localtime(&ctx->report_time));
|
|
|
|
m = msg_message("nr_header_date", "game date", game_name(), pzTime);
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, gamedate_season(f->locale), true);
|
|
|
|
newline(out);
|
2014-08-17 00:14:50 +02:00
|
|
|
sprintf(buf, "%s, %s/%s (%s)", factionname(f),
|
2014-12-09 07:20:36 +01:00
|
|
|
LOC(f->locale, rc_name_s(f->race, NAME_PLURAL)),
|
2018-11-24 12:26:52 +01:00
|
|
|
magic_name(f->magiegebiet, f->locale), faction_getemail(f));
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (f_get_alliance(f)) {
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, alliancename(f->alliance), true);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (f->age <= 2) {
|
2017-01-22 20:19:32 +01:00
|
|
|
const char *email;
|
|
|
|
const char *subject;
|
|
|
|
email = config_get("game.email");
|
2017-11-14 16:20:31 +01:00
|
|
|
if (!email)
|
|
|
|
log_error("game.email not set");
|
|
|
|
else {
|
|
|
|
subject = get_mailcmd(f->locale);
|
|
|
|
|
|
|
|
m = msg_message("newbie_info_game", "email subject", email, subject);
|
|
|
|
if (m) {
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
|
|
|
centre(out, buf, true);
|
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-02-03 14:49:35 +01:00
|
|
|
if ((f->options & WANT_OPTION(O_COMPUTER)) == 0) {
|
2017-01-22 20:19:32 +01:00
|
|
|
const char *s;
|
2016-09-11 16:35:55 +02:00
|
|
|
s = locale_getstring(f->locale, "newbie_info_cr");
|
2014-08-17 00:14:50 +02:00
|
|
|
if (s) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, s, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2018-02-03 14:49:35 +01:00
|
|
|
f->options |= WANT_OPTION(O_COMPUTER);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2018-02-03 14:49:35 +01:00
|
|
|
if (f->options & WANT_OPTION(O_SCORE) && f->age > DISPLAYSCORE) {
|
2015-09-06 19:04:04 +02:00
|
|
|
char score[32], avg[32];
|
|
|
|
write_score(score, sizeof(score), f->score);
|
|
|
|
write_score(avg, sizeof(avg), average_score_of_age(f->age, f->age / 24 + 1));
|
|
|
|
RENDER(f, buf, sizeof(buf), ("nr_score", "score average", score, avg));
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2017-03-11 19:36:26 +01:00
|
|
|
no_units = f->num_units;
|
|
|
|
no_people = f->num_people;
|
2014-12-19 19:57:24 +01:00
|
|
|
m = msg_message("nr_population", "population units limit", no_people, no_units, rule_faction_limit());
|
2010-08-08 10:06:34 +02:00
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
if (f->race == get_race(RC_HUMAN)) {
|
|
|
|
int maxmig = count_maxmigrants(f);
|
|
|
|
if (maxmig > 0) {
|
|
|
|
m =
|
|
|
|
msg_message("nr_migrants", "units maxunits", count_migrants(f), maxmig);
|
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2014-08-17 00:14:50 +02:00
|
|
|
if (f_get_alliance(f)) {
|
|
|
|
m =
|
|
|
|
msg_message("nr_alliance", "leader name id age",
|
2016-09-16 18:03:28 +02:00
|
|
|
alliance_get_leader(f->alliance), f->alliance->name, f->alliance->id,
|
|
|
|
turn - f->alliance_joindate);
|
2014-08-17 00:14:50 +02:00
|
|
|
nr_render(m, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(m);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2014-08-17 00:14:50 +02:00
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
maxh = maxheroes(f);
|
|
|
|
if (maxh) {
|
|
|
|
message *msg =
|
|
|
|
msg_message("nr_heroes", "units maxunits", countheroes(f), maxh);
|
|
|
|
nr_render(msg, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(msg);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (f->items != NULL) {
|
|
|
|
message *msg = msg_message("nr_claims", "items", f->items);
|
|
|
|
nr_render(msg, f->locale, buf, sizeof(buf), f);
|
|
|
|
msg_release(msg);
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, buf, true);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bufp = buf;
|
|
|
|
size = sizeof(buf) - 1;
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(buf, size, "%s:", LOC(f->locale, "nr_options"));
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
for (op = 0; op != MAXOPTIONS; op++) {
|
2018-02-03 14:49:35 +01:00
|
|
|
if (f->options & WANT_OPTION(op) && options[op]) {
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, " ", size);
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, LOC(f->locale, options[op]), size);
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
|
|
|
flag++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flag > 0) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2015-05-13 04:25:50 +02:00
|
|
|
*bufp = 0;
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
rp_messages(out, f->msgs, f, 0, true);
|
|
|
|
rp_battles(out, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
a = a_find(f->attribs, &at_reportspell);
|
|
|
|
if (a) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, LOC(f->locale, "section_newspells"), true);
|
2015-05-13 04:25:50 +02:00
|
|
|
while (a && a->type == &at_reportspell) {
|
|
|
|
spellbook_entry *sbe = (spellbook_entry *)a->data.v;
|
2015-05-13 05:36:00 +02:00
|
|
|
nr_spell(out, sbe, f->locale);
|
2015-05-13 04:25:50 +02:00
|
|
|
a = a->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ch = 0;
|
2018-05-03 22:40:54 +02:00
|
|
|
ERRNO_CHECK();
|
2015-05-13 04:25:50 +02:00
|
|
|
for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;
|
|
|
|
a = a->next) {
|
2018-01-12 09:17:01 +01:00
|
|
|
const item_type *itype = (const item_type *)a->data.v;
|
2015-05-13 04:25:50 +02:00
|
|
|
const char *description = NULL;
|
2018-01-12 09:17:01 +01:00
|
|
|
if (itype) {
|
|
|
|
const char *pname = resourcename(itype->rtype, 0);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
|
|
|
if (ch == 0) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, LOC(f->locale, "section_newpotions"), true);
|
2015-05-13 04:25:50 +02:00
|
|
|
ch = 1;
|
|
|
|
}
|
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
centre(out, LOC(f->locale, pname), true);
|
2017-01-10 16:31:05 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"),
|
2018-01-12 09:17:01 +01:00
|
|
|
potion_level(itype));
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
|
|
|
newline(out);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
|
|
|
bufp = buf;
|
|
|
|
size = sizeof(buf) - 1;
|
2017-01-10 16:31:05 +01:00
|
|
|
bytes = snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_herbsrequired"));
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
|
2018-01-12 09:17:01 +01:00
|
|
|
if (itype->construction) {
|
|
|
|
requirement *rm = itype->construction->materials;
|
2017-12-29 06:13:28 +01:00
|
|
|
while (rm->number) {
|
2015-05-13 04:25:50 +02:00
|
|
|
bytes =
|
2017-12-30 19:49:21 +01:00
|
|
|
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size);
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
2017-12-31 16:36:59 +01:00
|
|
|
++rm;
|
2017-12-29 06:13:28 +01:00
|
|
|
if (rm->number)
|
2017-12-30 19:49:21 +01:00
|
|
|
bytes = (int)str_strlcpy(bufp, ", ", size);
|
2015-05-13 04:25:50 +02:00
|
|
|
if (wrptr(&bufp, &size, bytes) != 0)
|
|
|
|
WARN_STATIC_BUFFER();
|
|
|
|
}
|
2018-07-31 10:12:54 +02:00
|
|
|
assert(!rm->rtype);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
*bufp = 0;
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, buf, true);
|
|
|
|
newline(out);
|
2018-03-11 09:02:02 +01:00
|
|
|
description = mkname("describe", pname);
|
2016-11-23 18:56:40 +01:00
|
|
|
description = LOC(f->locale, description);
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, description, true);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
2018-05-03 22:40:54 +02:00
|
|
|
ERRNO_CHECK();
|
2015-05-13 05:36:00 +02:00
|
|
|
centre(out, LOC(f->locale, "nr_alliances"), false);
|
|
|
|
newline(out);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
allies(out, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
rpline(out);
|
2015-05-13 04:25:50 +02:00
|
|
|
|
2018-05-03 22:40:54 +02:00
|
|
|
ERRNO_CHECK();
|
2015-05-13 04:25:50 +02:00
|
|
|
anyunits = 0;
|
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
for (r = ctx->first; r != ctx->last; r = r->next) {
|
2017-10-10 20:09:39 +02:00
|
|
|
int stealthmod = stealth_modifier(r, f, r->seen.mode);
|
2015-05-13 04:25:50 +02:00
|
|
|
building *b = r->buildings;
|
|
|
|
ship *sh = r->ships;
|
|
|
|
|
2016-09-16 18:03:28 +02:00
|
|
|
if (r->seen.mode < seen_lighthouse)
|
2015-05-13 04:25:50 +02:00
|
|
|
continue;
|
|
|
|
/* Beschreibung */
|
|
|
|
|
2016-09-25 13:01:51 +02:00
|
|
|
if (r->seen.mode >= seen_unit) {
|
2015-05-13 04:25:50 +02:00
|
|
|
anyunits = 1;
|
2017-03-05 16:55:11 +01:00
|
|
|
newline(out);
|
|
|
|
report_region(out, r, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
if (markets_module() && r->land) {
|
|
|
|
const item_type *lux = r_luxury(r);
|
|
|
|
const item_type *herb = r->land->herbtype;
|
2017-12-29 06:13:28 +01:00
|
|
|
|
|
|
|
m = NULL;
|
2015-05-13 04:25:50 +02:00
|
|
|
if (herb && lux) {
|
|
|
|
m = msg_message("nr_market_info_p", "p1 p2",
|
2015-11-04 12:15:25 +01:00
|
|
|
lux->rtype, herb->rtype);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
2018-02-26 19:48:52 +01:00
|
|
|
else if (lux) {
|
|
|
|
m = msg_message("nr_market_info_s", "p1",lux->rtype);
|
|
|
|
}
|
|
|
|
else if (herb) {
|
|
|
|
m = msg_message("nr_market_info_s", "p1", herb->rtype);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
if (m) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
nr_paragraph(out, m, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!fval(r->terrain, SEA_REGION) && rpeasants(r) / TRADE_FRACTION > 0) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
prices(out, r, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
guards(out, r, f);
|
2015-08-18 18:57:04 +02:00
|
|
|
newline(out);
|
2017-03-05 16:55:11 +01:00
|
|
|
report_travelthru(out, r, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-05-21 21:33:29 +02:00
|
|
|
report_region(out, r, f);
|
2016-09-25 13:01:51 +02:00
|
|
|
newline(out);
|
2017-05-21 21:33:29 +02:00
|
|
|
report_travelthru(out, r, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
|
2018-06-11 20:42:28 +02:00
|
|
|
if (wants_stats && r->seen.mode >= seen_unit) {
|
2015-05-13 05:36:00 +02:00
|
|
|
statistics(out, r, f);
|
2018-06-11 20:42:28 +02:00
|
|
|
newline(out);
|
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
|
|
|
|
/* Nachrichten an REGION in der Region */
|
2017-10-10 20:09:39 +02:00
|
|
|
if (r->seen.mode >= seen_travel) {
|
2015-05-13 04:25:50 +02:00
|
|
|
message_list *mlist = r_getmessages(r, f);
|
2015-08-16 11:30:44 +02:00
|
|
|
if (mlist) {
|
|
|
|
struct mlist **split = merge_messages(mlist, r->msgs);
|
2018-05-20 17:11:29 +02:00
|
|
|
rp_messages(out, mlist, f, 0, false);
|
2015-08-16 11:30:44 +02:00
|
|
|
split_messages(mlist, split);
|
|
|
|
}
|
|
|
|
else {
|
2018-05-20 17:11:29 +02:00
|
|
|
rp_messages(out, r->msgs, f, 0, false);
|
2015-08-16 11:30:44 +02:00
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* report all units. they are pre-sorted in an efficient manner */
|
|
|
|
u = r->units;
|
|
|
|
while (b) {
|
|
|
|
while (b && (!u || u->building != b)) {
|
2016-09-16 18:03:28 +02:00
|
|
|
nr_building(out, r, b, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
b = b->next;
|
|
|
|
}
|
|
|
|
if (b) {
|
2016-09-16 18:03:28 +02:00
|
|
|
nr_building(out, r, b, f);
|
2015-05-13 04:25:50 +02:00
|
|
|
while (u && u->building == b) {
|
2018-03-11 14:40:38 +01:00
|
|
|
if (visible_unit(u, f, stealthmod, r->seen.mode)) {
|
|
|
|
nr_unit(out, f, u, 6, r->seen.mode);
|
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
u = u->next;
|
|
|
|
}
|
|
|
|
b = b->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (u && !u->ship) {
|
2017-12-23 17:49:30 +01:00
|
|
|
if (visible_unit(u, f, stealthmod, r->seen.mode)) {
|
2017-12-23 17:37:24 +01:00
|
|
|
nr_unit(out, f, u, 4, r->seen.mode);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
assert(!u->building);
|
|
|
|
u = u->next;
|
|
|
|
}
|
|
|
|
while (sh) {
|
|
|
|
while (sh && (!u || u->ship != sh)) {
|
2016-09-16 18:03:28 +02:00
|
|
|
nr_ship(out, r, sh, f, NULL);
|
2015-05-13 04:25:50 +02:00
|
|
|
sh = sh->next;
|
|
|
|
}
|
|
|
|
if (sh) {
|
2016-09-16 18:03:28 +02:00
|
|
|
nr_ship(out, r, sh, f, u);
|
2015-05-13 04:25:50 +02:00
|
|
|
while (u && u->ship == sh) {
|
2018-03-11 14:40:38 +01:00
|
|
|
if (visible_unit(u, f, stealthmod, r->seen.mode)) {
|
|
|
|
nr_unit(out, f, u, 6, r->seen.mode);
|
|
|
|
}
|
2015-05-13 04:25:50 +02:00
|
|
|
u = u->next;
|
|
|
|
}
|
|
|
|
sh = sh->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!u);
|
|
|
|
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
rpline(out);
|
2018-05-03 22:40:54 +02:00
|
|
|
ERRNO_CHECK();
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
if (!is_monsters(f)) {
|
|
|
|
if (!anyunits) {
|
2015-05-13 05:36:00 +02:00
|
|
|
newline(out);
|
|
|
|
paragraph(out, LOC(f->locale, "nr_youaredead"), 0, 2, 0);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
else {
|
2015-05-13 05:36:00 +02:00
|
|
|
list_address(out, f, ctx->addresses);
|
2015-05-13 04:25:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-05-13 05:36:00 +02:00
|
|
|
fstream_done(&strm);
|
2018-05-03 22:40:54 +02:00
|
|
|
ERRNO_CHECK();
|
2015-05-13 04:25:50 +02:00
|
|
|
return 0;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define FMAXHASH 1021
|
|
|
|
|
|
|
|
struct fsee {
|
2014-08-17 00:14:50 +02:00
|
|
|
struct fsee *nexthash;
|
|
|
|
faction *f;
|
|
|
|
struct see {
|
|
|
|
struct see *next;
|
|
|
|
faction *seen;
|
|
|
|
unit *proof;
|
|
|
|
} *see;
|
2011-03-07 08:02:35 +01:00
|
|
|
} *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
|
|
|
void register_nr(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2014-08-17 00:14:50 +02: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
|
|
|
{
|
2014-08-17 00:14:50 +02:00
|
|
|
int i;
|
|
|
|
for (i = 0; i != FMAXHASH; ++i) {
|
|
|
|
while (fsee[i]) {
|
|
|
|
struct fsee *fs = fsee[i]->nexthash;
|
|
|
|
free(fsee[i]);
|
|
|
|
fsee[i] = fs;
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|