2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-04-16 16:34:19 +02:00
|
|
|
|
*
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2000
|
|
|
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
|
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
|
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
|
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
|
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
|
|
|
*
|
|
|
|
|
* This program may not be used, modified or distributed without
|
|
|
|
|
* prior permission by the authors of Eressea.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define FAST_SEEN 0
|
|
|
|
|
#define INDENT 0
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
2001-02-10 11:40:12 +01:00
|
|
|
|
#include <eressea.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-02-10 11:40:12 +01:00
|
|
|
|
/* modules includes */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <modules/score.h>
|
|
|
|
|
|
2001-02-10 11:40:12 +01:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/overrideroads.h>
|
2001-04-14 14:11:45 +02:00
|
|
|
|
#include <attributes/otherfaction.h>
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
|
|
|
|
# include <attributes/option.h>
|
|
|
|
|
#endif
|
2001-02-10 11:40:12 +01:00
|
|
|
|
|
|
|
|
|
/* gamecode includes */
|
|
|
|
|
#include "creation.h"
|
|
|
|
|
#include "economy.h"
|
|
|
|
|
#include "monster.h"
|
|
|
|
|
#include "laws.h"
|
|
|
|
|
|
|
|
|
|
/* kernel includes */
|
|
|
|
|
#include <alchemy.h>
|
|
|
|
|
#include <border.h>
|
|
|
|
|
#include <build.h>
|
|
|
|
|
#include <building.h>
|
|
|
|
|
#include <faction.h>
|
|
|
|
|
#include <group.h>
|
|
|
|
|
#include <item.h>
|
|
|
|
|
#include <karma.h>
|
|
|
|
|
#include <magic.h>
|
|
|
|
|
#include <message.h>
|
|
|
|
|
#include <movement.h>
|
|
|
|
|
#include <objtypes.h>
|
|
|
|
|
#include <plane.h>
|
|
|
|
|
#include <pool.h>
|
|
|
|
|
#include <race.h>
|
|
|
|
|
#include <region.h>
|
|
|
|
|
#include <reports.h>
|
|
|
|
|
#include <save.h>
|
|
|
|
|
#include <ship.h>
|
|
|
|
|
#include <skill.h>
|
|
|
|
|
#include <teleport.h>
|
|
|
|
|
#include <unit.h>
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* util includes */
|
2001-02-10 11:40:12 +01:00
|
|
|
|
#include <goodies.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <base36.h>
|
2001-02-24 13:50:51 +01:00
|
|
|
|
#include <nrmessage.h>
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
#include <translation.h>
|
2001-02-24 13:50:51 +01:00
|
|
|
|
#include <util/message.h>
|
2001-04-14 14:11:45 +02:00
|
|
|
|
#include <log.h>
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
extern int quiet;
|
|
|
|
|
|
|
|
|
|
boolean nocr = false;
|
|
|
|
|
boolean nonr = false;
|
|
|
|
|
boolean nomer = false;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* -------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
extern int *storms;
|
|
|
|
|
|
|
|
|
|
char **seasonnames;
|
|
|
|
|
char **weeknames;
|
|
|
|
|
char **weeknames2;
|
|
|
|
|
char **monthnames;
|
|
|
|
|
int *season;
|
|
|
|
|
char *agename;
|
|
|
|
|
int seasons;
|
|
|
|
|
extern int weeks_per_month;
|
|
|
|
|
extern int months_per_year;
|
|
|
|
|
|
2001-02-05 17:11:59 +01:00
|
|
|
|
int
|
|
|
|
|
read_datenames(const char *filename)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
FILE *namesFP;
|
|
|
|
|
char line[256];
|
|
|
|
|
int i, l;
|
|
|
|
|
|
|
|
|
|
if( (namesFP=fopen(filename,"r")) == NULL) {
|
2001-04-14 14:11:45 +02:00
|
|
|
|
log_error(("Kann Datei '%s' nicht <20>ffnen, Abbruch\n", filename));
|
2001-02-05 17:11:59 +01:00
|
|
|
|
return -1;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
l = strlen(line)-1;
|
|
|
|
|
if(line[l] == '\n') line[l] = 0;
|
|
|
|
|
agename = strdup(line);
|
|
|
|
|
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
seasons = strtol(line, NULL, 10);
|
|
|
|
|
seasonnames = malloc(sizeof(char *) * seasons);
|
|
|
|
|
|
2001-02-05 17:11:59 +01:00
|
|
|
|
for (i=0;i<seasons;i++) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
l = strlen(line)-1;
|
|
|
|
|
if(line[l] == '\n') line[l] = 0;
|
|
|
|
|
seasonnames[i] = strdup(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
weeks_per_month = strtol(line, NULL, 10);
|
|
|
|
|
weeknames = malloc(sizeof(char *) * weeks_per_month);
|
|
|
|
|
weeknames2 = malloc(sizeof(char *) * weeks_per_month);
|
|
|
|
|
|
|
|
|
|
for(i=0;i<weeks_per_month;i++) {
|
|
|
|
|
char * np;
|
|
|
|
|
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
l = strlen(line)-1;
|
|
|
|
|
if(line[l] == '\n') line[l] = 0;
|
|
|
|
|
|
|
|
|
|
np = strtok(line,":");
|
|
|
|
|
weeknames[i] = strdup(np);
|
|
|
|
|
np = strtok(NULL,":");
|
|
|
|
|
weeknames2[i] = strdup(np);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
months_per_year = strtol(line, NULL, 10);
|
|
|
|
|
monthnames = malloc(sizeof(char *) * months_per_year);
|
|
|
|
|
season = malloc(sizeof(int) * months_per_year);
|
|
|
|
|
storms = malloc(sizeof(int) * months_per_year);
|
|
|
|
|
|
|
|
|
|
for(i=0;i<months_per_year;i++) {
|
|
|
|
|
char * np;
|
|
|
|
|
fgets(line,255,namesFP);
|
|
|
|
|
l = strlen(line)-1;
|
|
|
|
|
if(line[l] == '\n') line[l] = 0;
|
|
|
|
|
|
|
|
|
|
np = strtok(line,":");
|
|
|
|
|
monthnames[i] = strdup(np);
|
|
|
|
|
season[i] = atoi(strtok(NULL,":"));
|
|
|
|
|
storms[i] = atoi(strtok(NULL,":"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(namesFP);
|
2001-02-05 17:11:59 +01:00
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
2001-04-22 07:36:50 +02:00
|
|
|
|
gamedate(const struct locale * lang)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int year,month,week,r;
|
|
|
|
|
static char buf[256];
|
|
|
|
|
int t = turn - FIRST_TURN;
|
|
|
|
|
|
|
|
|
|
if (t<0) t = turn;
|
2001-04-22 07:36:50 +02:00
|
|
|
|
assert(lang);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
year = t/(months_per_year * weeks_per_month) + 1;
|
|
|
|
|
r = t - (year-1) * months_per_year * weeks_per_month;
|
|
|
|
|
month = r/weeks_per_month;
|
|
|
|
|
week = r%weeks_per_month;
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, LOC(lang, "nr_calendar"),
|
|
|
|
|
weeknames[week],
|
|
|
|
|
monthnames[month],
|
|
|
|
|
year,
|
|
|
|
|
agename);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
gamedate2(void)
|
|
|
|
|
{
|
|
|
|
|
int year,month,week,r;
|
|
|
|
|
static char buf[256];
|
|
|
|
|
int t = turn - FIRST_TURN;
|
|
|
|
|
|
|
|
|
|
if (t<0) t = turn;
|
|
|
|
|
|
|
|
|
|
year = t/(months_per_year * weeks_per_month) + 1;
|
|
|
|
|
r = t - (year-1) * months_per_year * weeks_per_month;
|
|
|
|
|
month = r/weeks_per_month; /* 0 - months_per_year-1 */
|
|
|
|
|
week = r%weeks_per_month; /* 0 - weeks_per_month-1 */
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "in %s des Monats %s im Jahre %d %s.",
|
|
|
|
|
weeknames2[week],
|
|
|
|
|
monthnames[month],
|
|
|
|
|
year,
|
|
|
|
|
agename);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
gamedate_short(void)
|
|
|
|
|
{
|
|
|
|
|
int year,month,week,r;
|
|
|
|
|
static char buf[256];
|
|
|
|
|
int t = turn - FIRST_TURN;
|
|
|
|
|
|
|
|
|
|
if (t<0) t = turn;
|
|
|
|
|
|
|
|
|
|
year = t/(months_per_year * weeks_per_month) + 1;
|
|
|
|
|
r = t - (year-1) * months_per_year * weeks_per_month;
|
|
|
|
|
month = r/weeks_per_month; /* 0 - months_per_year-1 */
|
|
|
|
|
week = r%weeks_per_month; /* 0 - weeks_per_month-1 */
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%d/%s/%d", week+1, monthnames[month], year);
|
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
static void
|
|
|
|
|
rpsnr(FILE * F, const char * s, int offset)
|
|
|
|
|
{
|
|
|
|
|
char inset[REPORTWIDTH];
|
|
|
|
|
const char *l, *x = s;
|
|
|
|
|
char ui=0;
|
|
|
|
|
size_t indent = 0, len;
|
|
|
|
|
|
|
|
|
|
/* Geht nicht: Privatbeschreibungen der Monster enthalten
|
|
|
|
|
* \\r-Koordinaten ! */
|
|
|
|
|
/* assert(!strstr(s, "\\r(") || !"error: regionid not translated"); */
|
|
|
|
|
|
|
|
|
|
len = strlen(s);
|
|
|
|
|
while (*x++ == ' ');
|
|
|
|
|
indent = x - s - 1;
|
|
|
|
|
if (*(x - 1) && indent && *x == ' ') indent += 2;
|
|
|
|
|
if (!indent) indent = offset;
|
|
|
|
|
x = s;
|
|
|
|
|
memset(inset, 32, indent * sizeof(char));
|
|
|
|
|
inset[indent] = 0;
|
|
|
|
|
while (s <= x+len) {
|
|
|
|
|
size_t line = min(len-(s-x), REPORTWIDTH - indent*ui);
|
|
|
|
|
char * br = strchr(s, '\n');
|
|
|
|
|
l = s + line;
|
|
|
|
|
|
|
|
|
|
if(br && br < l) {
|
|
|
|
|
l = br;
|
|
|
|
|
} else {
|
|
|
|
|
if (*l) {
|
|
|
|
|
while (*l!=' ' && l!=s) --l;
|
|
|
|
|
/* wenn nicht gefunden, harte breaks: */
|
|
|
|
|
if (s == l) l = s + REPORTWIDTH - indent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*s) {
|
|
|
|
|
#if INDENT
|
|
|
|
|
putc(' ', F);
|
|
|
|
|
#endif
|
|
|
|
|
if (s!=x) {
|
|
|
|
|
fputs(inset, F);
|
|
|
|
|
}
|
|
|
|
|
fwrite(s, sizeof(char), l-s, F);
|
|
|
|
|
putc('\n', F);
|
|
|
|
|
}
|
|
|
|
|
s = l+1; ui=1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static faction *current_faction = NULL;
|
|
|
|
|
|
|
|
|
|
int outi;
|
|
|
|
|
char outbuf[4096];
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rpc(FILE * F, char c, size_t num)
|
|
|
|
|
{
|
|
|
|
|
while(num > 0) {
|
|
|
|
|
putc(c, F);
|
|
|
|
|
num--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rnl(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int rc, vc;
|
|
|
|
|
|
|
|
|
|
i = outi;
|
|
|
|
|
assert(i < 4096);
|
|
|
|
|
while (i && isspace((int)outbuf[i - 1]))
|
|
|
|
|
i--;
|
|
|
|
|
outbuf[i] = 0;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
rc = 0;
|
|
|
|
|
vc = 0;
|
|
|
|
|
|
|
|
|
|
while (outbuf[i]) {
|
|
|
|
|
switch (outbuf[i]) {
|
|
|
|
|
case ' ':
|
|
|
|
|
vc++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\t':
|
|
|
|
|
vc = (vc & ~7) + 8;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* ER: Tabs in Reports sind Mist. Die versauen die *
|
|
|
|
|
* Anzeige von Einheiten in Burgen und Schiffen. while
|
|
|
|
|
* (rc / 8 != vc / 8) { if ((rc & 7) == 7) putc(' ',
|
|
|
|
|
* F); else putc('\t', F); rc = (rc & ~7) + 8; } */
|
|
|
|
|
while (rc != vc) {
|
|
|
|
|
putc(' ', F);
|
|
|
|
|
rc++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
putc(outbuf[i], F);
|
|
|
|
|
rc++;
|
|
|
|
|
vc++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
assert(i < 4096);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
putc('\n', F);
|
|
|
|
|
outi = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rps(FILE * F, const char * src)
|
|
|
|
|
{
|
|
|
|
|
char * s;
|
|
|
|
|
|
|
|
|
|
if (strstr(src, "\\r(")) s = replace_global_coords(src, current_faction);
|
|
|
|
|
else s = strcpy(buf, src);
|
|
|
|
|
rpsnr(F, s, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
centre(FILE * F, const char *s, boolean breaking)
|
|
|
|
|
{
|
|
|
|
|
/* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme
|
|
|
|
|
* geben. Seltsamerweise wird i dann auf MAXINT oder aehnlich
|
|
|
|
|
* initialisiert. Deswegen keine Strings die laenger als REPORTWIDTH
|
|
|
|
|
* sind! */
|
|
|
|
|
|
|
|
|
|
if (breaking && REPORTWIDTH < strlen(s)) {
|
|
|
|
|
strlist *T, *SP = 0;
|
|
|
|
|
sparagraph(&SP, s, 0, 0);
|
|
|
|
|
T = SP;
|
|
|
|
|
while (SP) {
|
|
|
|
|
centre(F, SP->s, false);
|
|
|
|
|
SP = SP->next;
|
|
|
|
|
}
|
|
|
|
|
freestrlist(T);
|
|
|
|
|
} else {
|
|
|
|
|
rpc(F, ' ', (REPORTWIDTH - strlen(s)+1) / 2);
|
|
|
|
|
fputs(s, F);
|
|
|
|
|
putc('\n', F);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rparagraph(FILE *F, const char *s, int indent, char mark)
|
|
|
|
|
{
|
|
|
|
|
static char mbuf[BUFSIZE+1];
|
|
|
|
|
/* static size_t bsize = 0; */
|
|
|
|
|
size_t size;
|
|
|
|
|
char inset[REPORTWIDTH];
|
|
|
|
|
|
|
|
|
|
if (indent) {
|
|
|
|
|
memset(inset, ' ', indent);
|
|
|
|
|
inset[indent]=0;
|
|
|
|
|
if (mark)
|
|
|
|
|
inset[indent - 2] = mark;
|
|
|
|
|
} else {
|
|
|
|
|
assert(mark == 0);
|
|
|
|
|
inset[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
inset[indent]=0;
|
|
|
|
|
size = strlen(s)+indent+1;
|
|
|
|
|
if (size==1) return;
|
|
|
|
|
strcpy(mbuf, inset);
|
|
|
|
|
strncpy(mbuf+indent, s, BUFSIZE-indent);
|
|
|
|
|
*(mbuf+size-1)=0;
|
|
|
|
|
rps(F, mbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
report_spell(FILE * F, spellid_t id)
|
|
|
|
|
{
|
|
|
|
|
int k, itemanz, res, costtyp;
|
|
|
|
|
int dh = 0;
|
|
|
|
|
spell *sp = find_spellbyid(id);
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
centre(F, sp->name, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
strcpy(buf,"Beschreibung:");
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
rparagraph(F, sp->beschreibung, 0, 0);
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strcpy(buf, "Art: ");
|
|
|
|
|
if (sp->sptyp & PRECOMBATSPELL) {
|
|
|
|
|
scat("Pr<EFBFBD>kampfzauber");
|
|
|
|
|
} else if (sp->sptyp & COMBATSPELL) {
|
|
|
|
|
scat("Kampfzauber");
|
|
|
|
|
} else if (sp->sptyp & POSTCOMBATSPELL) {
|
|
|
|
|
scat("Postkampfzauber");
|
|
|
|
|
} else {
|
|
|
|
|
scat("Normaler Zauber");
|
|
|
|
|
}
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
|
|
|
|
strcpy(buf, "Komponenten:");
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
for (k = 0; k < MAXINGREDIENT; k++) {
|
|
|
|
|
res = sp->komponenten[k][0];
|
|
|
|
|
itemanz = sp->komponenten[k][1];
|
|
|
|
|
costtyp = sp->komponenten[k][2];
|
|
|
|
|
if(itemanz > 0){
|
|
|
|
|
sprintf(buf, " %d %s", itemanz, resname(res, itemanz!=1));
|
|
|
|
|
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR )
|
|
|
|
|
scat(" * Stufe");
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcpy(buf, "Modifikationen: ");
|
|
|
|
|
if (sp->sptyp & FARCASTING) {
|
|
|
|
|
scat("Fernzauber");
|
|
|
|
|
dh = 1;
|
|
|
|
|
}
|
|
|
|
|
if (sp->sptyp & OCEANCASTABLE) {
|
|
|
|
|
if (dh == 1){
|
|
|
|
|
scat(", ");
|
|
|
|
|
}
|
|
|
|
|
scat("Seezauber");
|
|
|
|
|
dh = 1;
|
|
|
|
|
}
|
|
|
|
|
if (sp->sptyp & ONSHIPCAST) {
|
|
|
|
|
if (dh == 1){
|
|
|
|
|
scat(", ");
|
|
|
|
|
}
|
|
|
|
|
scat("Schiffszauber");
|
|
|
|
|
dh = 1;
|
|
|
|
|
}
|
|
|
|
|
if (sp->sptyp & NOTFAMILIARCAST) {
|
|
|
|
|
if (dh == 1){
|
|
|
|
|
scat(", k");
|
|
|
|
|
} else {
|
|
|
|
|
scat("K");
|
|
|
|
|
}
|
|
|
|
|
scat("ann nicht vom Vertrauten gezaubert werden");
|
|
|
|
|
dh = 1;
|
|
|
|
|
}
|
|
|
|
|
if(dh == 0) scat("Keine");
|
|
|
|
|
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "Stufe: %d", sp->level);
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "Rang: %d", sp->rank);
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
strcpy(buf, "Syntax: ");
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
if(!sp->syntax){
|
|
|
|
|
if(sp->sptyp & ISCOMBATSPELL){
|
|
|
|
|
strcpy(buf, "KAMPFZAUBER ");
|
|
|
|
|
}else{
|
|
|
|
|
strcpy(buf, "ZAUBERE ");
|
|
|
|
|
}
|
|
|
|
|
/* Reihenfolge beachten: Erst REGION, dann STUFE! */
|
|
|
|
|
if (sp->sptyp & FARCASTING) {
|
|
|
|
|
scat("[REGION x y] ");
|
|
|
|
|
}
|
|
|
|
|
if (sp->sptyp & SPELLLEVEL) {
|
|
|
|
|
scat("[STUFE n] ");
|
|
|
|
|
}
|
|
|
|
|
scat("\"");
|
|
|
|
|
scat(sp->name);
|
|
|
|
|
scat("\" ");
|
|
|
|
|
if (sp->sptyp & ONETARGET){
|
|
|
|
|
if (sp->sptyp & UNITSPELL) {
|
|
|
|
|
scat("<Einheit-Nr>");
|
|
|
|
|
} else if (sp->sptyp & SHIPSPELL) {
|
|
|
|
|
scat("<Schiff-Nr>");
|
|
|
|
|
} else if (sp->sptyp & BUILDINGSPELL) {
|
|
|
|
|
scat("<Geb<65>ude-Nr>");
|
|
|
|
|
}
|
|
|
|
|
}else {
|
|
|
|
|
if (sp->sptyp & UNITSPELL) {
|
|
|
|
|
scat("<Einheit-Nr> [<Einheit-Nr> ...]");
|
|
|
|
|
} else if (sp->sptyp & SHIPSPELL) {
|
|
|
|
|
scat("<Schiff-Nr> [<Schiff-Nr> ...]");
|
|
|
|
|
} else if (sp->sptyp & BUILDINGSPELL) {
|
|
|
|
|
scat("<Geb<65>ude-Nr> [<Geb<65>ude-Nr> ...]");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
strcpy(buf, sp->syntax);
|
|
|
|
|
}
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmr_warnings(void)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
faction *f,*fa;
|
|
|
|
|
|
|
|
|
|
for(f=factions;f;f=f->next) {
|
|
|
|
|
if(f->no != MONSTER_FACTION && (turn-f->lastorders) >= 2) {
|
|
|
|
|
for(fa=factions;fa;fa=fa->next) {
|
|
|
|
|
if(isallied(NULL, f, fa, HELP_GUARD | HELP_MONEY) && isallied(NULL, fa,f,HELP_GUARD | HELP_MONEY)) {
|
|
|
|
|
sprintf(buf, "Achtung: %s hat einige Zeit keine "
|
|
|
|
|
"Z<EFBFBD>ge eingeschickt und k<>nnte dadurch in K<>rze aus dem "
|
|
|
|
|
"Spiel ausscheiden.", factionname(f));
|
|
|
|
|
addmessage(0, fa, buf, MSG_EVENT, ML_WARN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sparagraph(strlist ** SP, const char *s, int indent, char mark)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer
|
|
|
|
|
* mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf.
|
|
|
|
|
* Vgl. spunit (). */
|
|
|
|
|
|
|
|
|
|
int i, j, width;
|
|
|
|
|
int firstline;
|
|
|
|
|
static char buf[REPORTWIDTH + 1];
|
|
|
|
|
|
|
|
|
|
width = REPORTWIDTH - indent;
|
|
|
|
|
firstline = 1;
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
j = i;
|
|
|
|
|
while (s[j] && s[j] != ' ')
|
|
|
|
|
j++;
|
|
|
|
|
if (j > width) {
|
|
|
|
|
|
|
|
|
|
/* j zeigt auf das ende der aktuellen zeile, i zeigt auf den anfang der
|
|
|
|
|
* n<EFBFBD>chsten zeile. existiert ein wort am anfang der zeile, welches
|
|
|
|
|
* l<EFBFBD>nger als eine zeile ist, mu<EFBFBD> dieses hier abgetrennt werden. */
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
i = width - 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i = j + 1;
|
|
|
|
|
}
|
|
|
|
|
while (s[j]);
|
|
|
|
|
|
|
|
|
|
for (j = 0; j != indent; j++)
|
|
|
|
|
buf[j] = ' ';
|
|
|
|
|
|
|
|
|
|
if (firstline && mark)
|
|
|
|
|
buf[indent - 2] = mark;
|
|
|
|
|
|
|
|
|
|
for (j = 0; j != i - 1; j++)
|
|
|
|
|
buf[indent + j] = s[j];
|
|
|
|
|
buf[indent + j] = 0;
|
|
|
|
|
|
|
|
|
|
addstrlist(SP, buf);
|
|
|
|
|
|
|
|
|
|
if (s[i - 1] == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
s += i;
|
|
|
|
|
firstline = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
hat_in_region(item_t it, region * r, faction * f)
|
|
|
|
|
{
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->faction == f && get_item(u, it) > 0) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_curses(FILE *F, const void * obj, typ_t typ, const attrib *a, int self, int indent)
|
|
|
|
|
{
|
|
|
|
|
for(;a;a=a->next) {
|
|
|
|
|
int dh = 0;
|
|
|
|
|
|
|
|
|
|
if (fval(a->type, ATF_CURSE)) {
|
|
|
|
|
curse *c = (curse *)a->data.v;
|
|
|
|
|
if (c->type->curseinfo)
|
|
|
|
|
dh = c->type->curseinfo(obj, typ, c, self);
|
|
|
|
|
if (dh == 1) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, indent, 0);
|
|
|
|
|
}
|
|
|
|
|
} else if (a->type==&at_effect && self) {
|
|
|
|
|
effect_data * data = (effect_data *)a->data.v;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "Auf der Einheit lieg%s %d Wirkung%s %s.",
|
2001-01-25 10:37:55 +01:00
|
|
|
|
(data->value==1 ? "t" : "en"),
|
2001-04-16 16:34:19 +02:00
|
|
|
|
data->value,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
(data->value==1 ? "" : "en"),
|
2001-04-22 07:36:50 +02:00
|
|
|
|
LOC(NULL, resourcename(data->type->itype->rtype, 0)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, indent, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
replace_global_coords(const char *s, faction * f)
|
|
|
|
|
{
|
|
|
|
|
return translate_regions(s, f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rps_nowrap(FILE * F, const char *s)
|
|
|
|
|
{
|
|
|
|
|
const char *x = s;
|
|
|
|
|
int indent = 0;
|
|
|
|
|
|
|
|
|
|
x = s = replace_global_coords(s, current_faction);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
rpc(F, *s++, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rpu = 0;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rpunit(FILE * F, const faction * f, const unit * u, int indent, int mode)
|
|
|
|
|
{
|
|
|
|
|
strlist *S;
|
|
|
|
|
int dh;
|
|
|
|
|
boolean isbattle = (boolean)(mode == see_battle);
|
|
|
|
|
++rpu;
|
|
|
|
|
|
|
|
|
|
if(u->race == RC_SPELL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
dh = bufunit(f, u, indent, mode);
|
|
|
|
|
rparagraph(F, buf, indent, (char) ((u->faction == f) ? '*' : (dh ? '+' : '-')));
|
|
|
|
|
if(!isbattle){
|
|
|
|
|
print_curses(F, u, TYP_UNIT, u->attribs, (u->faction == f)? 1 : 0, indent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode==see_unit && u->faction == f && u->botschaften) {
|
|
|
|
|
for (S = u->botschaften; S; S = S->next) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, S->s, indent, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2001-02-24 13:50:51 +01:00
|
|
|
|
rp_messages(FILE * F, message_list * msgs, faction * viewer, int indent, boolean centered, boolean categorized)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
messageclass * category;
|
|
|
|
|
if (!msgs) return;
|
|
|
|
|
for (category=msgclasses; category; category=category->next) {
|
|
|
|
|
int k = 0;
|
2001-02-24 13:50:51 +01:00
|
|
|
|
struct mlist * m = msgs->begin;
|
|
|
|
|
while (m) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
boolean debug = viewer->options & want(O_DEBUG);
|
|
|
|
|
#ifdef MSG_LEVELS
|
|
|
|
|
if (!debug && get_msglevel(viewer->warnings, viewer->msglevels, m->type) < m->level) continue;
|
|
|
|
|
#endif
|
|
|
|
|
/* messagetype * mt = m->type; */
|
2001-02-28 23:14:59 +01:00
|
|
|
|
if (strcmp(nr_section(m->msg), category->name)==0)
|
|
|
|
|
{
|
|
|
|
|
char buf[4096], *s = buf;
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
nr_render(m->msg, viewer->locale, s, viewer);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!k && categorized) {
|
|
|
|
|
const char * name;
|
|
|
|
|
char cat_identifier[24];
|
|
|
|
|
|
|
|
|
|
sprintf(cat_identifier, "section_%s", category->name);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
name = LOC(viewer->locale, cat_identifier);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (debug) {
|
|
|
|
|
if (name!=buf) strcpy(buf, name);
|
|
|
|
|
sprintf(buf+strlen(name), " [%s]", cat_identifier);
|
|
|
|
|
name = buf;
|
|
|
|
|
}
|
|
|
|
|
k = 1;
|
|
|
|
|
rnl(F);
|
|
|
|
|
if (centered) centre(F, name, true);
|
|
|
|
|
else {
|
|
|
|
|
if (indent>0) strcpy(buf, " ");
|
|
|
|
|
strcpy(buf+indent, name);
|
|
|
|
|
rpsnr(F, buf, 2);
|
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
if (indent>0) {
|
|
|
|
|
strcpy(buf, " ");
|
|
|
|
|
strcpy(buf+indent, s);
|
|
|
|
|
s = buf;
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef MSG_LEVELS
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (debug) {
|
|
|
|
|
int mylevel = get_msglevel(viewer->warnings, viewer->msglevels, m->type);
|
|
|
|
|
int level = msg_level(m);
|
|
|
|
|
if (s!=buf) strcpy(buf, s);
|
|
|
|
|
sprintf(buf+strlen(s), " [%d:%d(%d)]", m->type->hashkey, level, mylevel);
|
|
|
|
|
s = buf;
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rpsnr(F, s, 2);
|
|
|
|
|
}
|
2001-02-24 13:50:51 +01:00
|
|
|
|
m=m->next;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
f_regionid(const region * r, const faction * f)
|
|
|
|
|
{
|
|
|
|
|
static int i = 0;
|
|
|
|
|
static char bufs[4][NAMESIZE + 20];
|
|
|
|
|
char * buf = bufs[(++i)%4];
|
|
|
|
|
plane *pl = NULL;
|
|
|
|
|
|
|
|
|
|
if (!r)
|
|
|
|
|
strcpy(buf, "(Chaos)");
|
|
|
|
|
else {
|
|
|
|
|
pl = getplane(r);
|
|
|
|
|
if(pl && fval(pl,PFL_NOCOORDS)) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "%s", rname(r, f->locale));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "%s (%d,%d%s%s)", rname(r, f->locale), region_x(r,f), region_y(r,f), pl?",":"", pl?pl->name:"");
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
prices(FILE * F, region * r, faction * f)
|
|
|
|
|
{
|
|
|
|
|
const luxury_type *sale=NULL;
|
|
|
|
|
struct demand * dmd;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
int n = 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (r->land==NULL || r->land->demands==NULL) return;
|
|
|
|
|
for (dmd=r->land->demands;dmd;dmd=dmd->next) {
|
|
|
|
|
if (dmd->value==0) sale = dmd->type;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
else if (dmd->value > 0) n++;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
assert(sale!=NULL);
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "Auf dem Markt wird f<>r %s %d Silber verlangt.",
|
2001-04-22 07:36:50 +02:00
|
|
|
|
LOC(f->locale, resourcename(sale->itype->rtype, GR_PLURAL)),
|
2001-02-03 14:45:35 +01:00
|
|
|
|
sale->price);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if(n > 0) scat(" Geboten wird f<>r ");
|
|
|
|
|
|
|
|
|
|
for (dmd=r->land->demands;dmd;dmd=dmd->next) if(dmd->value > 0) {
|
|
|
|
|
char sbuf[80];
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(sbuf, "%s %d Silber", LOC(f->locale,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
resourcename(dmd->type->itype->rtype, GR_PLURAL)),
|
|
|
|
|
dmd->value * dmd->type->price);
|
|
|
|
|
scat(sbuf);
|
|
|
|
|
n--;
|
|
|
|
|
if (n == 0) scat(".");
|
|
|
|
|
else if (n == 1) scat(" und f<>r ");
|
|
|
|
|
else scat(", f<>r ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Schreibe Paragraphen */
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
extern const direction_t back[MAXDIRECTIONS];
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
boolean
|
|
|
|
|
see_border(border * b, faction * f, region * r)
|
|
|
|
|
{
|
|
|
|
|
boolean cs = b->type->fvisible(b, f, r);
|
|
|
|
|
if (!cs) {
|
|
|
|
|
cs = b->type->rvisible(b, r);
|
|
|
|
|
if (!cs) {
|
|
|
|
|
unit * us = r->units;
|
|
|
|
|
while (us && !cs) {
|
|
|
|
|
if (us->faction==f) {
|
|
|
|
|
cs = b->type->uvisible(b, us);
|
|
|
|
|
if (cs) break;
|
|
|
|
|
}
|
|
|
|
|
us=us->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return cs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
describe(FILE * F, region * r, int partial, faction * f)
|
|
|
|
|
{
|
|
|
|
|
char dbuf[512];
|
|
|
|
|
int n;
|
|
|
|
|
boolean dh;
|
|
|
|
|
direction_t d;
|
|
|
|
|
int maxmining = 0, trees;
|
|
|
|
|
unit *u;
|
|
|
|
|
attrib *a;
|
|
|
|
|
const char *tname;
|
|
|
|
|
struct edge {
|
|
|
|
|
struct edge * next;
|
|
|
|
|
char * name;
|
|
|
|
|
boolean transparent;
|
|
|
|
|
boolean block;
|
|
|
|
|
boolean exist[MAXDIRECTIONS];
|
|
|
|
|
direction_t lastd;
|
|
|
|
|
} * edges = NULL, * e;
|
|
|
|
|
boolean see[MAXDIRECTIONS];
|
|
|
|
|
|
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++)
|
|
|
|
|
{ /* Nachbarregionen, die gesehen werden, ermitteln */
|
|
|
|
|
region *r2 = rconnect(r, d);
|
|
|
|
|
border *b;
|
|
|
|
|
see[d] = true;
|
|
|
|
|
if (!r2) continue;
|
|
|
|
|
for (b=get_borders(r, r2);b;) {
|
|
|
|
|
struct edge * e = edges;
|
|
|
|
|
boolean transparent = b->type->transparent(b, f);
|
|
|
|
|
const char * name = b->type->name(b, r, f, GF_DETAILED|GF_ARTICLE);
|
|
|
|
|
|
|
|
|
|
if (!transparent) see[d] = false;
|
|
|
|
|
if (!see_border(b, f, r)) {
|
|
|
|
|
b = b->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
while (e && (e->transparent != transparent || strcmp(name,e->name))) e = e->next;
|
|
|
|
|
if (!e) {
|
|
|
|
|
e = calloc(sizeof(struct edge), 1);
|
|
|
|
|
e->name = strdup(name);
|
|
|
|
|
e->transparent = transparent;
|
|
|
|
|
e->next = edges;
|
|
|
|
|
edges = e;
|
|
|
|
|
}
|
|
|
|
|
e->lastd=d;
|
|
|
|
|
e->exist[d] = true;
|
|
|
|
|
b = b->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcpy(buf, f_regionid(r, f));
|
|
|
|
|
|
|
|
|
|
if (partial == 1) {
|
|
|
|
|
scat(" (durchgereist)");
|
|
|
|
|
}
|
|
|
|
|
#ifdef SEE_FAR
|
|
|
|
|
else if (partial == 3) {
|
|
|
|
|
scat(" (benachbart)");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else if (partial == 2) {
|
|
|
|
|
scat(" (vom Turm erblickt)");
|
|
|
|
|
}
|
|
|
|
|
/* Terrain */
|
|
|
|
|
|
|
|
|
|
scat(", ");
|
|
|
|
|
if(is_cursed(r->attribs,C_MAELSTROM, 0))
|
|
|
|
|
tname = "maelstrom";
|
|
|
|
|
else {
|
|
|
|
|
if (r_isforest(r)) tname = "forest";
|
|
|
|
|
else tname = terrain[rterrain(r)].name;
|
|
|
|
|
}
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, tname));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* B<>ume */
|
|
|
|
|
|
|
|
|
|
trees = rtrees(r);
|
|
|
|
|
if (production(r) && trees > 0) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(trees);
|
|
|
|
|
scat(" ");
|
|
|
|
|
if (fval(r, RF_MALLORN)) {
|
|
|
|
|
if (rtrees(r) == 1)
|
|
|
|
|
scat("Mallornbaum");
|
|
|
|
|
else
|
|
|
|
|
scat("Mallornb<EFBFBD>ume");
|
|
|
|
|
}
|
|
|
|
|
else if (rtrees(r) == 1)
|
|
|
|
|
scat("Baum");
|
|
|
|
|
else
|
|
|
|
|
scat("B<EFBFBD>ume");
|
|
|
|
|
}
|
|
|
|
|
/* Eisen */
|
|
|
|
|
|
|
|
|
|
if (partial == 0
|
|
|
|
|
&& f != (faction *) NULL
|
|
|
|
|
&& (rterrain(r) == T_MOUNTAIN || rterrain(r) == T_GLACIER)) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->faction == f) {
|
|
|
|
|
int s = eff_skill(u, SK_MINING, r);
|
|
|
|
|
maxmining = max(maxmining, s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (maxmining >= 4) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(riron(r));
|
|
|
|
|
scat(" Eisen");
|
|
|
|
|
}
|
|
|
|
|
#ifdef NEW_ITEMS
|
|
|
|
|
if (rlaen(r)>=0 && maxmining >= 7)
|
|
|
|
|
#else
|
|
|
|
|
if (rlaen(r)>=0 && maxmining >= itemdata[I_EOG].minskill)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(rlaen(r));
|
|
|
|
|
scat(" Laen");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Bauern & Geld */
|
|
|
|
|
|
|
|
|
|
if (rpeasants(r)) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(rpeasants(r));
|
|
|
|
|
|
|
|
|
|
if(fval(r, RF_ORCIFIED)) {
|
|
|
|
|
scat(rpeasants(r)==1?" Ork":" Orks");
|
|
|
|
|
} else {
|
|
|
|
|
scat(rpeasants(r)==1?" Bauer":" Bauern");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rmoney(r) && partial == 0) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(rmoney(r));
|
|
|
|
|
scat(" Silber");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Pferde */
|
|
|
|
|
|
|
|
|
|
if (rhorses(r)) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
icat(rhorses(r));
|
|
|
|
|
scat(" ");
|
|
|
|
|
#ifdef NEW_ITEMS
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, resourcename(oldresourcetype[R_HORSE], (rhorses(r)>1)?GR_PLURAL:0)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#else
|
|
|
|
|
scat(itemdata[I_HORSE].name[rhorses(r) > 1]);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
scat(".");
|
|
|
|
|
|
|
|
|
|
if (r->display[0]) {
|
|
|
|
|
scat(" ");
|
|
|
|
|
scat(r->display);
|
|
|
|
|
|
|
|
|
|
n = r->display[strlen(r->display) - 1];
|
|
|
|
|
if (n != '!' && n != '?' && n != '.')
|
|
|
|
|
scat(".");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_cursed(r->attribs, C_REGCONF, 0)) {
|
2001-02-10 11:40:12 +01:00
|
|
|
|
attrib *a_do = a_find(r->attribs, &at_overrideroads);
|
2001-02-04 09:42:36 +01:00
|
|
|
|
if(a_do) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
scat(" ");
|
2001-02-04 09:42:36 +01:00
|
|
|
|
scat((char *)a_do->data.v);
|
|
|
|
|
} else {
|
|
|
|
|
int nrd = 0;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
|
2001-02-04 09:42:36 +01:00
|
|
|
|
/* Nachbarregionen, die gesehen werden, ermitteln */
|
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++)
|
|
|
|
|
if (see[d] && rconnect(r, d)) nrd++;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
|
2001-02-04 09:42:36 +01:00
|
|
|
|
/* Richtungen aufz<66>hlen */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
|
2001-02-04 09:42:36 +01:00
|
|
|
|
dh = false;
|
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; d++) if (see[d]) {
|
|
|
|
|
region * r2 = rconnect(r, d);
|
|
|
|
|
if(!r2) continue;
|
|
|
|
|
nrd--;
|
|
|
|
|
if (dh) {
|
|
|
|
|
if (nrd == 0) scat(" und im ");
|
|
|
|
|
else scat(", im ");
|
|
|
|
|
}
|
|
|
|
|
else scat(" Im ");
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, directions[d]));
|
2001-02-04 09:42:36 +01:00
|
|
|
|
scat(" ");
|
|
|
|
|
if (!dh) scat("der Region liegt ");
|
|
|
|
|
sprintf(dbuf, trailinto(r2, f->locale),
|
|
|
|
|
f_regionid(r2, f));
|
|
|
|
|
scat(dbuf);
|
|
|
|
|
dh = true;
|
|
|
|
|
}
|
|
|
|
|
/* Spezielle Richtungen */
|
|
|
|
|
for (a = a_find(r->attribs, &at_direction);a;a = a->nexttype) {
|
|
|
|
|
spec_direction * d = (spec_direction *)(a->data.v);
|
|
|
|
|
scat(" ");
|
|
|
|
|
scat(d->desc);
|
|
|
|
|
scat(" (\"");
|
|
|
|
|
scat(d->keyword);
|
|
|
|
|
scat("\")");
|
|
|
|
|
scat(".");
|
|
|
|
|
dh = 1;
|
|
|
|
|
}
|
|
|
|
|
if (dh) scat(".");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
} else {
|
|
|
|
|
scat(" Gro<72>e Verwirrung bef<65>llt alle Reisenden in dieser Region.");
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r->planep && r->planep->id == 1 &&
|
|
|
|
|
!is_cursed(r->attribs, C_ASTRALBLOCK, 0)) {
|
|
|
|
|
/* Sonderbehandlung Teleport-Ebene */
|
|
|
|
|
regionlist *rl = allinhab_in_range(r_astral_to_standard(r), TP_RADIUS);
|
|
|
|
|
regionlist *rl2;
|
|
|
|
|
|
|
|
|
|
if (rl) {
|
|
|
|
|
strcpy(buf, "Schemen der Regionen ");
|
|
|
|
|
rl2 = rl;
|
|
|
|
|
while(rl2) {
|
|
|
|
|
scat(f_regionid(rl2->region, f));
|
|
|
|
|
rl2 = rl2->next;
|
|
|
|
|
if(rl2) scat(", ");
|
|
|
|
|
}
|
|
|
|
|
scat(" sind erkennbar.");
|
|
|
|
|
free_regionlist(rl);
|
|
|
|
|
/* Schreibe Paragraphen */
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
|
|
/* Wirkungen permanenter Spr<70>che */
|
|
|
|
|
print_curses(F, r, TYP_REGION, r->attribs, 0, 0);
|
|
|
|
|
|
|
|
|
|
/* Produktionsreduktion */
|
|
|
|
|
a = a_find(r->attribs, &at_reduceproduction);
|
|
|
|
|
if(a) {
|
|
|
|
|
sprintf(buf, "Die Region ist verw<72>stet, der Boden karg.");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (edges) rnl(F);
|
|
|
|
|
for (e=edges;e;e=e->next) {
|
|
|
|
|
boolean first = true;
|
|
|
|
|
for (d=0;d!=MAXDIRECTIONS;++d) {
|
|
|
|
|
if (!e->exist[d]) continue;
|
|
|
|
|
if (first) strcpy(buf, "Im ");
|
|
|
|
|
else {
|
|
|
|
|
if (e->lastd==d) strcat(buf, " und im ");
|
|
|
|
|
else strcat(buf, ", im ");
|
|
|
|
|
}
|
2001-04-22 07:36:50 +02:00
|
|
|
|
strcat(buf, LOC(f->locale, directions[d]));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
if (!e->transparent) strcat(buf, " versperrt ");
|
|
|
|
|
else strcat(buf, " befindet sich ");
|
|
|
|
|
strcat(buf, e->name);
|
|
|
|
|
if (!e->transparent) strcat(buf, " die Sicht.");
|
|
|
|
|
else strcat(buf, ".");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
if (edges) {
|
|
|
|
|
while (edges) {
|
|
|
|
|
e = edges->next;
|
|
|
|
|
free(edges->name);
|
|
|
|
|
free(edges);
|
|
|
|
|
edges = e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern const int wagetable[6][3];
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
statistics(FILE * F, region * r, faction * f)
|
|
|
|
|
{
|
|
|
|
|
unit *u;
|
|
|
|
|
int number, p;
|
|
|
|
|
item *itm, *items = NULL;
|
|
|
|
|
p = rpeasants(r);
|
|
|
|
|
number = 0;
|
|
|
|
|
|
|
|
|
|
/* z<>hlen */
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->faction == f && u->race != RC_SPELL) {
|
|
|
|
|
for (itm=u->items;itm;itm=itm->next) {
|
|
|
|
|
i_change(&items, itm->type, itm->number);
|
|
|
|
|
}
|
|
|
|
|
number += u->number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ausgabe */
|
|
|
|
|
rnl(F);
|
|
|
|
|
sprintf(buf, "Statistik f<>r %s:", f_regionid(r, f));
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
/* Region */
|
|
|
|
|
if (landregion(rterrain(r)) && rmoney(r)) {
|
|
|
|
|
sprintf(buf, "Unterhaltung: max. %d Silber", entertainmoney(r));
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
}
|
|
|
|
|
if (production(r) && (!rterrain(r) == T_OCEAN || f->race == RC_AQUARIAN)) {
|
|
|
|
|
sprintf(buf, "Lohn f<>r Arbeit: %d Silber", fwage(r, f, true));
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
}
|
|
|
|
|
if (p) {
|
|
|
|
|
sprintf(buf, "Rekrutieren: max. %d Bauern",
|
|
|
|
|
p / RECRUITFRACTION);
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
|
2001-03-04 19:41:27 +01:00
|
|
|
|
if (buildingtype_exists(r, &bt_caravan)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, "Luxusg<EFBFBD>ter zum angegebenen Preis: %d",
|
|
|
|
|
(p * 2) / TRADE_FRACTION);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf, "Luxusg<EFBFBD>ter zum angegebenen Preis: %d",
|
|
|
|
|
p / TRADE_FRACTION);
|
|
|
|
|
}
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
}
|
|
|
|
|
/* Info <20>ber Einheiten */
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "Personen: %d", number);
|
|
|
|
|
rps(F, buf);
|
|
|
|
|
for (itm = items; itm; itm=itm->next) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s: %d", LOC(f->locale, resourcename(itm->type->rtype, GR_PLURAL)), itm->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rps(F, buf);
|
|
|
|
|
}
|
|
|
|
|
while (items) i_free(i_remove(&items, items));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
in_region(region * r, unit * u)
|
|
|
|
|
{
|
|
|
|
|
unit *ru;
|
|
|
|
|
|
|
|
|
|
for (ru = r->units; ru; ru = ru->next) {
|
|
|
|
|
if (u == ru) {
|
|
|
|
|
return (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
durchreisende(FILE * F, region * r, faction * f)
|
|
|
|
|
{
|
|
|
|
|
attrib *ru;
|
|
|
|
|
int wieviele;
|
|
|
|
|
int counter;
|
|
|
|
|
|
|
|
|
|
wieviele = counter = 0;
|
|
|
|
|
|
|
|
|
|
/* Wieviele sind aufzulisten? F<>r die Grammatik. */
|
|
|
|
|
|
|
|
|
|
for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
|
|
|
|
|
unit * u = (unit*)ru->data.v;
|
|
|
|
|
if (cansee_durchgezogen(f, r, u, 0) > 0 && !in_region(r, u)) {
|
|
|
|
|
if (u->ship && !fval(u, FL_OWNER))
|
|
|
|
|
continue;
|
|
|
|
|
wieviele++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!wieviele)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Auflisten. */
|
|
|
|
|
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
|
|
|
|
|
unit * u = (unit*)ru->data.v;
|
|
|
|
|
if (cansee_durchgezogen(f, r, u, 0) > 0 && !in_region(r, u)) {
|
|
|
|
|
if (u->ship && !fval(u, FL_OWNER))
|
|
|
|
|
continue;
|
|
|
|
|
counter++;
|
|
|
|
|
if (u->ship != (ship *) NULL) {
|
|
|
|
|
if (counter == 1) {
|
|
|
|
|
scat("Die ");
|
|
|
|
|
} else {
|
|
|
|
|
scat("die ");
|
|
|
|
|
}
|
|
|
|
|
scat(shipname(u->ship));
|
|
|
|
|
} else {
|
|
|
|
|
scat(unitname(u));
|
|
|
|
|
}
|
|
|
|
|
if (counter + 1 < wieviele) {
|
|
|
|
|
scat(", ");
|
|
|
|
|
} else if (counter + 1 == wieviele) {
|
|
|
|
|
scat(" und ");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wieviele == 1) {
|
|
|
|
|
scat(" hat die Region durchquert.");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
} else {
|
|
|
|
|
scat(" haben die Region durchquert.");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
order_template(FILE * F, faction * f)
|
|
|
|
|
{
|
|
|
|
|
strlist *S2;
|
|
|
|
|
region *r;
|
|
|
|
|
plane *pl;
|
|
|
|
|
unit *u;
|
|
|
|
|
int dh;
|
|
|
|
|
region *last = lastregion(f);
|
|
|
|
|
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
|
|
|
|
rps_nowrap(F, "Vorlage f<>r den n<>chsten Zug:");
|
|
|
|
|
rnl(F);
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s %s \"hier_passwort_eintragen\"", LOC(f->locale, parameters[P_FACTION]), factionid(f));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
dh = (f->options & Pow(O_SILBERPOOL));
|
|
|
|
|
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
sprintf(buf, "; ECHECK %s-w4 -r%d -v%s", dh ? "-l " : "",
|
|
|
|
|
race[f->race].rekrutieren, ECHECK_VERSION);
|
|
|
|
|
/* -v3.4: ECheck Version 3.4.x */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
for (r = firstregion(f); r != last; r = r->next) {
|
|
|
|
|
dh = 0;
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->faction == f && u->race != RC_SPELL) {
|
|
|
|
|
if (!dh) {
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
|
|
|
|
pl = getplane(r);
|
|
|
|
|
if (pl && fval(pl, PFL_NOCOORDS)) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s; %s", LOC(f->locale, parameters[P_REGION]), rname(r, f->locale));
|
2001-02-13 00:44:30 +01:00
|
|
|
|
} else if (pl && pl->id != 0) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s %d,%d,%d ; %s", LOC(f->locale, parameters[P_REGION]), region_x(r,f),
|
2001-02-11 20:56:49 +01:00
|
|
|
|
region_y(r,f), pl->id, rname(r, f->locale));
|
2001-02-13 00:44:30 +01:00
|
|
|
|
} else {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s %d,%d ; %s", LOC(f->locale, parameters[P_REGION]), region_x(r,f),
|
2001-01-25 10:37:55 +01:00
|
|
|
|
region_y(r,f), rname(r, f->locale));
|
|
|
|
|
}
|
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
sprintf(buf,"; ECheck Lohn %d", fwage(r,f,true));
|
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
dh = 1;
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s %s; %s [%d,%d$", LOC(u->faction->locale, parameters[P_UNIT]),
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unitid(u), u->name, u->number, get_money(u));
|
|
|
|
|
if (u->building != NULL && fval(u, FL_OWNER)) {
|
|
|
|
|
building * b = u->building;
|
|
|
|
|
int cost = buildingmaintenance(b, R_SILVER);
|
|
|
|
|
|
|
|
|
|
if (cost > 0) {
|
|
|
|
|
scat(",U");
|
|
|
|
|
icat(cost);
|
|
|
|
|
}
|
|
|
|
|
#if TODO
|
|
|
|
|
if (buildingdaten[u->building->typ].spezial != 0) {
|
|
|
|
|
scat("+");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
} else if (u->ship) {
|
|
|
|
|
if (fval(u, FL_OWNER))
|
|
|
|
|
scat(",S");
|
|
|
|
|
else
|
|
|
|
|
scat(",s");
|
|
|
|
|
scat(shipid(u->ship));
|
|
|
|
|
}
|
|
|
|
|
if (lifestyle(u) == 0)
|
|
|
|
|
scat(",I");
|
|
|
|
|
scat("]");
|
|
|
|
|
|
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
for (S2 = u->orders; S2; S2 = S2->next) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if(is_persistent(S2->s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, " %s", S2->s);
|
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-01 08:58:45 +02:00
|
|
|
|
/* If the lastorder begins with an @ it should have
|
|
|
|
|
* been printed in the loop before. */
|
|
|
|
|
if(u->lastorder[0] != 0 && u->lastorder[0] != '@') {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, " %s", u->lastorder);
|
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rps_nowrap(F, "");
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, LOC(f->locale, parameters[P_NEXT]));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rps_nowrap(F, buf);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
alliances(ally * sf)
|
|
|
|
|
{
|
|
|
|
|
int allierte = 0;
|
|
|
|
|
int i=0, h, hh = 0;
|
|
|
|
|
int dh = 0;
|
|
|
|
|
ally * sff;
|
|
|
|
|
for (sff = sf; sff; sff = sff->next) {
|
|
|
|
|
if (sff->status > 0 && sff->status <= HELP_ALL) {
|
|
|
|
|
allierte++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (sf) {
|
|
|
|
|
if (sf->status > 0) {
|
|
|
|
|
i++;
|
|
|
|
|
if (dh) {
|
|
|
|
|
if (i == allierte)
|
|
|
|
|
scat(" und ");
|
|
|
|
|
else
|
|
|
|
|
scat(", ");
|
|
|
|
|
}
|
|
|
|
|
dh = 1;
|
|
|
|
|
hh = 0;
|
|
|
|
|
scat(factionname(sf->faction));
|
|
|
|
|
scat(" (");
|
|
|
|
|
if (sf->status == HELP_ALL) {
|
|
|
|
|
scat("Alles");
|
|
|
|
|
} else
|
|
|
|
|
for (h = 1; h < HELP_ALL; h *= 2) {
|
|
|
|
|
if ((sf->status & h) == h)
|
|
|
|
|
switch (h) {
|
|
|
|
|
case HELP_MONEY:
|
|
|
|
|
scat("Silber");
|
|
|
|
|
hh = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HELP_FIGHT:
|
|
|
|
|
if (hh)
|
|
|
|
|
scat(", ");
|
|
|
|
|
scat("K<EFBFBD>mpfe");
|
|
|
|
|
hh = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HELP_OBSERVE:
|
|
|
|
|
if (hh)
|
|
|
|
|
scat(", ");
|
|
|
|
|
scat("Wahrnehmung");
|
|
|
|
|
hh = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HELP_GIVE:
|
|
|
|
|
if (hh)
|
|
|
|
|
scat(", ");
|
|
|
|
|
scat("Gib");
|
|
|
|
|
hh = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HELP_GUARD:
|
|
|
|
|
if (hh)
|
|
|
|
|
scat(", ");
|
|
|
|
|
scat("Bewache");
|
|
|
|
|
hh = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scat(")");
|
|
|
|
|
}
|
|
|
|
|
sf = sf->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
allies(FILE * F, faction * f)
|
|
|
|
|
{
|
|
|
|
|
#ifdef GROUPS
|
|
|
|
|
group * g = f->groups;
|
|
|
|
|
#endif
|
|
|
|
|
if (f->allies) {
|
|
|
|
|
if (!f->allies->next) {
|
|
|
|
|
strcpy(buf, "Wir helfen der Partei ");
|
|
|
|
|
} else {
|
|
|
|
|
strcpy(buf, "Wir helfen den Parteien ");
|
|
|
|
|
}
|
|
|
|
|
alliances(f->allies);
|
|
|
|
|
scat(".");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef GROUPS
|
|
|
|
|
while (g) {
|
|
|
|
|
if (g->allies) {
|
|
|
|
|
if (!g->allies->next) {
|
|
|
|
|
sprintf(buf, "%s hilft der Partei ", g->name);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf, "%s hilft den Parteien ", g->name);
|
|
|
|
|
}
|
|
|
|
|
alliances(g->allies);
|
|
|
|
|
scat(".");
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
g = g->next;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
guards(FILE * F, region * r, faction * see)
|
|
|
|
|
{ /* die Partei see sieht dies; wegen
|
|
|
|
|
* "unbekannte Partei", wenn man es selbst ist... */
|
|
|
|
|
|
|
|
|
|
faction* guardians[512];
|
|
|
|
|
|
|
|
|
|
int nextguard = 0;
|
|
|
|
|
|
|
|
|
|
unit *u;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
boolean tarned = false;
|
|
|
|
|
/* Bewachung */
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (getguard(u)) {
|
|
|
|
|
faction *f = u->faction;
|
|
|
|
|
|
|
|
|
|
if (f!=see && fval(u, FL_PARTEITARNUNG)) {
|
|
|
|
|
tarned=true;
|
|
|
|
|
} else {
|
|
|
|
|
for (i=0;i!=nextguard;++i) if (guardians[i]==f) break;
|
|
|
|
|
if (i==nextguard) {
|
|
|
|
|
guardians[nextguard++] = f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!nextguard && !tarned) return;
|
|
|
|
|
|
|
|
|
|
strcpy(buf, "Die Region wird von ");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i!=nextguard+(tarned?1:0); ++i) {
|
|
|
|
|
if (i!=0) {
|
|
|
|
|
if (i == nextguard-(tarned?0:1))
|
|
|
|
|
scat(" und ");
|
|
|
|
|
else
|
|
|
|
|
scat(", ");
|
|
|
|
|
}
|
|
|
|
|
if (i<nextguard) scat(factionname(guardians[i]));
|
|
|
|
|
|
|
|
|
|
else scat("unbekannten Einheiten");
|
|
|
|
|
}
|
|
|
|
|
scat(" bewacht.");
|
|
|
|
|
rnl(F);
|
|
|
|
|
rparagraph(F, buf, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rpline(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
rpc(F, ' ', 1);
|
|
|
|
|
rpc(F, '-', REPORTWIDTH);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2001-02-24 13:50:51 +01:00
|
|
|
|
fcompare(const void * a, const void * b)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
faction * f1 = *(faction**)a;
|
|
|
|
|
faction * f2 = *(faction**)b;
|
|
|
|
|
if (f1->no>f2->no) return 1;
|
|
|
|
|
else if (f1->no<f2->no) return -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
list_address(FILE * F, faction * uf)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
void **fp;
|
|
|
|
|
cvector *fcts = malloc(sizeof(cvector));
|
|
|
|
|
|
|
|
|
|
cv_init(fcts);
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
if (f->no != MONSTER_FACTION && kann_finden(uf, f) != 0) {
|
|
|
|
|
cv_pushback(fcts, f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v_sort(fcts->begin, fcts->end, fcompare);
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(uf->locale, "nr_addresses"), false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rnl(F);
|
|
|
|
|
for (fp = fcts->begin; fp != fcts->end; ++fp) {
|
|
|
|
|
f = *fp;
|
|
|
|
|
sprintf(buf, "%s: %s; %s", factionname(f), f->email, f->banner);
|
|
|
|
|
rparagraph(F, buf, 4, '*');
|
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
|
|
|
|
rpline(F);
|
|
|
|
|
free(cv_kill(fcts));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
report_building(FILE *F, const region * r, const building * b, const faction * f, int mode)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
unit *u;
|
|
|
|
|
attrib * a = a_find(b->attribs, &at_icastle);
|
|
|
|
|
const locale * lang = NULL;
|
|
|
|
|
const building_type * type = b->type;
|
|
|
|
|
|
|
|
|
|
if (f) lang = f->locale;
|
|
|
|
|
|
|
|
|
|
if (a!=NULL) {
|
|
|
|
|
type = ((icastle_data*)a->data.v)->type;
|
|
|
|
|
} else {
|
|
|
|
|
type = b->type;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s, %s %d, %s", buildingname(b), LOC(f->locale, "nr_size"),
|
|
|
|
|
b->size, buildingtype(b, b->size, lang));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (b->size < type->maxsize) {
|
|
|
|
|
scat(" (im Bau)");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (b->besieged > 0 && mode>=see_lighthouse) {
|
|
|
|
|
scat(", belagert von ");
|
|
|
|
|
icat(b->besieged);
|
|
|
|
|
scat(" Personen ");
|
|
|
|
|
if (b->besieged >= b->size * SIEGEFACTOR) {
|
|
|
|
|
scat("(abgeschnitten)");
|
|
|
|
|
} else {
|
|
|
|
|
scat("(unvollst<73>ndig belagert)");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
i = 0;
|
|
|
|
|
if (b->display[0]) {
|
|
|
|
|
scat("; ");
|
|
|
|
|
scat(b->display);
|
|
|
|
|
i = b->display[strlen(b->display) - 1];
|
|
|
|
|
}
|
|
|
|
|
if (i != '!' && i != '?' && i != '.')
|
|
|
|
|
scat(".");
|
|
|
|
|
|
|
|
|
|
rparagraph(F, buf, 2, 0);
|
|
|
|
|
|
|
|
|
|
if (mode<see_lighthouse) return;
|
|
|
|
|
|
|
|
|
|
/* Leere Burgen verursachten sonst segfault! */
|
|
|
|
|
if(buildingowner(r,b) != NULL){
|
|
|
|
|
print_curses(F, b, TYP_BUILDING, b->attribs,
|
|
|
|
|
(buildingowner(r,b)->faction == f)? 1 : 0, 2);
|
|
|
|
|
} else {
|
|
|
|
|
print_curses(F, b, TYP_BUILDING, b->attribs, 0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->building == b && fval(u, FL_OWNER)) {
|
|
|
|
|
rpunit(F, f, u, 6, mode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->building == b && !fval(u, FL_OWNER))
|
|
|
|
|
rpunit(F, f, u, 6, mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
report(FILE *F, faction * f)
|
|
|
|
|
{
|
|
|
|
|
#ifndef NEW_ITEMS
|
|
|
|
|
potion_t potion;
|
|
|
|
|
#endif
|
|
|
|
|
int flag = 0;
|
|
|
|
|
char ch;
|
|
|
|
|
int dh;
|
|
|
|
|
int anyunits;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b;
|
|
|
|
|
ship *sh;
|
|
|
|
|
unit *u;
|
|
|
|
|
attrib *a;
|
|
|
|
|
int wants_stats;
|
|
|
|
|
int wants_zugvorlage;
|
|
|
|
|
int wants_addresses;
|
|
|
|
|
seen_region * sd;
|
|
|
|
|
int ix;
|
|
|
|
|
unsigned char op;
|
|
|
|
|
char buf2[80];
|
|
|
|
|
ix = Pow(O_STATISTICS);
|
|
|
|
|
wants_stats = (f->options & ix);
|
|
|
|
|
ix = Pow(O_ZUGVORLAGE);
|
|
|
|
|
wants_zugvorlage = (f->options & ix);
|
|
|
|
|
ix = Pow(O_ADRESSEN);
|
|
|
|
|
wants_addresses = (f->options & ix);
|
|
|
|
|
|
|
|
|
|
if (quiet) {
|
|
|
|
|
printf(" NR");
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
printf(" - Schreibe Report\n");
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, gamedate(f->locale), true);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s, %s/%s (%s)", factionname(f), LOC(f->locale, race[f->race].name[1]),
|
2001-01-25 10:37:55 +01:00
|
|
|
|
neue_gebiete[f->magiegebiet], f->email);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
dh = 0;
|
|
|
|
|
for(a=a_find(f->attribs, &at_faction_special); a; a=a->nexttype) {
|
|
|
|
|
dh++;
|
2001-04-08 19:36:50 +02:00
|
|
|
|
if(fspecials[a->data.sa[0]].maxlevel != 100) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf2, "%s (%d)", fspecials[a->data.sa[0]].name, a->data.sa[1]);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf2, "%s", fspecials[a->data.sa[0]].name);
|
|
|
|
|
}
|
|
|
|
|
if(dh > 1) strcat(buf, ", ");
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
}
|
|
|
|
|
if(dh > 0) centre(F, buf, true);
|
|
|
|
|
dh = 0;
|
|
|
|
|
|
|
|
|
|
if(f->karma > 0) {
|
|
|
|
|
sprintf(buf, "Deine Partei hat %d Karma.", f->karma);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (f->age <= 2) {
|
|
|
|
|
rnl(F);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
sprintf(buf, "Dein Passwort lautet \"%s\".", f->passw);
|
|
|
|
|
centre(F, buf, true);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, "Bitte denke daran, deine Befehle mit dem Betreff"
|
|
|
|
|
" ERESSEA BEFEHLE an eressea@eressea.amber.kn-bremen.de zu senden."
|
|
|
|
|
" Am besten, du verwendest die Befehlsvorlage am Ende des Reports.");
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
sprintf(buf, "Die ersten beiden Z<>ge mu<6D>t du abgeben, sonst wird deine"
|
|
|
|
|
" Partei sofort wieder gel<65>scht, um Karteileichen zu vermeiden.");
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
sprintf(buf, "Mit der ersten Auswertung bekommst du einen Computerreport, "
|
|
|
|
|
"den du mit vielen der Tools auf http://eressea-pbem.de/download.html "
|
|
|
|
|
"benutzen kannst. Wenn du ihn weiterhin bekommen willst, gib einer "
|
|
|
|
|
"deiner Einheiten den Befehl OPTION COMPUTER");
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
|
|
|
|
if (f->options & want(O_SCORE) && f->age > DISPLAYSCORE) {
|
|
|
|
|
sprintf(buf, "Deine Partei hat diese Woche %d Punkte.", f->score);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
sprintf(buf, "(Durchschnitt f<>r Parteien <20>hnlichen Alters ist %d Punkte)",
|
|
|
|
|
average_score_of_age(f->age, f->age / 24 + 1));
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
if (f->race == RC_HUMAN) {
|
|
|
|
|
sprintf(buf, "Deine Partei besteht aus %d Personen in %d Einheiten, davon sind %d Personen Migranten.",
|
|
|
|
|
count_all(f), f->no_units, count_migrants(f));
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
sprintf(buf, "Maximal kann Deine Partei %d Migranten aufnehmen.",
|
|
|
|
|
count_maxmigrants(f));
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf, "Deine Partei besteht aus %d Personen in %d Einheiten.", count_all(f),f->no_units);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (f->age > 1 && f->lastorders != turn) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
if (turn - f->lastorders == 1) {
|
|
|
|
|
centre(F, "Deine Partei hat letzte Runde keinen Zug abgegeben!", true);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf,
|
|
|
|
|
"Deine Partei hat seit %d Runden keinen Zug abgegeben! Wenn du"
|
|
|
|
|
" drei Runden nacheinander keinen Zug abgibst, wird sie"
|
|
|
|
|
" automatisch gel<65>scht.",
|
|
|
|
|
turn - f->lastorders);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insekten-Winter-Warnung */
|
|
|
|
|
if(f->race == RC_INSECT) {
|
|
|
|
|
if(season[month(1)] == 0) {
|
|
|
|
|
strcpy(buf, "Es ist Winter, und Insekten k<>nnen nur in W<>sten oder mit "
|
|
|
|
|
"Hilfe des Nestw<74>rme-Tranks Personen rekrutieren.");
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
} else if(season[month(2)] == 0) {
|
|
|
|
|
strcpy(buf, "Es ist Sp<53>therbst, und diese Woche ist die letzte vor dem "
|
|
|
|
|
"Winter, in der Insekten rekrutieren k<>nnen.");
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s:", LOC(f->locale, "nr_options"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (op = 0; op != MAXOPTIONS; op++) {
|
|
|
|
|
if (f->options & (int) pow(2, op)) {
|
|
|
|
|
scat(" ");
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, options[op]));
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
2001-02-28 19:25:25 +01:00
|
|
|
|
if(op == O_NEWS) {
|
|
|
|
|
attrib *a = a_find(f->attribs, &at_option_news);
|
|
|
|
|
if(!a) {
|
|
|
|
|
/* Zur Altlastenbeseitigung */
|
|
|
|
|
f->options = f->options & ~op;
|
|
|
|
|
} else {
|
|
|
|
|
int sec = a->data.i;
|
|
|
|
|
int i;
|
|
|
|
|
scat("(");
|
|
|
|
|
for(i=1; sec != 0; i *= 2) {
|
|
|
|
|
if(sec & i) {
|
|
|
|
|
icat(i);
|
|
|
|
|
sec = sec & ~i;
|
|
|
|
|
if(sec) scat(",");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scat(")");
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
flag++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (flag > 0) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
}
|
|
|
|
|
/* Der Report soll sp<73>ter einmal durch einen Makroprozessor laufen.
|
|
|
|
|
* (enno) was? wer hat das geschrieben?
|
|
|
|
|
* Momentan ist das wegen der der Mailverschickmimik schwierig. */
|
|
|
|
|
rp_messages(F, f->msgs, f, 0, true, true);
|
|
|
|
|
if(f->battles) {
|
|
|
|
|
struct bmsg * bm;
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(f->locale, "section_battle"), false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rnl(F);
|
|
|
|
|
for (bm=f->battles;bm;bm=bm->next) {
|
2001-02-05 17:11:59 +01:00
|
|
|
|
#ifdef HAVE_SNPRINTF
|
2001-01-25 10:37:55 +01:00
|
|
|
|
snprintf(buf, 80, "In %s findet ein Kampf statt:",
|
|
|
|
|
translate_regions(regionid(bm->r), f));
|
|
|
|
|
#else
|
|
|
|
|
sprintf(buf, "In %s findet ein Kampf statt:",
|
|
|
|
|
translate_regions(regionid(bm->r), f));
|
|
|
|
|
buf[80]=0;
|
|
|
|
|
#endif
|
|
|
|
|
rnl(F);
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
rp_messages(F, bm->msgs, f, 0, true, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a = a_find(f->attribs, &at_reportspell);
|
|
|
|
|
if (a) {
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(f->locale, "section_newspells"), true);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
while (a) {
|
|
|
|
|
report_spell(F, (spellid_t)a->data.i);
|
|
|
|
|
a = a->nexttype;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ch = 0;
|
|
|
|
|
for (a=a_find(f->attribs, &at_showitem);a;a=a->nexttype) {
|
|
|
|
|
const potion_type * ptype = resource2potion(((const item_type*)a->data.v)->rtype);
|
|
|
|
|
requirement * m;
|
|
|
|
|
if (ptype==NULL) continue;
|
|
|
|
|
m = ptype->itype->construction->materials;
|
|
|
|
|
if (ch==0) {
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(f->locale, "section_newpotions"), true);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
ch = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(f->locale, resourcename(ptype->itype->rtype, 0)), true);
|
|
|
|
|
sprintf(buf, "%s %d", LOC(f->locale, "nr_level"), ptype->level);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf, "%s: ", LOC(f->locale, "nr_herbsrequired"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
while (m->number) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, resourcename(oldresourcetype[m->type], 0)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
++m;
|
|
|
|
|
if (m->number) scat(", ");
|
|
|
|
|
}
|
|
|
|
|
centre(F, buf, true);
|
|
|
|
|
rnl(F);
|
|
|
|
|
centre(F, ptype->text, true);
|
|
|
|
|
}
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
centre(F, LOC(f->locale, "nr_alliances"), false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
allies(F, f);
|
|
|
|
|
|
|
|
|
|
rpline(F);
|
|
|
|
|
|
|
|
|
|
anyunits = 0;
|
|
|
|
|
|
|
|
|
|
for (sd = seen; sd!=NULL; sd = sd->next) {
|
|
|
|
|
boolean unit_in_region = false;
|
|
|
|
|
boolean durchgezogen_in_region = false;
|
|
|
|
|
int turm_sieht_region = false;
|
|
|
|
|
|
|
|
|
|
switch (sd->mode) {
|
|
|
|
|
case see_lighthouse:
|
|
|
|
|
turm_sieht_region = true;
|
|
|
|
|
break;
|
|
|
|
|
#ifdef SEE_FAR
|
|
|
|
|
case see_far:
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
case see_travel:
|
|
|
|
|
durchgezogen_in_region = true;
|
|
|
|
|
break;
|
|
|
|
|
case see_unit:
|
|
|
|
|
unit_in_region = true;
|
|
|
|
|
anyunits = true;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
r = sd->r;
|
|
|
|
|
/* Beschreibung */
|
|
|
|
|
|
|
|
|
|
if (unit_in_region) {
|
|
|
|
|
describe(F, r, 0, f);
|
|
|
|
|
if (rterrain(r) != T_OCEAN && rpeasants(r)/TRADE_FRACTION > 0) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
prices(F, r, f);
|
|
|
|
|
}
|
|
|
|
|
guards(F, r, f);
|
|
|
|
|
durchreisende(F, r, f);
|
|
|
|
|
}
|
|
|
|
|
#ifdef SEE_FAR
|
|
|
|
|
else if (sd->mode==see_far) {
|
|
|
|
|
describe(F, r, 3, f);
|
|
|
|
|
guards(F, r, f);
|
|
|
|
|
durchreisende(F, r, f);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else if (turm_sieht_region) {
|
|
|
|
|
describe(F, r, 2, f);
|
|
|
|
|
durchreisende(F, r, f);
|
|
|
|
|
} else {
|
|
|
|
|
describe(F, r, 1, f);
|
|
|
|
|
durchreisende(F, r, f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Statistik */
|
|
|
|
|
|
|
|
|
|
if (wants_stats && unit_in_region == 1)
|
|
|
|
|
statistics(F, r, f);
|
|
|
|
|
|
|
|
|
|
/* Nachrichten an REGION in der Region */
|
|
|
|
|
|
|
|
|
|
if (unit_in_region || durchgezogen_in_region) {
|
|
|
|
|
rp_messages(F, r->msgs, f, 0, true, true);
|
|
|
|
|
}
|
|
|
|
|
/* Burgen und ihre Einheiten */
|
|
|
|
|
|
|
|
|
|
for (b = rbuildings(r); b; b = b->next) {
|
|
|
|
|
rnl(F);
|
|
|
|
|
report_building(F, r, b, f, sd->mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restliche Einheiten */
|
|
|
|
|
|
|
|
|
|
if (sd->mode>=see_lighthouse) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (!u->building && !u->ship) {
|
|
|
|
|
if ((u->faction == f) ||
|
|
|
|
|
(unit_in_region && cansee(f, r, u, 0)) ||
|
|
|
|
|
(durchgezogen_in_region && cansee(f, r, u, -1)) ||
|
|
|
|
|
#ifdef SEE_FAR
|
|
|
|
|
(sd->mode==see_far && cansee(f, r, u, -2)) ||
|
|
|
|
|
#endif
|
|
|
|
|
(turm_sieht_region && cansee(f, r, u, -2)))
|
|
|
|
|
{
|
|
|
|
|
if (dh == 0 && !(rbuildings(r) || r->ships)) {
|
|
|
|
|
dh = 1;
|
|
|
|
|
/* rnl(F); */
|
|
|
|
|
}
|
|
|
|
|
rpunit(F, f, u, 4, sd->mode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Schiffe und ihre Einheiten */
|
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
|
|
|
|
int w = 0;
|
|
|
|
|
faction *of = NULL;
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
|
|
|
|
|
/* Gewicht feststellen */
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->ship == sh && fval(u, FL_OWNER)) {
|
|
|
|
|
of = u->faction;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (of == f) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->ship == sh) {
|
|
|
|
|
w += weight(u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "%s, %s, (%d/%d)",
|
|
|
|
|
shipname(sh),
|
2001-04-22 07:36:50 +02:00
|
|
|
|
LOC(f->locale, sh->type->name[0]),
|
2001-01-25 10:37:55 +01:00
|
|
|
|
(w + 99) / 100, /* +99 weil sonst die Nachkommastellen ignoriert w<>rden */
|
|
|
|
|
shipcapacity(sh) / 100);
|
|
|
|
|
} else {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "%s, %s", shipname(sh),
|
2001-04-22 07:36:50 +02:00
|
|
|
|
LOC(f->locale, sh->type->name[0]));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(sh->type->construction->improvement==NULL); /* sonst ist construction::size nicht ship_type::maxsize */
|
|
|
|
|
if (sh->size!=sh->type->construction->maxsize) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf+strlen(buf), ", %s (%d/%d)",
|
|
|
|
|
LOC(f->locale, "nr_undercons"), sh->size,
|
|
|
|
|
sh->type->construction->maxsize);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
if (sh->damage) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
sprintf(buf+strlen(buf), ", %d%% %s",
|
|
|
|
|
sh->damage*100/(sh->size*DAMAGE_SCALE),
|
|
|
|
|
LOC(f->locale, "nr_damaged"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
if (sh->coast != NODIRECTION) {
|
|
|
|
|
scat(", ");
|
2001-04-22 07:36:50 +02:00
|
|
|
|
scat(LOC(f->locale, coasts[sh->coast]));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ch = 0;
|
|
|
|
|
if (sh->display[0]) {
|
|
|
|
|
scat("; ");
|
|
|
|
|
scat(sh->display);
|
|
|
|
|
|
|
|
|
|
ch = sh->display[strlen(sh->display) - 1];
|
|
|
|
|
}
|
|
|
|
|
if (ch != '!' && ch != '?' && ch != '.')
|
|
|
|
|
scat(".");
|
|
|
|
|
|
|
|
|
|
rparagraph(F, buf, 2, 0);
|
|
|
|
|
|
|
|
|
|
/* Leere Schiffe verursachten sonst segfault! */
|
|
|
|
|
if(shipowner(r,sh) != NULL){
|
|
|
|
|
print_curses(F, sh, TYP_SHIP, sh->attribs,
|
|
|
|
|
(shipowner(r,sh)->faction == f)? 1 : 0, 2);
|
|
|
|
|
} else {
|
|
|
|
|
print_curses(F, sh, TYP_SHIP, sh->attribs, 0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->ship == sh && fval(u, FL_OWNER)) {
|
|
|
|
|
rpunit(F, f, u, 6, sd->mode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
if (u->ship == sh && !fval(u, FL_OWNER))
|
|
|
|
|
rpunit(F, f, u, 6, sd->mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rnl(F);
|
|
|
|
|
rpline(F);
|
|
|
|
|
}
|
|
|
|
|
if (f->no != MONSTER_FACTION) {
|
|
|
|
|
if (!anyunits) {
|
|
|
|
|
rnl(F);
|
2001-04-22 07:36:50 +02:00
|
|
|
|
rparagraph(F, LOC(f->locale, "nr_youaredead"), 0, 0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
if (wants_addresses) {
|
|
|
|
|
list_address(F, f);
|
|
|
|
|
}
|
|
|
|
|
if (wants_zugvorlage) {
|
|
|
|
|
order_template(F, f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
FILE *
|
|
|
|
|
openbatch(void)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
FILE * BAT = NULL;
|
|
|
|
|
|
|
|
|
|
/* falls und mind. ein internet spieler gefunden wird, schreibe den
|
|
|
|
|
* header des batch files. ab nun kann BAT verwendet werden, um zu
|
|
|
|
|
* pruefen, ob netspieler vorhanden sind und ins mailit batch
|
|
|
|
|
* geschrieben werden darf. */
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
|
|
|
|
|
/* bei "internet:" verschicken wir die mail per batchfile. f<>r
|
|
|
|
|
* unix kann man alles in EIN batchfile schreiben, als
|
|
|
|
|
* sogenanntes "herefile". Konnte der batchfile nicht geoeffnet
|
|
|
|
|
* werden, schreiben wir die reports einzeln. der BAT file wird
|
|
|
|
|
* nur gemacht, wenn es auch internet benutzer gibt. */
|
|
|
|
|
|
|
|
|
|
if (f->email) {
|
|
|
|
|
sprintf(buf, "%s/mailit", reportpath());
|
|
|
|
|
if ((BAT = fopen(buf, "w")) == NULL)
|
|
|
|
|
puts("* Fehler: mailit konnte nicht ge<67>ffnet werden!");
|
|
|
|
|
else
|
|
|
|
|
fprintf(BAT,
|
|
|
|
|
"#!/bin/sh\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"# MAILIT shell file, vom Eressea Host generiert\n"
|
|
|
|
|
"#\n"
|
|
|
|
|
"# Verwendung: nohup mailit &\n"
|
|
|
|
|
"#\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"PATH=%s\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"chmod 755 *.sh\n"
|
|
|
|
|
"\n"
|
|
|
|
|
,MAILITPATH);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return BAT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
closebatch(FILE * BAT)
|
|
|
|
|
{
|
|
|
|
|
if (BAT) {
|
|
|
|
|
fputs("\n", BAT);
|
|
|
|
|
fclose(BAT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
base36conversion(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
if (forbiddenid(u->no)) {
|
|
|
|
|
uunhash(u);
|
|
|
|
|
u->no = newunitid();
|
|
|
|
|
uhash(u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void init_intervals(void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_MERIAN
|
|
|
|
|
|
|
|
|
|
#define xp(r, f) ((region_x((r),(f)))*2 + region_y((r),(f)))
|
|
|
|
|
#define yp(r, f) (region_y((r),(f)))
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
merian(FILE * out, faction * f)
|
|
|
|
|
{
|
|
|
|
|
int x1 = INT_MAX, x2=INT_MIN, y1=INT_MAX, y2=INT_MIN;
|
|
|
|
|
region *left=0, *right=0, *top=0, *bottom=0;
|
|
|
|
|
char ** line;
|
|
|
|
|
char * c;
|
|
|
|
|
int y, xw;
|
|
|
|
|
|
|
|
|
|
seen_region * sd;
|
|
|
|
|
if (!seen) return;
|
|
|
|
|
for (sd = seen; sd!=NULL; sd = sd->next) {
|
|
|
|
|
region * r = sd->r;
|
|
|
|
|
if (r->planeid != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!left || xp(r, f)<xp(left, f)) left=r;
|
|
|
|
|
if (!right || xp(r, f)>xp(right, f)) right=r;
|
|
|
|
|
if (!top || yp(r, f)>yp(top, f)) top=r;
|
|
|
|
|
if (!bottom || yp(r, f)<yp(bottom, f)) bottom=r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!left) return; /* Keine normale Region gesehen */
|
|
|
|
|
|
|
|
|
|
x1 = xp(left, f);
|
|
|
|
|
x2 = xp(right, f)+1;
|
|
|
|
|
y1 = yp(bottom, f);
|
|
|
|
|
y2 = yp(top, f)+1;
|
|
|
|
|
|
|
|
|
|
xw = abs(x1); xw = max(xw, x2);
|
|
|
|
|
if (xw>99) xw = 3;
|
|
|
|
|
else if (xw>9) xw = 2;
|
|
|
|
|
else xw = 1;
|
|
|
|
|
|
|
|
|
|
fputs("CR-Version: 42\nMERIAN Version 1.02\nKartenart: Hex(Standard)\n\nLEGENDE\nHochland = H\nGletscher = G\nGebirge = B\nWald = W\nSumpf = S\nOzean = .\nW<EFBFBD>ste = D\nEbene = E\n\n", out);
|
|
|
|
|
|
|
|
|
|
line = (char**)calloc(1, (y2-y1)*sizeof(char*));
|
|
|
|
|
c = (char*)calloc(1, (y2-y1)*((x2-x1)*sizeof(char)+13));
|
|
|
|
|
memset(c, ' ', (y2-y1)*((x2-x1)*sizeof(char)+13));
|
|
|
|
|
{
|
|
|
|
|
int width = 1+x2-x1;
|
|
|
|
|
int lx = region_x(top, f) - (xp(top, f)-x1) / 2;
|
|
|
|
|
int i;
|
|
|
|
|
if ((y2-y1) % 2 ==0) ++lx;
|
|
|
|
|
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y2);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (x<0)?'-':(x>0)?'+':' ');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
switch (xw) {
|
|
|
|
|
case 3:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y2);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (abs(x)/100)?((abs(x)/100)+'0'):' ');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
case 2:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y2);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (abs(x)%100)/10?((abs(x)%100)/10+'0'):(abs(x)<100?' ':'0'));
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
default:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+(i/2);
|
|
|
|
|
int o = abs(x1-y2);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", abs(x)%10+'0');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
}
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int o = abs(x1-y2);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
putc('/', out);
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
for (y=y1;y!=y2;++y) {
|
|
|
|
|
line[y-y1] = c + (y-y1)*((x2-x1)*sizeof(char)+13);
|
|
|
|
|
sprintf(line[y-y1], "%4d", y);
|
|
|
|
|
line[y-y1][4] = ' ';
|
|
|
|
|
sprintf(line[y-y1]+7+(x2-x1), "%4d", y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (sd = seen; sd!=NULL; sd = sd->next) {
|
|
|
|
|
region * r = sd->r;
|
|
|
|
|
|
|
|
|
|
if (getplane(r))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
line[yp(r, f)-y1][5+(xp(r, f)-x1)] = ' ';
|
|
|
|
|
line[yp(r, f)-y1][6+(xp(r, f)-x1)] = terrain[rterrain(r)].symbol;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* print header */
|
|
|
|
|
for (y=y1;y!=y2;++y) {
|
|
|
|
|
fputs(line[y2-y-1], out);
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
int width = 1+x2-x1;
|
|
|
|
|
int lx = region_x(bottom, f) - (xp(bottom, f)-x1) / 2;
|
|
|
|
|
int i;
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int o = abs(x1-y1);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
putc('/', out);
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y1);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (x<0)?'-':(x>0)?'+':' ');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
switch (xw) {
|
|
|
|
|
case 3:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y1);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (abs(x)/100)?((abs(x)/100)+'0'):' ');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
case 2:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y1);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", (abs(x)%100)/10?((abs(x)%100)/10+'0'):(abs(x)<100?' ':'0'));
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
default:
|
|
|
|
|
fputs(" ", out);
|
|
|
|
|
for (i=0;i!=width;++i) {
|
|
|
|
|
int x = lx+((i+1)/2);
|
|
|
|
|
int o = abs(x1-y1);
|
|
|
|
|
if (i%2 == o % 2)
|
|
|
|
|
fprintf(out, "%c", abs(x)%10+'0');
|
|
|
|
|
else putc(' ', out);
|
|
|
|
|
}
|
|
|
|
|
putc('\n', out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(c);
|
|
|
|
|
free(line);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
seen_region * seen;
|
|
|
|
|
seen_region * reuse;
|
|
|
|
|
seen_region** append;
|
|
|
|
|
seen_region * last;
|
|
|
|
|
|
|
|
|
|
#define MAXSEEHASH 4095
|
|
|
|
|
seen_region * seehash[MAXSEEHASH];
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
seen_done(void)
|
|
|
|
|
{
|
|
|
|
|
while (seen) {
|
|
|
|
|
seen_region * r = seen;
|
|
|
|
|
seen = seen->next;
|
|
|
|
|
free(r);
|
|
|
|
|
}
|
|
|
|
|
while (reuse) {
|
|
|
|
|
seen_region * r = reuse;
|
|
|
|
|
reuse = reuse->next;
|
|
|
|
|
free(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if FAST_SEEN
|
2001-04-16 16:34:19 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
init_intervals()
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
attrib * a;
|
|
|
|
|
for (a=a_find(r->attribs, &at_travelunit);a;a=a->nexttype) {
|
|
|
|
|
unit * v = (unit*)a->data.v;
|
|
|
|
|
faction * f = v->faction;
|
|
|
|
|
if (!f) continue;
|
|
|
|
|
if (!f->first)
|
|
|
|
|
{
|
|
|
|
|
assert(!f->last);
|
|
|
|
|
f->first = r;
|
|
|
|
|
}
|
|
|
|
|
f->last = r->next;
|
|
|
|
|
}
|
|
|
|
|
for (a=a_find(r->attribs, &at_lighthouse);a;a=a->nexttype) {
|
|
|
|
|
building * b = (building*)a->data.v;
|
|
|
|
|
region * br = b->region;
|
|
|
|
|
if (!b->region) continue;
|
|
|
|
|
for (u=br->units;u;u=u->next) {
|
|
|
|
|
faction * f = u->faction;
|
|
|
|
|
if (!f->first)
|
|
|
|
|
{
|
|
|
|
|
assert(!f->last);
|
|
|
|
|
f->first = r;
|
|
|
|
|
}
|
|
|
|
|
f->last = r->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
faction * f = u->faction;
|
|
|
|
|
if (!f->first)
|
|
|
|
|
{
|
|
|
|
|
assert(!f->last);
|
|
|
|
|
f->first = r;
|
|
|
|
|
}
|
|
|
|
|
f->last = r->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
add_seen(region * r, unsigned char mode, boolean dis)
|
|
|
|
|
{
|
|
|
|
|
seen_region * find;
|
|
|
|
|
|
|
|
|
|
int index = abs((r->x & 0xffff) + ((r->y) << 16)) % MAXSEEHASH;
|
|
|
|
|
for (find=seehash[index];find;find=find->nextHash) {
|
|
|
|
|
if (find->r==r) {
|
|
|
|
|
if (find->mode < mode) {
|
|
|
|
|
if (find->mode<=see_neighbour && find->next) {
|
|
|
|
|
find->next->prev = find->prev;
|
|
|
|
|
if (find->prev) find->prev->next = find->next;
|
|
|
|
|
else seen = find->next;
|
|
|
|
|
last->next = find;
|
|
|
|
|
find->prev = last;
|
|
|
|
|
find->next = NULL;
|
|
|
|
|
last = find;
|
|
|
|
|
append = &last->next;
|
|
|
|
|
}
|
|
|
|
|
find->mode = mode;
|
|
|
|
|
find->disbelieves |= dis;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!reuse) reuse = (seen_region*)calloc(1, sizeof(seen_region));
|
|
|
|
|
*append = reuse;
|
|
|
|
|
reuse = reuse->next;
|
|
|
|
|
(*append)->next = NULL;
|
|
|
|
|
(*append)->prev = last;
|
|
|
|
|
if (last) last->next = *append;
|
|
|
|
|
last = *append;
|
|
|
|
|
(*append)->nextHash = seehash[index];
|
|
|
|
|
seehash[index] = *append;
|
|
|
|
|
(*append)->r = r;
|
|
|
|
|
(*append)->mode = mode;
|
|
|
|
|
(*append)->disbelieves = dis;
|
|
|
|
|
append = &(*append)->next;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define DBG_CACHE 1
|
|
|
|
|
#if DBG_CACHE
|
|
|
|
|
int chits = 0;
|
|
|
|
|
int ctries = 0;
|
|
|
|
|
#endif
|
|
|
|
|
static void
|
|
|
|
|
prepare_report(faction * f)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
region * end = lastregion(f);
|
|
|
|
|
|
|
|
|
|
append = &reuse;
|
|
|
|
|
memset(seehash, 0, sizeof(seehash));
|
|
|
|
|
while (*append) append = &(*append)->next;
|
|
|
|
|
*append = seen;
|
|
|
|
|
seen = NULL;
|
|
|
|
|
last = NULL;
|
|
|
|
|
append = &seen;
|
|
|
|
|
for (r = firstregion(f); r != end; r = r->next)
|
|
|
|
|
{
|
|
|
|
|
attrib *ru;
|
|
|
|
|
unit * u;
|
|
|
|
|
unsigned char mode = see_none;
|
|
|
|
|
boolean dis = false;
|
|
|
|
|
#if DBG_CACHE
|
|
|
|
|
++ctries;
|
|
|
|
|
#endif
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->faction == f) {
|
|
|
|
|
if (u->race != RC_SPELL || u->number == RS_FARVISION) {
|
|
|
|
|
mode = see_unit;
|
|
|
|
|
if (fval(u, FL_DISBELIEVES)) {
|
|
|
|
|
dis = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode==see_none) for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
|
|
|
|
|
unit * u = (unit*)ru->data.v;
|
|
|
|
|
if (u->faction == f) {
|
|
|
|
|
mode = see_travel;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode==see_none && rterrain(r) == T_OCEAN) {
|
|
|
|
|
if (check_leuchtturm(r, f)) mode = see_lighthouse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode == see_none)
|
|
|
|
|
continue;
|
|
|
|
|
#if DBG_CACHE
|
|
|
|
|
else ++chits;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
add_seen(r, mode, dis);
|
|
|
|
|
/* nicht, wenn Verwirrung herrscht: */
|
|
|
|
|
if (!is_cursed(r->attribs, C_REGCONF, 0)) {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
|
|
|
|
|
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
|
|
|
|
|
region * r2 = rconnect(r, dir);
|
|
|
|
|
if (r2) {
|
|
|
|
|
border * b = get_borders(r, r2);
|
|
|
|
|
while (b) {
|
|
|
|
|
if (!b->type->transparent(b, f)) break;
|
|
|
|
|
b = b->next;
|
|
|
|
|
}
|
|
|
|
|
#ifdef SEE_FAR
|
|
|
|
|
if (!b) {
|
|
|
|
|
if (add_seen(r2, see_far, false)) {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
|
|
|
|
|
region * r3 = rconnect(r2, dir);
|
|
|
|
|
if (r3) {
|
|
|
|
|
border * b = get_borders(r2, r3);
|
|
|
|
|
while (b) {
|
|
|
|
|
if (!b->type->transparent(b, f)) break;
|
|
|
|
|
b = b->next;
|
|
|
|
|
}
|
|
|
|
|
if (!b) add_seen(r3, see_neighbour, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (!b) add_seen(r2, see_neighbour, false);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if DBG_CACHE
|
|
|
|
|
if (!quiet)
|
|
|
|
|
printf(" - cache hits: %.2f%%\n", 100*chits/(double)ctries);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define FMAXHASH 1023
|
|
|
|
|
|
|
|
|
|
struct fsee {
|
|
|
|
|
struct fsee * nexthash;
|
|
|
|
|
faction * f;
|
|
|
|
|
struct see {
|
|
|
|
|
struct see * next;
|
|
|
|
|
faction * seen;
|
|
|
|
|
unit * proof;
|
|
|
|
|
} * see;
|
|
|
|
|
} * fsee[FMAXHASH];
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
reports(void)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
boolean gotit;
|
|
|
|
|
FILE *shfp, *F, *BAT;
|
|
|
|
|
int wants_report, wants_computer_report,
|
|
|
|
|
wants_compressed, wants_bzip2;
|
|
|
|
|
|
|
|
|
|
nmr_warnings();
|
|
|
|
|
#ifdef DMALLOC
|
|
|
|
|
assert(dmalloc_verify ( NULL ));
|
|
|
|
|
#endif
|
2001-02-03 14:45:35 +01:00
|
|
|
|
makedir(reportpath(), 0700);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-01-27 19:15:52 +01:00
|
|
|
|
if (global.data_version<BASE36_VERSION) base36conversion();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* <20>ffnet file BAT (mailit batch file) */
|
|
|
|
|
|
|
|
|
|
BAT = openbatch();
|
|
|
|
|
|
|
|
|
|
wants_report = 1 << O_REPORT;
|
|
|
|
|
wants_computer_report = 1 << O_COMPUTER;
|
|
|
|
|
wants_compressed = 1 << O_COMPRESS;
|
|
|
|
|
wants_bzip2 = 1 << O_BZIP2;
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
report_donations();
|
|
|
|
|
#if FAST_SEEN
|
|
|
|
|
init_intervals();
|
|
|
|
|
#endif
|
|
|
|
|
remove_empty_units();
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
attrib * a = a_find(f->attribs, &at_reportspell);
|
|
|
|
|
current_faction = f;
|
|
|
|
|
gotit = false;
|
|
|
|
|
|
|
|
|
|
if (quiet) {
|
|
|
|
|
printf("Reports f<>r %s: ", factionname(f));
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
|
|
|
|
else printf("%s\n", factionname(f));
|
|
|
|
|
prepare_report(f);
|
|
|
|
|
if (!nonr && (f->options & wants_report))
|
|
|
|
|
{
|
|
|
|
|
sprintf(buf, "%s/%s.nr", reportpath(), factionid(f));
|
|
|
|
|
F = cfopen(buf, "wt");
|
|
|
|
|
if (F) {
|
|
|
|
|
report(F, f);
|
|
|
|
|
fclose(F);
|
|
|
|
|
gotit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!nocr && (f->options & wants_computer_report || f->age<3))
|
|
|
|
|
{
|
|
|
|
|
sprintf(buf, "%s/%s.cr", reportpath(), factionid(f));
|
|
|
|
|
F = cfopen(buf, "wt");
|
|
|
|
|
if (F) {
|
|
|
|
|
report_computer(F, f);
|
|
|
|
|
fclose(F);
|
|
|
|
|
gotit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (f->email && BAT) {
|
2001-02-04 14:20:12 +01:00
|
|
|
|
sprintf(buf, "%s/%s.sh", reportpath(), factionid(f));
|
|
|
|
|
shfp = fopen(buf, "w");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fprintf(shfp,"#!/bin/sh\n\nPATH=%s\n\n",MAILITPATH);
|
|
|
|
|
fprintf(shfp,"if [ $# -ge 1 ]; then\n");
|
|
|
|
|
fprintf(shfp,"\taddr=$1\n");
|
|
|
|
|
fprintf(shfp,"else\n");
|
2001-02-04 14:20:12 +01:00
|
|
|
|
fprintf(shfp,"\taddr=%s\n", f->email);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fprintf(shfp,"fi\n\n");
|
|
|
|
|
|
2001-02-04 14:20:12 +01:00
|
|
|
|
fprintf(BAT, "\n\ndate;echo %s\n", f->email);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-02-04 14:47:25 +01:00
|
|
|
|
if (f->no > 0 && f->options & wants_compressed) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if(f->age == 1) {
|
|
|
|
|
fprintf(BAT, "ls %s.nr %s.cr ../newbie.txt | zip -m -j -9 -@ %s.zip\n",
|
|
|
|
|
factionid(f), factionid(f), factionid(f));
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(BAT, "ls %s.nr %s.cr | zip -m -j -9 -@ %s.zip\n",
|
|
|
|
|
factionid(f), factionid(f), factionid(f));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(shfp, "eresseamail.zipped $addr \"%s %s\" \"%s-%d.zip\" "
|
|
|
|
|
"%s.zip\n", global.gamename, gamedate_short(), factionid(f), turn, factionid(f));
|
|
|
|
|
|
|
|
|
|
} else if(f->options & wants_bzip2) {
|
|
|
|
|
|
|
|
|
|
if (f->age == 1) {
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"text/plain\" \"Willkommen\" ../newbie.txt");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(BAT, "bzip2 -9v `ls %s.nr %s.cr`\n",
|
|
|
|
|
factionid(f), factionid(f));
|
|
|
|
|
|
|
|
|
|
fprintf(shfp, "eresseamail.bzip2 $addr \"%s %s\"", global.gamename, gamedate_short());
|
|
|
|
|
|
|
|
|
|
if (!nonr && f->options & wants_report)
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"application/x-bzip2\" \"Report\" %s.nr.bz2",
|
|
|
|
|
factionid(f));
|
|
|
|
|
|
|
|
|
|
if (!nocr && (f->options & wants_computer_report || f->age<3))
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"application/x-bzip2\" \"Computer-Report\" %s.cr.bz2",
|
|
|
|
|
factionid(f));
|
|
|
|
|
#ifdef USE_MERIAN
|
|
|
|
|
if (!nomer && f->options & wants_merian)
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"application/x-bzip2\" \"Merian-Karte\" %s.mer.bz2",
|
|
|
|
|
factionid(f));
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
fprintf(shfp, MAIL " $addr \"%s %s\"", global.gamename, gamedate_short());
|
|
|
|
|
|
|
|
|
|
if (f->age == 1) {
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"text/plain\" \"Willkommen\" ../newbie.txt");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nonr && f->options & wants_report)
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"text/plain\" \"Report\" %s.nr",
|
|
|
|
|
factionid(f));
|
|
|
|
|
|
|
|
|
|
if (!nocr && (f->options & wants_computer_report || f->age<3))
|
|
|
|
|
fprintf(shfp,
|
|
|
|
|
" \\\n\t\"text/x-eressea-cr\" \"Computer-Report\" %s.cr",
|
|
|
|
|
factionid(f));
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-04 14:20:12 +01:00
|
|
|
|
fprintf(BAT, ". %s.sh %s\n", factionid(f), f->email);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fclose(shfp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!gotit)
|
|
|
|
|
printf("* Fehler: Kein Report f<>r Partei Nr. %s!\n",
|
|
|
|
|
factionid(f));
|
|
|
|
|
while (a) {
|
|
|
|
|
attrib * a_old = a;
|
|
|
|
|
a = a->nexttype;
|
|
|
|
|
a_remove(&f->attribs, a_old);
|
|
|
|
|
}
|
|
|
|
|
if (quiet)
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
/* schliesst BAT und verschickt Zeitungen und Kommentare */
|
|
|
|
|
current_faction = NULL;
|
|
|
|
|
seen_done();
|
|
|
|
|
closebatch(BAT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
report_cleanup(void)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0;i!=FMAXHASH;++i) {
|
|
|
|
|
while (fsee[i]) {
|
|
|
|
|
struct fsee * fs = fsee[i]->nexthash;
|
|
|
|
|
free(fsee[i]);
|
|
|
|
|
fsee[i] = fs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unit *
|
|
|
|
|
can_find(faction * f, faction * f2)
|
|
|
|
|
{
|
|
|
|
|
int key = f->no % FMAXHASH;
|
|
|
|
|
struct fsee * fs = fsee[key];
|
|
|
|
|
struct see * ss;
|
|
|
|
|
if (f==f2) return f->units;
|
|
|
|
|
while (fs && fs->f!=f) fs=fs->nexthash;
|
|
|
|
|
if (!fs) return NULL;
|
|
|
|
|
ss=fs->see;
|
|
|
|
|
while (ss && ss->seen!=f2) ss=ss->next;
|
|
|
|
|
if (ss) {
|
2001-04-22 20:14:07 +02:00
|
|
|
|
/* bei TARNE PARTEI yxz muss die Partei von unit proof nicht
|
|
|
|
|
* wirklich Partei f2 sein! */
|
|
|
|
|
/* assert(ss->proof->faction==f2); */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return ss->proof;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2001-04-14 14:11:45 +02:00
|
|
|
|
add_find(faction * f, unit * u, faction *f2)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
/* faction f sees f2 through u */
|
|
|
|
|
int key = f->no % FMAXHASH;
|
|
|
|
|
struct fsee ** fp = &fsee[key];
|
|
|
|
|
struct fsee * fs;
|
|
|
|
|
struct see ** sp;
|
|
|
|
|
struct see * ss;
|
|
|
|
|
while (*fp && (*fp)->f!=f) fp=&(*fp)->nexthash;
|
|
|
|
|
if (!*fp) {
|
|
|
|
|
fs = *fp = calloc(sizeof(struct fsee), 1);
|
|
|
|
|
fs->f = f;
|
|
|
|
|
} else fs = *fp;
|
|
|
|
|
sp = &fs->see;
|
|
|
|
|
while (*sp && (*sp)->seen!=f2) sp=&(*sp)->next;
|
|
|
|
|
if (!*sp) {
|
|
|
|
|
ss = *sp = calloc(sizeof(struct see), 1);
|
|
|
|
|
ss->proof = u;
|
|
|
|
|
ss->seen = f2;
|
|
|
|
|
} else ss = *sp;
|
|
|
|
|
ss->proof = u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
update_find(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
static boolean initial = true;
|
|
|
|
|
|
|
|
|
|
if (initial) for (r=regions;r;r=r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
faction * lastf = u->faction;
|
|
|
|
|
unit * u2;
|
|
|
|
|
for (u2=r->units;u2;u2=u2->next) {
|
|
|
|
|
if (u2->faction==lastf || u2->faction==u->faction)
|
|
|
|
|
continue;
|
|
|
|
|
if (seefaction(u->faction, r, u2, 0)) {
|
2001-04-14 14:11:45 +02:00
|
|
|
|
attrib *a = a_find(u2->attribs, &at_otherfaction);
|
|
|
|
|
if(a) {
|
|
|
|
|
faction *f = findfaction(a->data.i);
|
|
|
|
|
lastf=f;
|
|
|
|
|
add_find(u->faction, u2, f);
|
|
|
|
|
} else {
|
|
|
|
|
lastf=u2->faction;
|
|
|
|
|
add_find(u->faction, u2, u2->faction);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
initial = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean
|
|
|
|
|
kann_finden(faction * f1, faction * f2)
|
|
|
|
|
{
|
|
|
|
|
update_find();
|
|
|
|
|
return (boolean)(can_find(f1, f2)!=NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******* summary *******/
|
|
|
|
|
int dropouts[2];
|
|
|
|
|
int * age = NULL;
|
|
|
|
|
|
|
|
|
|
typedef struct summary {
|
|
|
|
|
int waffen;
|
|
|
|
|
int factions;
|
|
|
|
|
int artefakte;
|
|
|
|
|
int ruestungen;
|
|
|
|
|
int schiffe;
|
|
|
|
|
int gebaeude;
|
|
|
|
|
int maxskill;
|
|
|
|
|
int inhabitedregions;
|
|
|
|
|
int peasants;
|
|
|
|
|
int peasantmoney;
|
|
|
|
|
int nunits;
|
|
|
|
|
int playerpop;
|
|
|
|
|
int playermoney;
|
|
|
|
|
int armed_men;
|
|
|
|
|
int poprace[MAXRACES];
|
|
|
|
|
int factionrace[MAXRACES];
|
|
|
|
|
int landregionen;
|
|
|
|
|
int regionen_mit_spielern;
|
|
|
|
|
int landregionen_mit_spielern;
|
|
|
|
|
int orkifizierte_regionen;
|
|
|
|
|
int spielerpferde;
|
|
|
|
|
int pferde;
|
|
|
|
|
} summary;
|
|
|
|
|
|
|
|
|
|
summary *
|
|
|
|
|
make_summary(boolean count_new)
|
|
|
|
|
{
|
|
|
|
|
char sk;
|
|
|
|
|
faction *f;
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
summary * s = calloc(1, sizeof(summary));
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
f->nregions = 0;
|
|
|
|
|
f->nunits = 0;
|
|
|
|
|
f->number = 0;
|
|
|
|
|
f->money = 0;
|
|
|
|
|
if (count_new == true || f->age > 0) s->factions++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Alles z<>hlen */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
s->pferde += rhorses(r);
|
|
|
|
|
s->schiffe += listlen(r->ships);
|
|
|
|
|
s->gebaeude += listlen(r->buildings);
|
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
s->landregionen++;
|
|
|
|
|
if (r->units) {
|
|
|
|
|
s->landregionen_mit_spielern++;
|
|
|
|
|
}
|
|
|
|
|
if (fval(r, RF_ORCIFIED)) {
|
|
|
|
|
s->orkifizierte_regionen++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (r->units) {
|
|
|
|
|
s->regionen_mit_spielern++;
|
|
|
|
|
}
|
|
|
|
|
if (rpeasants(r) || r->units) {
|
|
|
|
|
s->inhabitedregions++;
|
|
|
|
|
s->peasants += rpeasants(r);
|
|
|
|
|
s->peasantmoney += rmoney(r);
|
|
|
|
|
|
|
|
|
|
/* Einheiten Info. nregions darf nur einmal pro Partei
|
|
|
|
|
* incrementiert werden. */
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = u->next) freset(u->faction, FL_DH);
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
f = u->faction;
|
|
|
|
|
if (u->faction->no != MONSTER_FACTION) {
|
|
|
|
|
s->nunits++;
|
|
|
|
|
s->playerpop += u->number;
|
|
|
|
|
s->spielerpferde += get_item(u, I_HORSE);
|
|
|
|
|
s->playermoney += get_money(u);
|
|
|
|
|
s->armed_men += armedmen(u);
|
|
|
|
|
s->waffen += get_item(u, I_SWORD);
|
|
|
|
|
s->waffen += get_item(u, I_SPEAR);
|
|
|
|
|
s->waffen += get_item(u, I_CATAPULT);
|
|
|
|
|
s->waffen += get_item(u, I_CROSSBOW);
|
|
|
|
|
s->waffen += get_item(u, I_LONGBOW);
|
|
|
|
|
s->waffen += get_item(u, I_RUNESWORD);
|
|
|
|
|
|
|
|
|
|
s->ruestungen += get_item(u, I_CHAIN_MAIL);
|
|
|
|
|
s->ruestungen += get_item(u, I_PLATE_ARMOR);
|
|
|
|
|
|
|
|
|
|
#ifdef COMPATIBILITY
|
|
|
|
|
s->ruestungen += get_item(u, I_CLOAK_OF_INVULNERABILITY);
|
|
|
|
|
|
|
|
|
|
s->artefakte += get_item(u, I_AMULET_OF_DARKNESS);
|
|
|
|
|
s->artefakte += get_item(u, I_AMULET_OF_HEALING);
|
|
|
|
|
s->artefakte += get_item(u, I_CLOAK_OF_INVULNERABILITY);
|
|
|
|
|
s->artefakte += get_item(u, I_SHIELDSTONE);
|
|
|
|
|
s->artefakte += get_item(u, I_STAFF_OF_FIRE);
|
|
|
|
|
s->artefakte += get_item(u, I_STAFF_OF_LIGHTNING);
|
|
|
|
|
s->artefakte += get_item(u, I_WAND_OF_TELEPORTATION);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
s->artefakte += get_item(u, I_AMULET_OF_TRUE_SEEING);
|
|
|
|
|
s->artefakte += get_item(u, I_RING_OF_INVISIBILITY);
|
|
|
|
|
s->artefakte += get_item(u, I_RING_OF_POWER);
|
|
|
|
|
s->artefakte += get_item(u, I_RUNESWORD);
|
|
|
|
|
|
|
|
|
|
s->spielerpferde += get_item(u, I_HORSE);
|
|
|
|
|
|
|
|
|
|
for (sk = 0; sk < MAXSKILLS; sk++) {
|
|
|
|
|
int aktskill;
|
|
|
|
|
aktskill = eff_skill(u, sk, r);
|
|
|
|
|
if (aktskill > s->maxskill) s->maxskill = aktskill;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(f, FL_DH)) {
|
|
|
|
|
f->nregions++;
|
|
|
|
|
fset(f, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f->nunits++;
|
|
|
|
|
f->number += u->number;
|
|
|
|
|
f->money += get_money(u);
|
|
|
|
|
s->poprace[u->race] += u->number;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* jetzt noch parteienweise z<>hlen */
|
|
|
|
|
/* Problem mit Monsterpartei ... */
|
|
|
|
|
for (f = factions; f; f = f->next) if (f->no!=MONSTER_FACTION) {
|
|
|
|
|
if (count_new == true || f->age > 0) s->factionrace[f->race]++;
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
pcomp(int i, int j)
|
|
|
|
|
{
|
|
|
|
|
sprintf(buf, "%d (%s%d)", i, (i>=j)?"+":"", i-j);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
rcomp(int i, int j)
|
|
|
|
|
{
|
|
|
|
|
sprintf(buf, "%d (%s%d,%s%d%%)",
|
|
|
|
|
i, (i>=j)?"+":"", i-j, (i>=j)?"+":"",j?((i-j)*100)/j:0);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
writemonument(void)
|
|
|
|
|
{
|
|
|
|
|
FILE * F;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b;
|
|
|
|
|
building *buildings[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
|
|
|
|
int size[7] = {0,0,0,0,0,0,0};
|
|
|
|
|
int i, j, ra;
|
|
|
|
|
int count = 0;
|
|
|
|
|
unit *owner;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (b = r->buildings; b; b = b->next) {
|
|
|
|
|
if (b->type == &bt_monument && b->display && *b->display) {
|
|
|
|
|
freset(b, FL_DH);
|
|
|
|
|
count++;
|
|
|
|
|
if(b->size > size[6]) {
|
|
|
|
|
for(i=0; i <= 6; i++) if(b->size >= size[i]) {
|
|
|
|
|
for(j=5;j >= i; j--) {
|
|
|
|
|
size[j+1] = size[j];
|
|
|
|
|
buildings[j+1] = buildings[j];
|
|
|
|
|
}
|
|
|
|
|
buildings[i] = b;
|
|
|
|
|
size[i] = b->size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i=0; i <= 6; i++) if(buildings[i]) {
|
|
|
|
|
fset(buildings[i], FL_DH);
|
|
|
|
|
}
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
sprintf(zText, "%s/news-monument", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (!F) return;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fprintf(F, "\n--- maintitle ---\n\n");
|
|
|
|
|
for(i = 0; i<=6; i++) {
|
|
|
|
|
if (buildings[i] != NULL) {
|
|
|
|
|
fprintf(F, "In %s", rname(buildings[i]->region, NULL));
|
|
|
|
|
if ((owner=buildingowner(buildings[i]->region,buildings[i]))!=NULL && !fval(owner,FL_PARTEITARNUNG)) {
|
|
|
|
|
fprintf(F, ", Eigent<6E>mer: %s", factionname(owner->faction));
|
|
|
|
|
}
|
|
|
|
|
fprintf(F, "\n\n");
|
|
|
|
|
report_building(F, buildings[i]->region, buildings[i], findfaction(0), see_neighbour);
|
|
|
|
|
fprintf(F, "\n\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(F, "\n--- newcomer ---\n\n");
|
|
|
|
|
|
|
|
|
|
if(count > 7) {
|
|
|
|
|
ra = rand()%(count-7);
|
|
|
|
|
j = 0;
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (b = r->buildings; b; b = b->next) {
|
|
|
|
|
if (b->type == &bt_monument && b->display && *b->display && !fval(b, FL_DH)) {
|
|
|
|
|
j++;
|
|
|
|
|
if(j == ra) {
|
|
|
|
|
fprintf(F, "In %s", rname(b->region, NULL));
|
|
|
|
|
if ((owner=buildingowner(b->region,b))!=NULL && !fval(owner,FL_PARTEITARNUNG)) {
|
|
|
|
|
fprintf(F, ", Eigent<6E>mer: %s", factionname(owner->faction));
|
|
|
|
|
}
|
|
|
|
|
fprintf(F, "\n\n");
|
|
|
|
|
report_building(F, b->region, b, findfaction(0), see_neighbour);
|
|
|
|
|
fprintf(F, "\n\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(F);
|
|
|
|
|
|
|
|
|
|
#ifdef OLD_ITEMS
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
sprintf(zText, "%s/news-silly", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (!F) return;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (f=factions;f;f=f->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
int k;
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (u=f->units;u;u=u->nextF) {
|
|
|
|
|
count += get_herb(u, h);
|
|
|
|
|
}
|
|
|
|
|
for (i=0;i!=3;++i) if (count<fjord[i].size) break;
|
|
|
|
|
if (i) {
|
|
|
|
|
for (k=0;k<i-1;++k) fjord[k] = fjord[k+1];
|
|
|
|
|
fjord[i-1].size=count;
|
|
|
|
|
fjord[i-1].f=f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fprintf(F, "\n\nBesitzer der gr<67><72>ten %shaufen:\n", herbdata[0][h]);
|
|
|
|
|
for (i=0;i!=3;++i) {
|
|
|
|
|
fprintf(F, " %s (%d St<53>ck)\n", factionname(fjord[2-i].f), fjord[2-i].size);
|
|
|
|
|
}
|
|
|
|
|
fclose(F);
|
|
|
|
|
#else
|
|
|
|
|
printf("!! news-silly not implemented\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-31 00:16:17 +01:00
|
|
|
|
static void
|
2001-02-10 14:20:33 +01:00
|
|
|
|
writeadresses(void)
|
2001-01-31 00:16:17 +01:00
|
|
|
|
{
|
|
|
|
|
faction *f;
|
2001-02-28 19:25:25 +01:00
|
|
|
|
FILE *F;
|
2001-01-31 00:16:17 +01:00
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
sprintf(zText, "%s/adressen", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (!F) return;
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if (f->no != MONSTER_FACTION && !nonplayer_race(f->race)) {
|
2001-01-31 00:16:17 +01:00
|
|
|
|
fprintf(F, "%s:%s:%s\n", factionname(f), f->email, f->banner);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose(F);
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-28 19:25:25 +01:00
|
|
|
|
static void
|
|
|
|
|
writenewssubscriptions(void)
|
|
|
|
|
{
|
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
FILE *F;
|
|
|
|
|
|
|
|
|
|
sprintf(zText, "%s/news-subscriptions", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (!F) return;
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
for(f=factions; f; f=f->next) {
|
|
|
|
|
attrib *a = a_find(f->attribs, &at_option_news);
|
|
|
|
|
if(!a) {
|
|
|
|
|
fprintf(F, "%s:0\n", f->email);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(F, "%s:%d\n", f->email, a->data.i);
|
|
|
|
|
}
|
2001-02-28 19:25:25 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-02-28 19:25:25 +01:00
|
|
|
|
fclose(F);
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
writeforward(void)
|
|
|
|
|
{
|
|
|
|
|
FILE *forwardFile;
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
sprintf(zText, "%s/aliases", basepath());
|
|
|
|
|
forwardFile = cfopen(zText, "w");
|
|
|
|
|
if (!forwardFile) return;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->faction->no != MONSTER_FACTION) {
|
|
|
|
|
fprintf(forwardFile,"einheit-%s: %s\n", unitid(u), u->faction->email);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(forwardFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
report_summary(summary * s, summary * o, boolean full)
|
|
|
|
|
{
|
2001-01-31 00:16:17 +01:00
|
|
|
|
FILE * F = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int i, newplayers = 0;
|
|
|
|
|
faction * f;
|
|
|
|
|
int nmrs[ORDERGAP];
|
|
|
|
|
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
|
|
|
|
char zText[MAX_PATH];
|
|
|
|
|
if (full) {
|
|
|
|
|
sprintf(zText, "%s/parteien.full", basepath());
|
|
|
|
|
} else {
|
2001-02-04 14:20:12 +01:00
|
|
|
|
sprintf(zText, "%s/parteien", basepath());
|
2001-01-28 09:50:46 +01:00
|
|
|
|
}
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (!F) return;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
printf("Schreibe Zusammenfassung (parteien)...\n");
|
|
|
|
|
fprintf(F, "%s\n%s\n\n", global.gamename, gamedate2());
|
|
|
|
|
fprintf(F, "Auswertung Nr: %d\n", turn);
|
|
|
|
|
fprintf(F, "Parteien: %s\n", pcomp(s->factions, o->factions));
|
|
|
|
|
fprintf(F, "Einheiten: %s\n\n", pcomp(s->nunits, o->nunits));
|
|
|
|
|
fprintf(F, "Spielerpopulation: %s\n",
|
|
|
|
|
pcomp(s->playerpop, o->playerpop));
|
|
|
|
|
fprintf(F, " davon bewaffnet: %s\n",
|
|
|
|
|
pcomp(s->armed_men, o->armed_men));
|
|
|
|
|
|
|
|
|
|
if (full) {
|
|
|
|
|
fprintf(F, "Regionen: %d\n", listlen(regions));
|
|
|
|
|
fprintf(F, "Bewohnte Regionen: %d\n", s->inhabitedregions);
|
|
|
|
|
fprintf(F, "Landregionen: %d\n", s->landregionen);
|
|
|
|
|
fprintf(F, "Spielerregionen: %d\n", s->regionen_mit_spielern);
|
|
|
|
|
fprintf(F, "Landspielerregionen: %d\n", s->landregionen_mit_spielern);
|
|
|
|
|
fprintf(F, "Orkifizierte Regionen: %d\n\n", s->orkifizierte_regionen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= RC_AQUARIAN ; i++) if (s->factionrace[i] && !nonplayer_race(i)) {
|
|
|
|
|
fprintf(F, "%14sv<73>lker: %s\n",
|
|
|
|
|
race[i].name[3], pcomp(s->factionrace[i], o->factionrace[i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(F, "\n");
|
|
|
|
|
|
|
|
|
|
if (full) {
|
|
|
|
|
for (i = 0; i < MAXRACES; i++) if (s->poprace[i]) {
|
|
|
|
|
fprintf(F, "%20s: %s\n",race[i].name[1],
|
|
|
|
|
rcomp(s->poprace[i],o->poprace[i]));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i <= RC_AQUARIAN; i++) if (s->poprace[i] && !nonplayer_race(i)) {
|
|
|
|
|
fprintf(F, "%20s: %s\n",race[i].name[1],
|
|
|
|
|
rcomp(s->poprace[i],o->poprace[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (full) {
|
|
|
|
|
fprintf(F, "\nWaffen: %s\n", pcomp(s->waffen,o->waffen));
|
|
|
|
|
fprintf(F, "R<EFBFBD>stungen: %s\n",
|
|
|
|
|
pcomp(s->ruestungen,o->ruestungen));
|
|
|
|
|
fprintf(F, "ungez<EFBFBD>hmte Pferde: %s\n", pcomp(s->pferde, o->pferde));
|
|
|
|
|
fprintf(F, "gez<EFBFBD>hmte Pferde: %s\n",
|
|
|
|
|
pcomp(s->spielerpferde,o->spielerpferde));
|
|
|
|
|
fprintf(F, "Artefakte: %s\n", pcomp(s->artefakte,o->artefakte));
|
|
|
|
|
fprintf(F, "Schiffe: %s\n", pcomp(s->schiffe, o->schiffe));
|
|
|
|
|
fprintf(F, "Geb<EFBFBD>ude: %s\n", pcomp(s->gebaeude, o->gebaeude));
|
|
|
|
|
|
|
|
|
|
fprintf(F, "\nBauernpopulation: %s\n", pcomp(s->peasants,o->peasants));
|
|
|
|
|
|
|
|
|
|
fprintf(F, "Population gesamt: %d\n\n", s->playerpop+s->peasants);
|
|
|
|
|
|
|
|
|
|
fprintf(F, "Reichtum Spieler: $%s\n",
|
|
|
|
|
pcomp(s->playermoney,o->playermoney));
|
|
|
|
|
fprintf(F, "Reichtum Bauern: $%s\n",
|
|
|
|
|
pcomp(s->peasantmoney, o->peasantmoney));
|
|
|
|
|
fprintf(F, "Reichtum gesamt: $%d\n\n", s->playermoney+s->peasantmoney);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(F, "\n\n");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != ORDERGAP; i++) {
|
|
|
|
|
nmrs[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
if (f->age <= 1 && turn - f->lastorders == 1) {
|
|
|
|
|
newplayers++;
|
|
|
|
|
} else if (f->no != MONSTER_FACTION) {
|
|
|
|
|
nmrs[min(ORDERGAP-1,turn-f->lastorders)]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != ORDERGAP; i++) {
|
|
|
|
|
fprintf(F, "%d %s:\t\t %d\n", i,
|
|
|
|
|
i != 1 ? "NMRs" : "NMR ", nmrs[i]);
|
|
|
|
|
}
|
|
|
|
|
if (age) {
|
|
|
|
|
if (age[2] != 0) {
|
|
|
|
|
fprintf(F, "Erstabgaben:\t %d%%\n", 100 - (dropouts[0] * 100 / age[2]));
|
|
|
|
|
}
|
|
|
|
|
if (age[3] != 0) {
|
|
|
|
|
fprintf(F, "Zweitabgaben:\t %d%%\n", 100 - (dropouts[1] * 100 / age[3]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fprintf(F, "Neue Spieler:\t %d\n", newplayers);
|
|
|
|
|
|
|
|
|
|
if (factions)
|
|
|
|
|
fprintf(F, "\nParteien:\n\n");
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next)
|
|
|
|
|
fprintf(F, "%s (%.3s/%.3s), %d Einh., %d Pers., $%d, %d %s\n",
|
|
|
|
|
factionname(f), race[f->race].name[0], neue_gebiete[f->magiegebiet],
|
|
|
|
|
f->nunits, f->number, f->money,
|
|
|
|
|
turn - f->lastorders,
|
|
|
|
|
turn - f->lastorders != 1 ? "NMRs" : "NMR ");
|
|
|
|
|
|
|
|
|
|
fclose(F);
|
|
|
|
|
|
2001-01-31 00:16:17 +01:00
|
|
|
|
if (full) {
|
|
|
|
|
FILE * F;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef PLAYER_CSV
|
|
|
|
|
region * r;
|
|
|
|
|
#endif
|
|
|
|
|
printf("Schreibe Liste der Adressen (adressen)...\n");
|
2001-01-31 00:16:17 +01:00
|
|
|
|
writeadresses();
|
2001-02-28 19:25:25 +01:00
|
|
|
|
writenewssubscriptions();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
writeforward();
|
|
|
|
|
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
2001-01-31 00:16:17 +01:00
|
|
|
|
char zText[MAX_PATH];
|
2001-01-28 09:50:46 +01:00
|
|
|
|
sprintf(zText, "%s/datum", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
2001-01-31 00:16:17 +01:00
|
|
|
|
if (!F) return;
|
2001-01-28 09:50:46 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
printf("Schreibe Datum (datum)...\n");
|
|
|
|
|
fputs(gamedate2(), F);
|
|
|
|
|
fclose(F);
|
2001-01-31 00:16:17 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef PLAYER_CSV
|
2001-01-28 09:50:46 +01:00
|
|
|
|
{
|
|
|
|
|
strcpy(zText, "%s/players", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!F) return;
|
|
|
|
|
printf("Schreibe Spielerliste (players)...\n");
|
|
|
|
|
r = findregion(0, 0);
|
|
|
|
|
if (r) for (f=factions;f;f=f->next) {
|
|
|
|
|
fputs("id;name;email;info;age;x;y;nmr;score;race;magic;units;people;money", F);
|
|
|
|
|
fprintf(F, "%s;\"%s\";\"%s\";\"%s\";\"%s\";%d;%d;%d;%d;%d;"
|
|
|
|
|
"\"%s\";\"%s\";"
|
|
|
|
|
"%d;%d;%d\n",
|
|
|
|
|
factionid(f), f->name, f->email, f->banner, f->passw, f->age, region_x(r, f), region_y(r, f), turn-f->lastorders, f->score,
|
|
|
|
|
race[f->race].name[0], neue_gebiete[f->magiegebiet],
|
|
|
|
|
f->nunits, f->number, f->money);
|
|
|
|
|
}
|
|
|
|
|
fclose(F);
|
|
|
|
|
#endif
|
|
|
|
|
writemonument();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/******* end summary ******/
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_unit(struct opstack ** stack, const void * userdata) /* unit -> string */
|
|
|
|
|
{
|
|
|
|
|
const struct unit * u = opop(stack, const struct unit *);
|
|
|
|
|
const char * c = u?unitname(u):"nobody";
|
|
|
|
|
size_t len = strlen(c);
|
|
|
|
|
opush(stack, strcpy(balloc(len+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_faction(struct opstack ** stack, const void * userdata) /* faction -> string */
|
|
|
|
|
{
|
|
|
|
|
const struct faction * f = opop(stack, const struct faction *);
|
|
|
|
|
const char * c = factionname(f);
|
|
|
|
|
size_t len = strlen(c);
|
|
|
|
|
opush(stack, strcpy(balloc(len+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_region(struct opstack ** stack, const void * userdata) /* region -> string */
|
|
|
|
|
{
|
|
|
|
|
const struct faction * f = (const struct faction *)userdata;
|
|
|
|
|
const struct region * r = opop(stack, const struct region *);
|
|
|
|
|
const char * c = regionname(r, f);
|
|
|
|
|
size_t len = strlen(c);
|
|
|
|
|
opush(stack, strcpy(balloc(len+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_ship(struct opstack ** stack, const void * userdata) /* ship -> string */
|
|
|
|
|
{
|
|
|
|
|
const struct ship * u = opop(stack, const struct ship *);
|
|
|
|
|
const char * c = u?shipname(u):"nobody";
|
|
|
|
|
size_t len = strlen(c);
|
|
|
|
|
opush(stack, strcpy(balloc(len+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_building(struct opstack ** stack, const void * userdata) /* building -> string */
|
|
|
|
|
{
|
|
|
|
|
const struct building * u = opop(stack, const struct building *);
|
|
|
|
|
const char * c = u?buildingname(u):"nobody";
|
|
|
|
|
size_t len = strlen(c);
|
|
|
|
|
opush(stack, strcpy(balloc(len+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_resource(struct opstack ** stack, const void * userdata)
|
|
|
|
|
{
|
|
|
|
|
const faction * report = (const faction*)userdata;
|
|
|
|
|
int j = opop(stack, int);
|
|
|
|
|
struct resource_type * res = opop(stack, struct resource_type *);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
const char * c = LOC(report->locale, resourcename(res, j!=1));
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
opush(stack, strcpy(balloc(strlen(c)+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
static void
|
|
|
|
|
eval_race(struct opstack ** stack, const void * userdata)
|
|
|
|
|
{
|
|
|
|
|
const faction * report = (const faction*)userdata;
|
|
|
|
|
int j = opop(stack, int);
|
|
|
|
|
int r = opop(stack, int);
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
const char * c = LOC(report->locale, race[r].name[j!=1]);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
opush(stack, strcpy(balloc(strlen(c)+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
eval_direction(struct opstack ** stack, const void * userdata)
|
|
|
|
|
{
|
|
|
|
|
const faction * report = (const faction*)userdata;
|
|
|
|
|
int i = opop(stack, int);
|
|
|
|
|
|
2001-04-22 07:36:50 +02:00
|
|
|
|
const char * c = LOC(report->locale, directions[i]);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
opush(stack, strcpy(balloc(strlen(c)+1), c));
|
|
|
|
|
}
|
|
|
|
|
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
static void
|
|
|
|
|
eval_skill(struct opstack ** stack, const void * userdata)
|
|
|
|
|
{
|
|
|
|
|
const faction * report = (const faction*)userdata;
|
|
|
|
|
int sk = opop(stack, int);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
const char * c = skillname(sk, report->locale);
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
opush(stack, strcpy(balloc(strlen(c)+1), c));
|
|
|
|
|
unused(userdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
report_init(void)
|
|
|
|
|
{
|
|
|
|
|
add_function("region", &eval_region);
|
|
|
|
|
add_function("resource", &eval_resource);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
add_function("race", &eval_race);
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
add_function("faction", &eval_faction);
|
|
|
|
|
add_function("ship", &eval_ship);
|
|
|
|
|
add_function("unit", &eval_unit);
|
|
|
|
|
add_function("building", &eval_building);
|
|
|
|
|
add_function("skill", &eval_skill);
|
2001-04-16 16:34:19 +02:00
|
|
|
|
add_function("direction", &eval_direction);
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
}
|