/* vi: set ts=2: * * Eressea PB(E)M host Copyright (C) 1998-2003 * 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) * * based on: * * Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace * Atlantis v1.7 Copyright 1996 by Alex Schröder * * This program may not be used, modified or distributed without * prior permission by the authors of Eressea. * This program may not be sold or used commercially without prior written * permission from the authors. */ #include #include "eressea.h" #include "reports.h" /* kernel includes */ #include "building.h" #include "faction.h" #include "group.h" #include "item.h" #include "karma.h" #include "magic.h" #include "message.h" #include "order.h" #include "plane.h" #include "race.h" #include "region.h" #include "ship.h" #include "skill.h" #include "unit.h" #ifdef USE_UGROUPS # include "ugroup.h" # include #endif /* util includes */ #include #include #include /* libc includes */ #include #include #include /* attributes includes */ #include #include #include const char * g_reportdir; const char *coasts[MAXDIRECTIONS] = { "coast::nw", "coast::ne", "coast::e", "coast::se", "coast::sw", "coast::w" }; const char * reportpath(void) { static char zText[MAX_PATH]; if (g_reportdir) return g_reportdir; return strcat(strcpy(zText, basepath()), "/reports"); } static char * groupid(const struct group * g, const struct faction * f) { typedef char name[OBJECTIDSIZE + 1]; static name idbuf[8]; static int nextbuf = 0; char *buf = idbuf[(++nextbuf) % 8]; sprintf(buf, "%s (%s)", g->name, factionid(f)); return buf; } static const char * report_kampfstatus(const unit * u, const struct locale * lang) { static char fsbuf[64]; static const char * azstatus[] = { "status_aggressive", "status_front", "status_rear", "status_defensive", "status_avoid", "status_flee" }; strcpy(fsbuf, LOC(lang, azstatus[u->status])); if (fval(u, UFL_NOAID)) { strcat(fsbuf, ", "); strcat(fsbuf, LOC(lang, "status_noaid")); } return fsbuf; } const char * hp_status(const unit * u) { double p = (double) ((double) u->hp / (double) (u->number * unit_max_hp(u))); if (p > 2.00) return mkname("damage", "critical"); if (p > 1.50) return mkname("damage", "heavily"); if (p < 0.50) return mkname("damage", "badly"); if (p < 0.75) return mkname("damage", "wounded"); if (p < 0.99) return mkname("damage", "exhausted"); return NULL; } void report_item(const unit * owner, const item * i, const faction * viewer, const char ** name, const char ** basename, int * number, boolean singular) { if (owner->faction == viewer) { if (name) *name = locale_string(viewer->locale, resourcename(i->type->rtype, ((i->number!=1 && !singular)?GR_PLURAL:0))); if (basename) *basename = resourcename(i->type->rtype, 0); if (number) *number = i->number; } else if (i->type->rtype==r_silver) { int pp = i->number/owner->number; if (number) *number = 1; if (pp > 50000 && dragonrace(owner->race)) { if (name) *name = locale_string(viewer->locale, "dragonhoard"); if (basename) *basename = "dragonhoard"; } else if (pp > 5000) { if (name) *name = locale_string(viewer->locale, "moneychest"); if (basename) *basename = "moneychest"; } else if (pp > 500) { if (name) *name = locale_string(viewer->locale, "moneybag"); if (basename) *basename = "moneybag"; } else { if (number) *number = 0; if (name) *name = NULL; if (basename) *basename = NULL; } } else { if (name) *name = locale_string(viewer->locale, resourcename(i->type->rtype, NMF_APPEARANCE|((i->number!=1 && !singular)?GR_PLURAL:0))); if (basename) *basename = resourcename(i->type->rtype, NMF_APPEARANCE); if (number) { if (fval(i->type, ITF_HERB)) *number = 1; else *number = i->number; } } } #define ORDERS_IN_NR 1 static size_t buforder(char * bufp, size_t size, const order * ord, int mode) { size_t tsize = 0, rsize; rsize = strlcpy(bufp, ", \"", size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (modesize) rsize = size-1; size -= rsize; bufp += rsize; if (size>1) { strcpy(bufp, "\""); ++tsize; } return tsize; } int bufunit(const faction * f, const unit * u, int indent, int mode) { int i, dh; skill_t sk; int getarnt = fval(u, UFL_PARTEITARNUNG); const char *pzTmp; building * b; boolean isbattle = (boolean)(mode == see_battle); int telepath_see = fspecial(f, FS_TELEPATHY); attrib *a_fshidden = NULL; item * itm; item * show; faction *fv = visible_faction(f, u); char * bufp = buf; boolean itemcloak = false; static const curse_type * itemcloak_ct = 0; static boolean init = false; size_t size = sizeof(buf), rsize; if (!init) { init = true; itemcloak_ct = ct_find("itemcloak"); } if (itemcloak_ct!=NULL) { itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); } if (fspecial(u->faction, FS_HIDDEN)) a_fshidden = a_find(u->attribs, &at_fshidden); rsize = strlcpy(bufp, unitname(u), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (!isbattle) { attrib *a_otherfaction = a_find(u->attribs, &at_otherfaction); if (u->faction == f) { if (fval(u, UFL_GROUP)) { attrib *a = a_find(u->attribs, &at_group); if (a) { group * g = (group*)a->data.v; rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, groupid(g, f), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } if (getarnt) { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, LOC(f->locale, "anonymous"), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } else if (a_otherfaction) { faction * otherfaction = get_otherfaction(a_otherfaction); if (otherfaction) { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, factionname(otherfaction), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } } else { if (getarnt) { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, LOC(f->locale, "anonymous"), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } else { if (a_otherfaction && alliedunit(u, f, HELP_FSTEALTH)) { faction * f = get_otherfaction(a_otherfaction); bufp += snprintf(bufp, size, ", %s (%s)", factionname(f), factionname(u->faction)); size = sizeof(buf)-(bufp-buf); } else { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, factionname(fv), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } } } #ifdef USE_UGROUPS if (u->faction == f) { attrib *a = a_find(u->attribs, &at_ugroup); if (a) { ugroup *ug = findugroupid(u->faction, a->data.i); if (is_ugroupleader(u, ug)) { if (size>1) { strcpy(bufp++, "*"); --size; } } rsize = strlcpy(bufp, itoa36(ug->id), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } #endif rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (u->faction != f && a_fshidden && a_fshidden->data.ca[0] == 1 && effskill(u, SK_STEALTH) >= 6) { rsize = strlcpy(bufp, "? ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } else { bufp += snprintf(bufp, size, "%d ", u->number); size = sizeof(buf)-(bufp-buf); } pzTmp = get_racename(u->attribs); if (pzTmp) { rsize = strlcpy(bufp, pzTmp, size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (u->faction==f && fval(u->race, RCF_SHAPESHIFTANY)) { rsize = strlcpy(bufp, " (", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, racename(f->locale, u, u->race), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (size>1) { strcpy(bufp++, ")"); --size; } } } else { rsize = strlcpy(bufp, racename(f->locale, u, u->irace), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (u->faction==f && u->irace!=u->race) { rsize = strlcpy(bufp, " (", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, racename(f->locale, u, u->race), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (size>1) { strcpy(bufp++, ")"); --size; } } } #ifdef HEROES if (fval(u, UFL_HERO) && (u->faction == f || omniscient(f))) { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, LOC(f->locale, "hero"), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } #endif /* status */ if (u->number && (u->faction == f || telepath_see || isbattle)) { const char * c = locale_string(f->locale, hp_status(u)); rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, report_kampfstatus(u, f->locale), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (c || fval(u, UFL_HUNGER)) { rsize = strlcpy(bufp, " (", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (c) { rsize = strlcpy(bufp, c, size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } if (fval(u, UFL_HUNGER)) { if (c) rsize = strlcpy(bufp, ", hungert", size); else rsize = strlcpy(bufp, "hungert", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } if (size>1) { strcpy(bufp++, ")"); --size; } } } if (getguard(u)) { rsize = strlcpy(bufp, ", bewacht die Region", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } if ((b = usiege(u))!=NULL) { rsize = strlcpy(bufp, ", belagert ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, buildingname(b), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } dh = 0; if (u->faction == f || telepath_see) { for (sk = 0; sk != MAXSKILLS; sk++) { rsize = spskill(bufp, size, f->locale, u, sk, &dh, 1); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } dh = 0; if (f == u->faction || telepath_see || omniscient(f)) { show = u->items; } else if (!itemcloak && 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, false); if (ic && *ic && in>0) { 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, false); if (sc==ic || strcmp(sc, ic)==0) { ishow->number+=itm->number; break; } } if (ishow==NULL) { ishow = i_add(&show, i_new(itm->type, itm->number)); } } } } else { show = NULL; } for (itm=show; itm; itm=itm->next) { const char * ic; int in; report_item(u, itm, f, &ic, NULL, &in, false); if (in==0 || ic==NULL) continue; rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (!dh) { bufp += snprintf(bufp, size, "%s: ", LOC(f->locale, "nr_inventory")); size = sizeof(buf)-(bufp-buf); dh = 1; } if (in == 1) { rsize = strlcpy(bufp, ic, size); } else { rsize = snprintf(bufp, size, "%d %s", in, ic); } if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } if (show!=u->items) while (show) i_free(i_remove(&show, show)); if (u->faction == f || telepath_see) { sc_mage * m = get_mage(u); if (m!=NULL) { spell_list *slist = m->spells; int t = effskill(u, SK_MAGIC); bufp += snprintf(bufp, size, ". Aura %d/%d", get_spellpoints(u), max_spellpoints(u->region,u)); size = sizeof(buf)-(bufp-buf); for (dh=0; slist; slist=slist->next) { spell * sp = slist->data; if (sp->level > t) continue; if (!dh) { rsize = snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_spells")); dh = 1; } else { rsize = strlcpy(bufp, ", ", size); } if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, spell_name(sp, f->locale), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } for (i=0; i!=MAXCOMBATSPELLS; ++i) { if (get_combatspell(u, i)) break; } if (i!=MAXCOMBATSPELLS) { bufp += snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_combatspells")); size = sizeof(buf)-(bufp-buf); dh = 0; for (i = 0; i < MAXCOMBATSPELLS; i++){ const spell *sp; if (!dh){ dh = 1; } else { rsize = strlcpy(bufp, ", ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } sp = get_combatspell(u,i); if (sp) { int sl = get_combatspelllevel(u, i); rsize = strlcpy(bufp, spell_name(sp, u->faction->locale), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (sl > 0) { bufp += snprintf(bufp, size, " (%d)", sl); size = sizeof(buf)-(bufp-buf); } } else { rsize = strlcpy(bufp, LOC(f->locale, "nr_nospells"), size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } } } #ifdef LASTORDER if (!isbattle && u->lastorder) { rsize = buforder(bufp, size, u->lastorder, 0); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } #else if (!isbattle) { boolean printed = 0; order * ord;; for (ord=u->old_orders;ord;ord=ord->next) { if (is_repeated(ord)) { if (printedorders;ord;ord=ord->next) { if (is_repeated(ord)) { if (printeddisplay && u->display[0]) { rsize = strlcpy(bufp, "; ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, u->display, size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; i = u->display[strlen(u->display) - 1]; } if (i != '!' && i != '?' && i != '.') { if (size>1) { strcpy(bufp++, "."); --size; } } pzTmp = uprivate(u); if (u->faction == f && pzTmp) { rsize = strlcpy(bufp, " (Bem: ", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, pzTmp, size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, ")", size); if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } dh=0; if (!getarnt && f) { if (alliedfaction(getplane(u->region), f, fv, HELP_ALL)) { dh = 1; } } return dh; } /* TODO: telepath_see wird nicht berücksichtigt: Parteien mit * telepath_see sollten immer einzelne Einheiten zu sehen * bekommen, alles andere ist darstellungsteschnisch kompliziert. */ #ifdef USE_UGROUPS int bufunit_ugroupleader(const faction * f, const unit * u, int indent, int mode) { int i, dh; int getarnt = fval(u, UFL_PARTEITARNUNG); faction *fv; const char *pzTmp; attrib *a_fshidden = NULL; item * itm; item * show; ugroup *ug = findugroup(u); boolean guards = false; boolean sieges = false; boolean itemcloak = false; static const curse_type * itemcloak_ct = 0; static boolean init = false; if (!init) { init = true; itemcloak_ct = ct_find("itemcloak"); } if (itemcloak_ct!=NULL) { itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); } if(fspecial(u->faction, FS_HIDDEN)) a_fshidden = a_find(u->attribs, &at_fshidden); strcpy(buf, u->name); fv = visible_faction(f, u); if (getarnt) { scat(", "); scat(LOC(f->locale, "anonymous")); } else { scat(", "); scat(factionname(fv)); } scat(", "); for(i = 0; i < ug->members; i++) { unit *uc = ug->unit_array[i]; if(uc->faction != f && a_fshidden && a_fshidden->data.ca[0] == 1 && effskill(uc, SK_STEALTH) >= 6) { scat("? "); } else { icat(uc->number); scat(" "); } pzTmp = get_racename(uc->attribs); if (pzTmp || u->irace != uc->race) { if (pzTmp) scat(pzTmp); else scat(racename(f->locale, u, u->irace)); scat(" ("); scat(itoa36(uc->no)); scat("), "); } else { scat(racename(f->locale, u, u->race)); scat(" ("); scat(itoa36(uc->no)); scat("), "); } if(getguard(uc)) guards = true; if(usiege(uc)) sieges = true; } if(guards == true) scat(", bewacht die Region"); if(sieges == true) { scat(", belagert "); for(i = 0; i < ug->members; i++) { building *b = usiege(ug->unit_array[i]); if(b) { scat(buildingname(b)); scat(", "); } } } dh = 0; show = NULL; for(i = 0; i < ug->members; i++) { unit *uc = ug->unit_array[i]; if (!itemcloak && mode >= see_unit && !(a_fshidden && a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3)) { for (itm=uc->items;itm;itm=itm->next) { item *ishow; const char * ic; int in; report_item(u, itm, f, NULL, &ic, &in, false); if (ic && *ic && in>0) { 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, false); if (sc==ic || strcmp(sc, ic)==0) { ishow->number+=itm->number; break; } } if (ishow==NULL) { ishow = i_add(&show, i_new(itm->type, itm->number)); } } } } } for (itm=show; itm; itm=itm->next) { const char * ic; int in; report_item(u, itm, f, &ic, NULL, &in, false); if (in==0 || ic==NULL) continue; scat(", "); if (!dh) { sprintf(buf+strlen(buf), "%s: ", LOC(f->locale, "nr_inventory")); dh = 1; } if (in == 1) { scat(ic); } else { icat(in); scat(" "); scat(ic); } } if(show) while(show) i_free(i_remove(&show, show)); i = 0; if (u->display && u->display[0]) { scat("; "); scat(u->display); i = u->display[strlen(u->display) - 1]; } if (i != '!' && i != '?' && i != '.') scat("."); dh=0; if (!getarnt && f && f->allies) { ally *sf; for (sf = f->allies; sf && !dh; sf = sf->next) { if (sf->status > 0 && sf->status <= HELP_ALL && sf->faction == fv) { dh = 1; } } } return dh; } #endif size_t spskill(char * buffer, size_t size, const struct locale * lang, const struct unit * u, skill_t sk, int *dh, int days) { char * bufp = buffer; int i, effsk; size_t rsize; size_t tsize = 0; if (!u->number) return 0; if (!has_skill(u, sk)) return 0; rsize = strlcpy(bufp, ", ", size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (!*dh) { rsize = strlcpy(bufp, LOC(lang, "nr_skills"), size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, ": ", size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; *dh = 1; } rsize = strlcpy(bufp, skillname(sk, lang), size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, " ", size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if (sk == SK_MAGIC){ if (find_magetype(u) != M_GRAU){ rsize = strlcpy(bufp, LOC(lang, mkname("school", magietypen[find_magetype(u)])), size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; rsize = strlcpy(bufp, " ", size); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } if (sk == SK_STEALTH && fval(u, UFL_STEALTH)) { i = u_geteffstealth(u); if (i>=0) { rsize = slprintf(bufp, size, "%d/", i); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } effsk = effskill(u, sk); rsize = slprintf(bufp, size, "%d", effsk); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; if(u->faction->options & Pow(O_SHOWSKCHANGE)) { skill *skill = get_skill(u, sk); int oldeff = 0; int diff; if (skill->old > 0) { oldeff = skill->old + get_modifier(u, sk, skill->old, u->region, false); } oldeff = max(0, oldeff); diff = effsk - oldeff; if (diff != 0) { rsize = slprintf(bufp, size, " (%s%d)", (diff>0)?"+":"", diff); tsize += rsize; if (rsize>size) rsize = size-1; size -= rsize; bufp += rsize; } } return tsize; } void lparagraph(struct strlist ** SP, 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 (). */ char *buflocal = calloc(strlen(s) + indent + 1, sizeof(char)); if (indent) { memset(buflocal, ' ', indent); if (mark) buflocal[indent - 2] = mark; } strcpy(buflocal + indent, s); addstrlist(SP, buflocal); free(buflocal); } void spunit(struct strlist ** SP, const struct faction * f, const unit * u, int indent, int mode) { int dh; #ifdef USE_UGROUPS ugroup *ug = findugroup(u); if(ug) { if(is_ugroupleader(u, ug)) { dh = bufunit_ugroupleader(f, u, indent, mode); } else { return; } } else #endif dh = bufunit(f, u, indent, mode); lparagraph(SP, buf, indent, (char) ((u->faction == f) ? '*' : (dh ? '+' : '-'))); } /* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und * Spionage des Spions */ void spy_message(int spy, unit *u, unit *target) { const char *c; produceexp(u, SK_SPY, u->number); /* Infos: * - Kampfstatus * - verborgene Gegenstände: Amulette, Ringe, Phiolen, Geld * - Partei * - Talentinfo * - Zaubersprüche * - Zauberwirkungen */ /* mit spy=100 (magische Spionage) soll alles herausgefunden werden */ buf[0]='\0'; if (spy > 99){ /* magische Spionage */ /* Zauberwirkungen */ } if (spy > 20){ sc_mage * m = get_mage(target); /* bei Magiern Zaubersprüche und Magiegebiet */ if (m) { spell_list *slist = m->spells; boolean first = true; scat("Magiegebiet: "); scat(LOC(u->faction->locale, magietypen[find_magetype(target)])); scat(", Sprüche: "); for (;slist; slist=slist->next) { spell * sp = slist->data; if (first) { first = false; } else { scat(", "); } scat(spell_name(sp, u->faction->locale)); } if (first) scat("Keine"); scat(". "); } } if (spy > 6){ /* wahre Partei */ scat("Partei '"); scat(factionname(target->faction)); scat("'. "); } else { /* ist die Einheit in Spionage nicht gut genug, glaubt sie die * Parteitarnung */ faction *fv = visible_faction(u->faction,target); if (fv != target->faction){ scat("Partei '"); scat(factionname(fv)); scat("'. "); } else if (!fval(target, UFL_PARTEITARNUNG)){ scat("Partei '"); scat(factionname(target->faction)); scat("'. "); } } if (spy > 0){ scat("Talente: "); { int first = 1; int found = 0; skill_t sk; for (sk = 0; sk != MAXSKILLS; sk++) { if (has_skill(target, sk)) { found++; if (first == 1) { first = 0; } else { scat(", "); } scat(skillname(sk, u->faction->locale)); scat(" "); icat(eff_skill(target, sk, target->region)); } } if (found == 0) { scat("Keine"); } scat(". "); } scat("Im Gepäck sind"); { boolean first = true; int found = 0; item * itm; for (itm=target->items;itm;itm=itm->next) { if (itm->number>0) { resource_type * rtype = itm->type->rtype; ++found; if (first) { first = false; scat(": "); } else { scat(", "); } if (itm->number == 1) { scat("1 "); scat(locale_string(u->faction->locale, resourcename(rtype, 0))); } else { icat(itm->number); scat(" "); scat(locale_string(u->faction->locale, resourcename(rtype, NMF_PLURAL))); } } } if (found == 0) { scat(" keine verborgenen Gegenstände"); } scat(". "); } } /* spion ist gleich gut wie Wahrnehmung Opfer */ /* spion ist schlechter als Wahrnehmung Opfer */ { /* immer */ scat("Kampfstatus: "); scat(report_kampfstatus(target, u->faction->locale)); c = locale_string(u->faction->locale, hp_status(target)); if (c && strlen(c)) sprintf(buf, "%s (%s)", buf, c); scat("."); } ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target report", u, target, strdup(buf))); } const struct unit * ucansee(const struct faction *f, const struct unit *u, const struct unit *x) { if (cansee(f, u->region, u, 0)) return u; return x; } faction_list * get_addresses(faction * f, struct seen_region * seehash[]) { /* "TODO: travelthru" */ region *r, *last = lastregion(f); const faction * lastf = NULL; faction_list * flist = calloc(1, sizeof(faction_list)); flist->data = f; for (r=firstregion(f);r!=last;r=r->next) { const unit * u = r->units; const seen_region * sr = find_seen(seehash, r); if (sr==NULL) continue; while (u!=NULL) { faction * sf = visible_faction(f, u); boolean ballied = sf && sf!=f && sf!=lastf && !fval(u, UFL_PARTEITARNUNG) && cansee(f, r, u, 0); if (ballied || ALLIED(f, sf)) { faction_list ** fnew = &flist; while (*fnew && (*fnew)->data->no < sf->no) { fnew =&(*fnew)->next; } if ((*fnew==NULL) || (*fnew)->data!=sf) { faction_list * finsert = malloc(sizeof(faction_list)); finsert->next = *fnew; *fnew = finsert; finsert->data = sf; } lastf = sf; } u = u->next; } } if (f->alliance != NULL) { faction *f2; for(f2 = factions; f2; f2 = f2->next) { if(f2->alliance != NULL && f2->alliance == f->alliance) { faction_list ** fnew = &flist; while (*fnew && (*fnew)->data->no < f2->no) { fnew =&(*fnew)->next; } if ((*fnew==NULL) || (*fnew)->data!=f2) { faction_list * finsert = malloc(sizeof(faction_list)); finsert->next = *fnew; *fnew = finsert; finsert->data = f2; } } } } return flist; } #define MAXSEEHASH 10007 seen_region * reuse; seen_region ** seen_init(void) { return (seen_region **)calloc(MAXSEEHASH, sizeof(seen_region*)); } void seen_done(seen_region * seehash[]) { int i; for (i=0;i!=MAXSEEHASH;++i) { seen_region * sd = seehash[i]; if (sd==NULL) continue; while (sd->nextHash!=NULL) sd = sd->nextHash; sd->nextHash = reuse; reuse = seehash[i]; seehash[i] = NULL; } free(seehash); } void free_seen(void) { while (reuse) { seen_region * r = reuse; reuse = reuse->nextHash; free(r); } } seen_region * find_seen(struct seen_region * seehash[], const region * r) { unsigned int index = reg_hashkey(r) % MAXSEEHASH; seen_region * find = seehash[index]; while (find) { if (find->r==r) return find; find=find->nextHash; } return NULL; } void get_seen_interval(struct seen_region ** seen, region ** first, region ** last) { /* this is required to find the neighbour regions of the ones we are in, * which may well be outside of [firstregion, lastregion) */ #ifdef ENUM_REGIONS int i; for (i=0;i!=MAXSEEHASH;++i) { seen_region * sr = seen[i]; while (sr!=NULL) { if (*first==NULL || sr->r->index<(*first)->index) { *first = sr->r; } if (*last!=NULL && sr->r->index>=(*last)->index) { *last = sr->r->next; } sr = sr->nextHash; } } #else region * r = regions; while (r!=first) { if (find_seen(seen, r)!=NULL) { *first = r; break; } r = r->next; } r = *last; while (r!=NULL) { if (find_seen(seen, r)!=NULL) { *last = r->next; } r = r->next; } #endif } boolean add_seen(struct seen_region * seehash[], struct region * r, unsigned char mode, boolean dis) { seen_region * find = find_seen(seehash, r); if (find==NULL) { unsigned int index = reg_hashkey(r) % MAXSEEHASH; if (!reuse) reuse = (seen_region*)calloc(1, sizeof(struct seen_region)); find = reuse; reuse = reuse->nextHash; find->nextHash = seehash[index]; seehash[index] = find; find->r = r; } else if (find->mode >= mode) { return false; } find->mode = mode; find->disbelieves |= dis; return true; }