forked from github/server
1e51d0e9e2
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.
1001 lines
26 KiB
C
1001 lines
26 KiB
C
/* vi: set ts=2:
|
||
*
|
||
* 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.
|
||
*/
|
||
|
||
#include <config.h>
|
||
#include <eressea.h>
|
||
#include "creport.h"
|
||
|
||
/* tweakable features */
|
||
#define ENCODE_SPECIAL 1
|
||
#define RENDER_CRMESSAGES 1
|
||
|
||
/* modules include */
|
||
#include <modules/score.h>
|
||
|
||
/* attributes include */
|
||
#include <attributes/follow.h>
|
||
#include <attributes/racename.h>
|
||
|
||
/* gamecode includes */
|
||
#include "laws.h"
|
||
#include "economy.h"
|
||
|
||
/* kernel includes */
|
||
#include <alchemy.h>
|
||
#include <border.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 <plane.h>
|
||
#include <race.h>
|
||
#include <region.h>
|
||
#include <reports.h>
|
||
#include <ship.h>
|
||
#include <skill.h>
|
||
#include <teleport.h>
|
||
#include <unit.h>
|
||
#include <save.h>
|
||
|
||
/* util includes */
|
||
#include <util/message.h>
|
||
#include <goodies.h>
|
||
#include <crmessage.h>
|
||
#include <nrmessage.h>
|
||
|
||
/* libc includes */
|
||
#include <math.h>
|
||
#include <stdio.h>
|
||
#include <assert.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
/* imports */
|
||
extern const char *directions[];
|
||
extern const char *spelldata[];
|
||
extern int quiet;
|
||
|
||
/* globals */
|
||
#define C_REPORT_VERSION 57
|
||
|
||
/* implementation */
|
||
void
|
||
cr_output_str_list(FILE * F, const char *title, const strlist * S, faction * f)
|
||
{
|
||
char *s;
|
||
|
||
if (!S) return;
|
||
|
||
fprintf(F, "%s\n", title);
|
||
while (S) {
|
||
s = replace_global_coords(S->s, f);
|
||
fprintf(F, "\"%s\"\n", s);
|
||
S = S->next;
|
||
}
|
||
}
|
||
|
||
#include "objtypes.h"
|
||
|
||
static void
|
||
print_curses(FILE * F, void * obj, typ_t typ, attrib *a, int self)
|
||
{
|
||
boolean header = false;
|
||
while (a) {
|
||
int dh = 0;
|
||
curse *c;
|
||
|
||
if (fval(a->type, ATF_CURSE)) {
|
||
|
||
c = (curse *)a->data.v;
|
||
if (c->type->curseinfo)
|
||
dh = c->type->curseinfo(obj, typ, c, self);
|
||
if (dh == 1) {
|
||
if (!header) {
|
||
header = 1;
|
||
fputs("EFFECTS\n", F);
|
||
}
|
||
fprintf(F, "\"%s\"\n", buf);
|
||
}
|
||
} else if (a->type==&at_effect && self) {
|
||
effect_data * data = (effect_data *)a->data.v;
|
||
if (!header) {
|
||
header = 1;
|
||
fputs("EFFECTS\n", F);
|
||
}
|
||
fprintf(F, "\"%d %s\"\n", data->value, locale_string(NULL, resourcename(data->type->itype->rtype, 0)));
|
||
}
|
||
a = a->next;
|
||
}
|
||
}
|
||
|
||
static int
|
||
cr_unit(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
unit * u = (unit *)v;
|
||
sprintf(buffer, "%d", u?u->no:-1);
|
||
unused(report);
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
cr_ship(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
ship * u = (ship *)v;
|
||
sprintf(buffer, "%d", u?u->no:-1);
|
||
unused(report);
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
cr_building(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
building * u = (building *)v;
|
||
sprintf(buffer, "%d", u?u->no:-1);
|
||
unused(report);
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
cr_faction(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
faction * f = (faction *)v;
|
||
sprintf(buffer, "%d", f?f->no:-1);
|
||
unused(report);
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
cr_region(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
region * r = (region *)v;
|
||
if (r) {
|
||
plane * p = rplane(r);
|
||
if (!p || !(p->flags & PFL_NOCOORDS)) {
|
||
sprintf(buffer, "%d %d %d", region_x(r, report), region_y(r, report), p?p->id:0);
|
||
return 0;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
static int
|
||
cr_resource(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
const resource_type * r = (const resource_type *)v;
|
||
if (r) {
|
||
sprintf(buffer, "\"%s\"", locale_string(report->locale, resourcename(r, 0)));
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
static int
|
||
cr_skill(const void * v, char * buffer, const void * userdata)
|
||
{
|
||
const faction * report = (const faction*)userdata;
|
||
skill_t sk = (skill_t)v;
|
||
if (sk!=NOSKILL) sprintf(buffer, "\"%s\"", locale_string(report->locale, skillnames[sk]));
|
||
else strcpy(buffer, "\"\"");
|
||
return 0;
|
||
}
|
||
|
||
void
|
||
creport_init(void)
|
||
{
|
||
tsf_register("report", &cr_ignore);
|
||
tsf_register("string", &cr_string);
|
||
tsf_register("int", &cr_int);
|
||
tsf_register("unit", &cr_unit);
|
||
tsf_register("region", &cr_region);
|
||
tsf_register("faction", &cr_faction);
|
||
tsf_register("ship", &cr_ship);
|
||
tsf_register("building", &cr_building);
|
||
tsf_register("skill", &cr_skill);
|
||
tsf_register("resource", &cr_resource);
|
||
}
|
||
|
||
void
|
||
creport_cleanup(void)
|
||
{
|
||
}
|
||
|
||
static int msgno;
|
||
|
||
#define MTMAXHASH 1023
|
||
|
||
static struct known_mtype {
|
||
const struct message_type * mtype;
|
||
struct known_mtype * nexthash;
|
||
} * mtypehash[MTMAXHASH];
|
||
|
||
static void
|
||
report_crtypes(FILE * F, const struct locale* lang)
|
||
{
|
||
int i;
|
||
fputs("MESSAGETYPES\n", F);
|
||
for (i=0;i!=MTMAXHASH;++i) {
|
||
struct known_mtype * kmt;
|
||
for (kmt=mtypehash[i];kmt;kmt=kmt->nexthash) {
|
||
const struct nrmessage_type * nrt = nrt_find(lang, kmt->mtype);
|
||
if (nrt) {
|
||
unsigned int hash = hashstring(mt_name(kmt->mtype));
|
||
fputc('\"', F);
|
||
fputs(escape_string(nrt_string(nrt), NULL, 0), F);
|
||
fprintf(F, "\";%d\n", hash);
|
||
}
|
||
}
|
||
while (mtypehash[i]) {
|
||
kmt = mtypehash[i];
|
||
mtypehash[i] = mtypehash[i]->nexthash;
|
||
free(kmt);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
render_messages(FILE * F, faction * f, message_list *msgs)
|
||
{
|
||
struct mlist* m = msgs->begin;
|
||
while (m) {
|
||
char crbuffer[1024];
|
||
boolean printed = false;
|
||
const struct message_type * mtype = m->msg->type;
|
||
unsigned int hash = hashstring(mtype->name);
|
||
#if RENDER_CRMESSAGES
|
||
char nrbuffer[4096];
|
||
nrbuffer[0] = '\0';
|
||
if (nr_render(m->msg, f->locale, nrbuffer, f)==0 && nrbuffer[0]) {
|
||
fprintf(F, "MESSAGE %d\n", ++msgno);
|
||
fprintf(F, "%d;type\n", hash);
|
||
fputs("\"", F);
|
||
fputs(nrbuffer, F);
|
||
fputs("\";rendered\n", F);
|
||
printed = true;
|
||
}
|
||
#endif
|
||
crbuffer[0] = '\0';
|
||
if (cr_render(m->msg, crbuffer, (const void*)f)==0 && crbuffer[0]) {
|
||
if (!printed) fprintf(F, "MESSAGE %d\n", ++msgno);
|
||
fputs(crbuffer, F);
|
||
}
|
||
else log_error(("could not render cr-message %p\n", m->msg));
|
||
if (printed) {
|
||
unsigned int ihash = hash % MTMAXHASH;
|
||
struct known_mtype * kmt = mtypehash[ihash];
|
||
while (kmt && kmt->mtype != mtype) kmt = kmt->nexthash;
|
||
if (kmt==NULL) {
|
||
kmt = (struct known_mtype*)malloc(sizeof(struct known_mtype));
|
||
kmt->nexthash = mtypehash[ihash];
|
||
kmt->mtype = mtype;
|
||
mtypehash[ihash] = kmt;
|
||
}
|
||
}
|
||
m = m->next;
|
||
}
|
||
}
|
||
|
||
static void
|
||
cr_output_messages(FILE * F, message_list *msgs, faction * f)
|
||
{
|
||
if (msgs) render_messages(F, f, msgs);
|
||
}
|
||
|
||
/* prints a building */
|
||
static void
|
||
cr_output_buildings(FILE * F, building * b, unit * u, int fno, faction *f)
|
||
{
|
||
const building_type * type = b->type;
|
||
unit * bo = buildingowner(b->region, b);
|
||
|
||
assert(b);
|
||
fprintf(F, "BURG %d\n", b->no);
|
||
if (!u || u->faction != f) {
|
||
const attrib * a = a_find(b->attribs, &at_icastle);
|
||
if (a) type = ((icastle_data*)a->data.v)->type;
|
||
}
|
||
fprintf(F, "\"%s\";Typ\n", buildingtype(b, b->size, f->locale));
|
||
fprintf(F, "\"%s\";Name\n", b->name);
|
||
if (strlen(b->display))
|
||
fprintf(F, "\"%s\";Beschr\n", b->display);
|
||
if (b->size)
|
||
fprintf(F, "%d;Groesse\n", b->size);
|
||
if (u)
|
||
fprintf(F, "%d;Besitzer\n", u ? u->no : -1);
|
||
if (fno >= 0)
|
||
fprintf(F, "%d;Partei\n", fno);
|
||
#ifdef TODO
|
||
int cost = buildingdaten[b->type].per_size * b->size + buildingdaten[b->type].unterhalt;
|
||
if (u && u->faction == f && cost)
|
||
fprintf(F, "%d;Unterhalt\n", cost);
|
||
#endif
|
||
if (b->besieged)
|
||
fprintf(F, "%d;Belagerer\n", b->besieged);
|
||
if(bo != NULL){
|
||
print_curses(F, b, TYP_BUILDING, b->attribs,
|
||
(bo->faction == f)? 1 : 0);
|
||
} else {
|
||
print_curses(F, b, TYP_BUILDING, b->attribs, 0);
|
||
}
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
/* prints a ship */
|
||
static void
|
||
cr_output_ship(FILE * F, ship * s, unit * u, int fcaptain, faction * f, region * r)
|
||
{
|
||
unit *u2;
|
||
int w = 0;
|
||
assert(s);
|
||
fprintf(F, "SCHIFF %d\n", s->no);
|
||
fprintf(F, "\"%s\";Name\n", s->name);
|
||
if (strlen(s->display))
|
||
fprintf(F, "\"%s\";Beschr\n", s->display);
|
||
fprintf(F, "\"%s\";Typ\n", s->type->name[0]);
|
||
fprintf(F, "%d;Groesse\n", s->size);
|
||
if (s->damage) {
|
||
int percent = s->damage*100/(s->size*DAMAGE_SCALE);
|
||
fprintf(F, "%d;Schaden\n", percent);
|
||
}
|
||
if (u)
|
||
fprintf(F, "%d;Kapitaen\n", u ? u->no : -1);
|
||
if (fcaptain >= 0)
|
||
fprintf(F, "%d;Partei\n", fcaptain);
|
||
|
||
/* calculate cargo */
|
||
if (u && (u->faction == f || omniscient(f))) {
|
||
for (u2 = r->units; u2; u2 = u2->next)
|
||
if (u2->ship == s)
|
||
w += weight(u2);
|
||
|
||
fprintf(F, "%d;Ladung\n", (w + 99) / 100);
|
||
fprintf(F, "%d;MaxLadung\n", shipcapacity(s) / 100);
|
||
}
|
||
/* shore */
|
||
w = NODIRECTION;
|
||
if (rterrain(r) != T_OCEAN) w = s->coast;
|
||
if (w != NODIRECTION)
|
||
fprintf(F, "%d;Kueste\n", w);
|
||
|
||
if(shipowner(r, s) != NULL){
|
||
print_curses(F, s, TYP_SHIP, s->attribs,
|
||
(shipowner(r, s)->faction == f)? 1 : 0);
|
||
} else {
|
||
print_curses(F, s, TYP_SHIP, s->attribs, 0);
|
||
}
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
/* prints all that belongs to a unit */
|
||
static void
|
||
cr_output_unit(FILE * F, region * r,
|
||
faction * f, /* observers faction */
|
||
unit * u, int mode)
|
||
{
|
||
/* Race attributes are always plural and item attributes always
|
||
* singular */
|
||
const item_type * lasttype;
|
||
int pr;
|
||
item *itm, *show;
|
||
boolean itemcloak = is_cursed(u->attribs, C_ITEMCLOAK, 0);
|
||
building * b;
|
||
const char * pzTmp;
|
||
skill_t sk;
|
||
strlist *S;
|
||
const attrib *a_fshidden = NULL;
|
||
|
||
assert(u);
|
||
|
||
if(fspecial(u->faction, FS_HIDDEN))
|
||
a_fshidden = a_find(u->attribs, &at_fshidden);
|
||
|
||
fprintf(F, "EINHEIT %d\n", u->no);
|
||
fprintf(F, "\"%s\";Name\n", u->name);
|
||
if (strlen(u->display))
|
||
fprintf(F, "\"%s\";Beschr\n", u->display);
|
||
|
||
if ((u->faction == f || omniscient(f)) || !fval(u, FL_PARTEITARNUNG)) {
|
||
#ifdef GROUPS
|
||
if (u->faction == f) {
|
||
const attrib * a = a_find(u->attribs, &at_group);
|
||
if (a) {
|
||
const group * g = (const group*)a->data.v;
|
||
fprintf(F, "%d;gruppe\n", g->gid);
|
||
}
|
||
}
|
||
#endif
|
||
fprintf(F, "%d;Partei\n", u->faction->no);
|
||
}
|
||
|
||
if(u->faction != f && a_fshidden
|
||
&& a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) {
|
||
fprintf(F, "-1;Anzahl\n");
|
||
} else {
|
||
fprintf(F, "%d;Anzahl\n", u->number);
|
||
}
|
||
|
||
|
||
pzTmp = get_racename(u->attribs);
|
||
if (pzTmp==NULL) fprintf(F, "\"%s\";Typ\n", race[u->irace].name[1]);
|
||
else fprintf(F, "\"%s\";Typ\n", pzTmp);
|
||
if ((pzTmp || u->irace != u->race) && u->faction==f) {
|
||
fprintf(F, "\"%s\";wahrerTyp\n", race[u->race].name[1]);
|
||
}
|
||
|
||
if (u->building)
|
||
fprintf(F, "%d;Burg\n", u->building->no);
|
||
if (u->ship)
|
||
fprintf(F, "%d;Schiff\n", u->ship->no);
|
||
if (getguard(u))
|
||
fprintf(F, "%d;bewacht\n", getguard(u)?1:0);
|
||
if ((b=usiege(u))!=NULL)
|
||
fprintf(F, "%d;belagert\n", b->no);
|
||
if (fval(u, FL_PARTEITARNUNG))
|
||
fprintf(F, "%d;Parteitarnung\n", fval(u, FL_PARTEITARNUNG));
|
||
|
||
/* additional information for own units */
|
||
if (u->faction == f || omniscient(f)) {
|
||
const char *c;
|
||
int i;
|
||
const attrib * a;
|
||
|
||
a = a_find(u->attribs, &at_follow);
|
||
if (a) {
|
||
unit * u = (unit*)a->data.v;
|
||
if (u) fprintf(F, "%d;folgt\n", u->no);
|
||
}
|
||
i = ualias(u);
|
||
if (i>0)
|
||
fprintf(F, "%d;temp\n", i);
|
||
else if (i<0)
|
||
fprintf(F, "%d;alias\n", -i);
|
||
i = get_money(u);
|
||
if (u->status)
|
||
fprintf(F, "%d;Kampfstatus\n", u->status);
|
||
i = u_geteffstealth(u);
|
||
if (i >= 0)
|
||
fprintf(F, "%d;Tarnung\n", i);
|
||
c = uprivate(u);
|
||
if (c)
|
||
fprintf(F, "\"%s\";privat\n", c);
|
||
c = hp_status(u);
|
||
if (c && *c && (u->faction == f || omniscient(f)))
|
||
fprintf(F, "\"%s\";hp\n", c);
|
||
if (fval(u, FL_HUNGER) && (u->faction == f))
|
||
fputs("1;hunger\n", F);
|
||
if (is_mage(u)) {
|
||
fprintf(F, "%d;Aura\n", get_spellpoints(u));
|
||
fprintf(F, "%d;Auramax\n", max_spellpoints(u->region,u));
|
||
}
|
||
|
||
/* default commands */
|
||
fprintf(F, "COMMANDS\n");
|
||
if(u->lastorder[0]) fprintf(F, "\"%s\"\n", u->lastorder);
|
||
for (S = u->orders; S; S = S->next) {
|
||
if(is_persistent(S->s)) {
|
||
fprintf(F, "\"%s\"\n", S->s);
|
||
}
|
||
}
|
||
|
||
/* talents */
|
||
pr = 0;
|
||
for (sk = 0; sk != MAXSKILLS; ++sk)
|
||
if (get_skill(u, sk)) {
|
||
if (!pr) {
|
||
pr = 1;
|
||
fprintf(F, "TALENTE\n");
|
||
}
|
||
#ifdef NOVISIBLESKILLPOINTS
|
||
/* 0 ist nur der Kompatibilit<69>t wegen drin, rausnehmen */
|
||
fprintf(F, "0 %d;%s\n", eff_skill(u, sk, r), skillnames[sk]);
|
||
#else
|
||
fprintf(F, "%d %d;%s\n", get_skill(u, sk), eff_skill(u, sk, r), skillnames[sk]);
|
||
#endif
|
||
}
|
||
/* spells */
|
||
if (is_mage(u)) {
|
||
sc_mage * mage = get_mage(u);
|
||
spell_ptr *spt = mage->spellptr;
|
||
if (spt) {
|
||
spell *sp;
|
||
int i;
|
||
fprintf(F, "SPRUECHE\n");
|
||
for (;spt; spt = spt->next) {
|
||
sp = find_spellbyid(spt->spellid);
|
||
fprintf(F, "\"%s\"\n", sp->name);
|
||
}
|
||
for (i=0;i!=MAXCOMBATSPELLS;++i) {
|
||
sp = find_spellbyid(mage->combatspell[i]);
|
||
if (sp) {
|
||
fprintf(F, "KAMPFZAUBER %d\n", i);
|
||
fprintf(F, "\"%s\";name\n", sp->name);
|
||
fprintf(F, "%d;level\n", mage->combatspelllevel[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/* items */
|
||
pr = 0;
|
||
if (f == u->faction || omniscient(u->faction)) {
|
||
show = u->items;
|
||
} else if (itemcloak==false && mode>=see_unit && !(a_fshidden
|
||
&& a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) {
|
||
show = NULL;
|
||
for (itm=u->items;itm;itm=itm->next) {
|
||
item * ishow;
|
||
const char * ic;
|
||
int in;
|
||
report_item(u, itm, f, NULL, &ic, &in, true);
|
||
if (in>0 && ic && *ic) {
|
||
for (ishow = show; ishow; ishow=ishow->next) {
|
||
const char * sc;
|
||
int sn;
|
||
if (ishow->type==itm->type) sc=ic;
|
||
else report_item(u, ishow, f, NULL, &sc, &sn, true);
|
||
if (sc==ic || strcmp(sc, ic)==0) {
|
||
ishow->number+=itm->number;
|
||
break;
|
||
}
|
||
}
|
||
if (ishow==NULL) {
|
||
ishow = i_add(&show, i_new(itm->type));
|
||
ishow->number = itm->number;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
show = NULL;
|
||
}
|
||
lasttype = NULL;
|
||
for (itm=show; itm; itm=itm->next) {
|
||
const char * ic;
|
||
int in;
|
||
assert(itm->type!=lasttype || !"error: list contains two objects of the same item");
|
||
report_item(u, itm, f, NULL, &ic, &in, true);
|
||
if (in==0) continue;
|
||
if (!pr) {
|
||
pr = 1;
|
||
fputs("GEGENSTAENDE\n", F);
|
||
}
|
||
fprintf(F, "%d;%s\n", in, locale_string(NULL, ic));
|
||
}
|
||
|
||
if ((u->faction == f || omniscient(f)) && u->botschaften)
|
||
cr_output_str_list(F, "EINHEITSBOTSCHAFTEN", u->botschaften, f);
|
||
|
||
print_curses(F, u, TYP_UNIT, u->attribs, (u->faction == f)? 1 : 0);
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
/* prints allies */
|
||
static void
|
||
show_allies(FILE * F, ally * sf)
|
||
{
|
||
for (; sf; sf = sf->next) if(sf->faction) {
|
||
fprintf(F, "ALLIANZ %d\n", sf->faction->no);
|
||
fprintf(F, "\"%s\";Parteiname\n", sf->faction->name);
|
||
fprintf(F, "%d;Status\n", sf->status);
|
||
}
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
/* prints all visible spells in a region */
|
||
static void
|
||
show_active_spells(region * r)
|
||
{
|
||
char fogwall[MAXDIRECTIONS];
|
||
#ifdef TODO /* alte Regionszauberanzeigen umstellen */
|
||
unit *u;
|
||
int env = 0;
|
||
#endif
|
||
memset(fogwall, 0, sizeof(char) * MAXDIRECTIONS);
|
||
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
extern int fcompare(const void *a, const void *b);
|
||
|
||
|
||
/* this is a copy of laws.c->find_address output changed. */
|
||
static void
|
||
cr_find_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 != 0 && kann_finden(uf, f) != 0) {
|
||
cv_pushback(fcts, f);
|
||
}
|
||
}
|
||
v_sort(fcts->begin, fcts->end, fcompare);
|
||
|
||
/* FIND orders - diese duerfen erst ablaufen, nachdem alle ihre Adresse
|
||
* gesetzt haben! */
|
||
|
||
if (!quiet)
|
||
puts(" - gebe Adressen heraus (CR)");
|
||
for (fp = fcts->begin; fp != fcts->end; ++fp) {
|
||
f = *fp;
|
||
if (uf!=f && f->no != 0 && kann_finden(uf, f) != 0) {
|
||
fprintf(F, "PARTEI %d\n", f->no);
|
||
fprintf(F, "\"%s\";Parteiname\n", f->name);
|
||
fprintf(F, "\"%s\";email\n", f->email);
|
||
fprintf(F, "\"%s\";banner\n", f->banner);
|
||
}
|
||
}
|
||
free(cv_kill(fcts));
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
|
||
static void
|
||
cr_reportspell(FILE * F, spellid_t id)
|
||
{
|
||
int k, itemanz, res, costtyp;
|
||
spell *sp = find_spellbyid(id);
|
||
|
||
fprintf(F, "ZAUBER %d\n", hashstring(sp->name));
|
||
fprintf(F, "\"%s\";name\n", sp->name);
|
||
fprintf(F, "%d;level\n", sp->level);
|
||
fprintf(F, "%d;rank\n", sp->rank);
|
||
fprintf(F, "\"%s\";info\n", sp->beschreibung);
|
||
|
||
if (sp->sptyp & PRECOMBATSPELL) fputs("\"precombat\";class\n", F);
|
||
else if (sp->sptyp & COMBATSPELL) fputs("\"combat\";class\n", F);
|
||
else if (sp->sptyp & POSTCOMBATSPELL) fputs("\"postcombat\";class\n", F);
|
||
else fputs("\"normal\";class\n", F);
|
||
|
||
if (sp->sptyp & FARCASTING) fputs("1;far\n", F);
|
||
if (sp->sptyp & OCEANCASTABLE) fputs("1;ocean\n", F);
|
||
if (sp->sptyp & ONSHIPCAST) fputs("1;ship\n", F);
|
||
if (!(sp->sptyp & NOTFAMILIARCAST)) fputs("1;familiar\n", F);
|
||
fputs("KOMPONENTEN\n", F);
|
||
|
||
for (k = 0; k < MAXINGREDIENT; k++) {
|
||
res = sp->komponenten[k][0];
|
||
itemanz = sp->komponenten[k][1];
|
||
costtyp = sp->komponenten[k][2];
|
||
if(itemanz > 0) {
|
||
fprintf(F, "%d %d;%s\n", itemanz, costtyp == SPC_LEVEL || costtyp == SPC_LINEAR, resname(res, 0));
|
||
}
|
||
}
|
||
}
|
||
|
||
static unsigned int
|
||
encode_region(faction * f, region * r) {
|
||
unsigned int id;
|
||
char *cp, c;
|
||
/* obfuscation */
|
||
assert(sizeof(int)==sizeof(char)*4);
|
||
id = (((((r->x ^ f->no) % 1024) << 20) | ((r->y ^ f->no) % 1024)));
|
||
cp = (char*)&id;
|
||
c = cp[0];
|
||
cp[0] = cp[2];
|
||
cp[2] = cp[1];
|
||
cp[1] = cp[3];
|
||
cp[3] = c;
|
||
return id;
|
||
}
|
||
|
||
/* main function of the creport. creates the header and traverses all regions */
|
||
void
|
||
report_computer(FILE * F, faction * f)
|
||
{
|
||
int i;
|
||
region *r;
|
||
building *b;
|
||
ship *sh;
|
||
unit *u;
|
||
seen_region * sd;
|
||
const attrib * a;
|
||
|
||
int maxmining;
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||
/* initialisations, header and lists */
|
||
|
||
if (quiet) {
|
||
printf(" CR");
|
||
fflush(stdout);
|
||
}
|
||
else printf(" - schreibe Computerreport\n");
|
||
|
||
fprintf(F, "VERSION %d\n", C_REPORT_VERSION);
|
||
fprintf(F, "\"%s\";Spiel\n", global.gamename);
|
||
fprintf(F, "\"%s\";Konfiguration\n", "Standard");
|
||
fprintf(F, "\"%s\";Koordinaten\n", "Hex");
|
||
fprintf(F, "%d;Basis\n", 36);
|
||
fprintf(F, "%d;Umlaute\n", 1);
|
||
fprintf(F, "%d;Runde\n", turn);
|
||
fputs("2;Zeitalter\n", F);
|
||
fprintf(F, "PARTEI %d\n", f->no);
|
||
/* fprintf(F, "\"%s\";Passwort\n", f->passw); */
|
||
fprintf(F, "\"%s\";locale\n", locale_name(f->locale));
|
||
fprintf(F, "%d;Optionen\n", f->options);
|
||
if (f->options & want(O_SCORE) && f->age>DISPLAYSCORE) {
|
||
fprintf(F, "%d;Punkte\n", f->score);
|
||
fprintf(F, "%d;Punktedurchschnitt\n", average_score_of_age(f->age, f->age / 24 + 1));
|
||
}
|
||
fprintf(F, "\"%s\";Typ\n", race[f->race].name[1]);
|
||
fprintf(F, "%d;Rekrutierungskosten\n", race[f->race].rekrutieren);
|
||
fprintf(F, "%d;Anzahl Personen\n", count_all(f));
|
||
fprintf(F, "\"%s\";Magiegebiet\n", neue_gebiete[f->magiegebiet]);
|
||
|
||
if (f->race == RC_HUMAN) {
|
||
fprintf(F, "%d;Anzahl Immigranten\n", count_migrants(f));
|
||
fprintf(F, "%d;Max. Immigranten\n", count_maxmigrants(f));
|
||
}
|
||
fprintf(F, "\"%s\";Parteiname\n", f->name);
|
||
fprintf(F, "\"%s\";email\n", f->email);
|
||
fprintf(F, "\"%s\";banner\n", f->banner);
|
||
fputs("OPTIONEN\n", F);
|
||
for (i=0;i!=MAXOPTIONS;++i) {
|
||
fprintf(F, "%d;%s\n", (f->options&want(i))?1:0, options[i]);
|
||
}
|
||
show_allies(F, f->allies);
|
||
#ifdef GROUPS
|
||
{
|
||
group * g;
|
||
for (g=f->groups;g;g=g->next) {
|
||
fprintf(F, "GRUPPE %d\n", g->gid);
|
||
fprintf(F, "\"%s\";name\n", g->name);
|
||
show_allies(F, g->allies);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
cr_output_str_list(F, "FEHLER", f->mistakes, f);
|
||
cr_output_messages(F, f->msgs, f);
|
||
{
|
||
struct bmsg * bm;
|
||
for (bm=f->battles;bm;bm=bm->next) {
|
||
fprintf(F, "BATTLE %d %d\n", region_x(bm->r, f), region_y(bm->r, f));
|
||
cr_output_messages(F, bm->msgs, f);
|
||
}
|
||
}
|
||
|
||
cr_find_address(F, f);
|
||
a = a_find(f->attribs, &at_reportspell);
|
||
while (a) {
|
||
cr_reportspell(F, (spellid_t)a->data.i);
|
||
a = a->nexttype;
|
||
}
|
||
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;
|
||
const char * ch;
|
||
if (ptype==NULL) continue;
|
||
m = ptype->itype->construction->materials;
|
||
ch = resourcename(ptype->itype->rtype, 0);
|
||
fprintf(F, "TRANK %d\n", hashstring(ch));
|
||
fprintf(F, "\"%s\";Name\n", locale_string(f->locale, ch));
|
||
fprintf(F, "%d;Stufe\n", ptype->level);
|
||
fprintf(F, "\"%s\";Beschr\n", ptype->text);
|
||
fprintf(F, "ZUTATEN\n");
|
||
|
||
while (m->number) {
|
||
fprintf(F, "\"%s\"\n", locale_string(f->locale, resourcename(oldresourcetype[m->type], 0)));
|
||
m++;
|
||
}
|
||
}
|
||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||
* = = = */
|
||
/* traverse all regions */
|
||
for (sd = seen; sd!=NULL; sd = sd->next) {
|
||
int modifier = 0;
|
||
const char * tname;
|
||
|
||
r = sd->r;
|
||
|
||
if (!rplane(r)) fprintf(F, "REGION %d %d\n", region_x(r, f), region_y(r, f));
|
||
else {
|
||
#if ENCODE_SPECIAL
|
||
if (rplane(r)->flags & PFL_NOCOORDS) fprintf(F, "SPEZIALREGION %d %d\n", encode_region(f, r), rplane(r)->id);
|
||
#else
|
||
if (rplane(r)->flags & PFL_NOCOORDS) continue;
|
||
#endif
|
||
else fprintf(F, "REGION %d %d %d\n", region_x(r, f), region_y(r, f), rplane(r)->id);
|
||
}
|
||
if (r->land && strlen(rname(r, f->locale))) fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
|
||
if (is_cursed(r->attribs,C_MAELSTROM, 0))
|
||
tname = "maelstrom";
|
||
else {
|
||
if (r_isforest(r)) tname = "forest";
|
||
else tname = terrain[rterrain(r)].name;
|
||
}
|
||
|
||
fprintf(F, "\"%s\";Terrain\n", locale_string(f->locale, tname));
|
||
if (sd->mode != see_neighbour)
|
||
{
|
||
int g = 0;
|
||
direction_t d;
|
||
if (r->display && strlen(r->display))
|
||
fprintf(F, "\"%s\";Beschr\n", r->display);
|
||
if (landregion(rterrain(r))) {
|
||
fprintf(F, "%d;Bauern\n", rpeasants(r));
|
||
fprintf(F, "%d;Pferde\n", rhorses(r));
|
||
fprintf(F, "%d;Baeume\n", rtrees(r));
|
||
if (fval(r, RF_MALLORN) && rtrees(r))
|
||
fprintf(F, "1;Mallorn\n");
|
||
|
||
if (sd->mode>=see_unit) {
|
||
struct demand * dmd = r->land->demands;
|
||
if (rterrain(r) == T_MOUNTAIN || rterrain(r) == T_GLACIER) {
|
||
maxmining = 0;
|
||
for (u = r->units; u; u = u->next) {
|
||
int s = eff_skill(u, SK_MINING, r);
|
||
if (u->faction == f || omniscient(f))
|
||
maxmining = max(maxmining, s);
|
||
}
|
||
if (maxmining >= 4)
|
||
fprintf(F, "%d;Eisen\n", riron(r));
|
||
if (maxmining >= 7)
|
||
fprintf(F, "%d;Laen\n", rlaen(r));
|
||
}
|
||
fprintf(F, "%d;Silber\n", rmoney(r));
|
||
fprintf(F, "%d;Unterh\n", entertainmoney(r));
|
||
|
||
if (is_cursed(r->attribs, C_RIOT, 0)){
|
||
fprintf(F, "0;Rekruten\n");
|
||
} else {
|
||
fprintf(F, "%d;Rekruten\n", rpeasants(r) / RECRUITFRACTION);
|
||
}
|
||
if (production(r)) {
|
||
fprintf(F, "%d;Lohn\n", fwage(r, f, true));
|
||
}
|
||
/* trade */
|
||
if(rpeasants(r)/TRADE_FRACTION > 0) {
|
||
fputs("PREISE\n", F);
|
||
while (dmd) {
|
||
fprintf(F, "%d;%s\n", (dmd->value
|
||
? dmd->value*dmd->type->price
|
||
: -dmd->type->price),
|
||
locale_string(f->locale, resourcename(dmd->type->itype->rtype, 0)));
|
||
dmd=dmd->next;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
for (d = 0; d != MAXDIRECTIONS; d++)
|
||
{ /* Nachbarregionen, die gesehen werden, ermitteln */
|
||
region * r2 = rconnect(r, d);
|
||
border * b;
|
||
if (!r2) continue;
|
||
b = get_borders(r, r2);
|
||
while (b) {
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
if (cs) {
|
||
fprintf(F, "GRENZE %d\n", ++g);
|
||
fprintf(F, "\"%s\";typ\n", b->type->name(b, r, f, GF_NONE));
|
||
fprintf(F, "%d;richtung\n", d);
|
||
if (!b->type->transparent(b, f)) fputs("1;opaque\n", F);
|
||
/* pfusch: */
|
||
if (b->type==&bt_road) {
|
||
int p = rroad(r, d)*100/terrain[rterrain(r)].roadreq;
|
||
fprintf(F, "%d;prozent\n", p);
|
||
}
|
||
}
|
||
b = b->next;
|
||
}
|
||
}
|
||
if (sd->mode==see_unit && 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);
|
||
|
||
if (rl) {
|
||
regionlist *rl2 = rl;
|
||
while(rl2) {
|
||
region * r = rl2->region;
|
||
fprintf(F, "SCHEMEN %d %d\n", region_x(r, f), region_y(r, f));
|
||
fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
|
||
rl2 = rl2->next;
|
||
if(rl2) scat(", ");
|
||
}
|
||
free_regionlist(rl);
|
||
}
|
||
}
|
||
|
||
print_curses(F, r, TYP_REGION, r->attribs, 0);
|
||
/* describe both passed and inhabited regions */
|
||
show_active_spells(r);
|
||
{
|
||
boolean see = false;
|
||
const attrib * ru;
|
||
/* show units pulled throuth region */
|
||
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) && in_region(r, u) == 0) {
|
||
if (u->ship && !fval(u, FL_OWNER))
|
||
continue;
|
||
if (!see) fprintf(F, "DURCHREISE\n");
|
||
see = true;
|
||
if (u->ship)
|
||
fprintf(F, "\"%s\"\n", shipname(u->ship));
|
||
else
|
||
fprintf(F, "\"%s\"\n", unitname(u));
|
||
}
|
||
}
|
||
}
|
||
cr_output_messages(F, r->msgs, f);
|
||
/* buildings */
|
||
for (b = rbuildings(r); b; b = b->next) {
|
||
int fno = -1;
|
||
u = buildingowner(r, b);
|
||
if (u && !fval(u, FL_PARTEITARNUNG))
|
||
fno = u->faction->no;
|
||
|
||
cr_output_buildings(F, b, u, fno, f);
|
||
}
|
||
|
||
/* ships */
|
||
for (sh = r->ships; sh; sh = sh->next) {
|
||
int fno = -1;
|
||
u = shipowner(r, sh);
|
||
if (u && !fval(u, FL_PARTEITARNUNG))
|
||
fno = u->faction->no;
|
||
|
||
cr_output_ship(F, sh, u, fno, f, r);
|
||
}
|
||
|
||
/* visible units */
|
||
for (u = r->units; u; u = u->next) {
|
||
boolean visible = true;
|
||
switch (sd->mode) {
|
||
case see_unit:
|
||
modifier=0;
|
||
break;
|
||
#ifdef SEE_FAR
|
||
case see_far:
|
||
#endif
|
||
case see_lighthouse:
|
||
modifier = -2;
|
||
break;
|
||
case see_travel:
|
||
modifier = -1;
|
||
break;
|
||
default:
|
||
visible=false;
|
||
}
|
||
if (u->building || u->ship || (visible && cansee(f, r, u, modifier)))
|
||
cr_output_unit(F, r, f, u, sd->mode);
|
||
}
|
||
} /* region traversal */
|
||
}
|
||
report_crtypes(F, f->locale);
|
||
}
|