- reorganizing units for faster report-generation

- more xml functionality
This commit is contained in:
Enno Rehling 2008-06-06 21:54:19 +00:00
parent 277141c45d
commit b5bffaf75e
13 changed files with 519 additions and 357 deletions

View file

@ -669,6 +669,7 @@ cr_output_unit(FILE * F, const region * r,
boolean itemcloak = false;
static const curse_type * itemcloak_ct = 0;
static boolean init = false;
item result[MAX_INVENTORY];
if (fval(u->race, RCF_INVISIBLE)) return;
@ -889,29 +890,12 @@ cr_output_unit(FILE * F, const region * r,
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, itm->number));
}
}
}
&& a_fshidden->data.ca[1] == 1 && effskill(u, SK_STEALTH) >= 3))
{
int n = report_items(u->items, result, MAX_INVENTORY, u, f);
assert(n>=0);
if (n>0) show = result;
else show = NULL;
} else {
show = NULL;
}
@ -928,12 +912,6 @@ cr_output_unit(FILE * F, const region * r,
}
fprintf(F, "%d;%s\n", in, add_translation(ic, locale_string(f->locale, ic)));
}
if (show!=u->items) {
/* free the temporary items */
while (show) {
i_free(i_remove(&show, show));
}
}
print_curses(F, f, u, TYP_UNIT);
}
@ -1057,7 +1035,7 @@ encode_region(const faction * f, const region * r) {
}
static char *
report_resource(char * buf, const char * name, const struct locale * loc, int amount, int level)
cr_output_resource(char * buf, const char * name, const struct locale * loc, int amount, int level)
{
buf += sprintf(buf, "RESOURCE %u\n", hashstring(name));
buf += sprintf(buf, "\"%s\";type\n", add_translation(name, LOC(loc, name)));
@ -1117,61 +1095,32 @@ cr_borders(seen_region ** seen, const region * r, const faction * f, int seemode
}
static void
cr_output_resources(FILE * F, report_context * ctx, region * r, struct rawmaterial * res, int see_mode)
cr_output_resources(FILE * F, report_context * ctx, seen_region * sr)
{
char cbuf[BUFFERSIZE], *pos = cbuf;
region * r = sr->r;
faction * f = ctx->f;
resource_report result[MAX_RAWMATERIALS];
int n, size = report_resources(sr, result, MAX_RAWMATERIALS, f);
#ifdef RESOURCECOMPAT
int trees = rtrees(r, 2);
int saplings = rtrees(r, 1);
#ifdef RESOURCECOMPAT
if (trees > 0) fprintf(F, "%d;Baeume\n", trees);
if (saplings > 0) fprintf(F, "%d;Schoesslinge\n", saplings);
if (fval(r, RF_MALLORN) && (trees > 0 || saplings > 0))
fprintf(F, "1;Mallorn\n");
#endif
if (!fval(r, RF_MALLORN)) {
if (saplings) pos = report_resource(pos, "rm_sapling", f->locale, saplings, -1);
if (trees) pos = report_resource(pos, "rm_trees", f->locale, trees, -1);
} else {
if (saplings) pos = report_resource(pos, "rm_mallornsapling", f->locale, saplings, -1);
if (trees) pos = report_resource(pos, "rm_mallorn", f->locale, trees, -1);
for (n=0;n<size;++n) {
if (result[n].level>=0 && result[n].number>=0) {
fprintf(F, "%d;%s\n", result[n].number, crtag(result[n].name));
}
}
if (see_mode>=see_unit) {
while (res) {
int maxskill = 0;
int level = -1;
int visible = -1;
const item_type * itype = resource2item(res->type->rtype);
if (res->type->visible==NULL) {
visible = res->amount;
level = res->level + itype->construction->minskill - 1;
} else {
const unit * u;
for (u=r->units; visible!=res->amount && u!=NULL; u=u->next) {
if (u->faction == f) {
int s = eff_skill(u, itype->construction->skill, r);
if (s>maxskill) {
if (s>=itype->construction->minskill) {
assert(itype->construction->minskill>0);
level = res->level + itype->construction->minskill - 1;
}
maxskill = s;
visible = res->type->visible(res, maxskill);
}
}
}
}
if (level>=0 && visible >=0) {
pos = report_resource(pos, res->type->name, f->locale, visible, level);
#ifdef RESOURCECOMPAT
if (visible>=0) fprintf(F, "%d;%s\n", visible, crtag(res->type->name));
#endif
}
res = res->next;
for (n=0;n<size;++n) {
if (result[n].number>=0) {
pos = cr_output_resource(pos, result[n].name, f->locale, result[n].number, result[n].level);
}
}
if (pos!=cbuf) fputs(cbuf, F);
@ -1248,7 +1197,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
/* this writes both some tags (RESOURCECOMPAT) and a block.
* must not write any blocks before it */
cr_output_resources(F, ctx, r, r->resources, sr->mode);
cr_output_resources(F, ctx, sr);
if (sr->mode>=see_unit) {
/* trade */
@ -1350,6 +1299,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
}
}
}
/* main function of the creport. creates the header and traverses all regions */
static int
report_computer(const char * filename, report_context * ctx, const char * charset)

View file

@ -3003,16 +3003,16 @@ do_work(unit * u, order * ord, request * o)
region * r = u->region;
int w;
if(fval(u, UFL_WERE)) {
cmistake(u, ord, 313, MSG_INCOME);
if (fval(u, UFL_WERE)) {
if (ord) cmistake(u, ord, 313, MSG_INCOME);
return -1;
}
if (besieged(u)) {
cmistake(u, ord, 60, MSG_INCOME);
if (ord) cmistake(u, ord, 60, MSG_INCOME);
return -1;
}
if (u->ship && is_guarded(r, u, GUARD_CREWS)) {
cmistake(u, ord, 69, MSG_INCOME);
if (ord) cmistake(u, ord, 69, MSG_INCOME);
return -1;
}
w = wage(r, u->faction, u->race);
@ -3022,7 +3022,7 @@ do_work(unit * u, order * ord, request * o)
working += u->number;
return 0;
}
else if (!is_monsters(u->faction)) {
else if (ord && !is_monsters(u->faction)) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "race_cantwork", "race", u->race));
}

View file

@ -3917,8 +3917,6 @@ processorders (void)
process();
/*************************************************/
for (r = regions;r;r=r->next) reorder_owners(r);
puts(" - Attribute altern");
ageing();
remove_empty_units();
@ -3932,6 +3930,12 @@ processorders (void)
* Beschreibungen geändert haben */
update_spells();
warn_password();
/* we reorder the owners to be at the top of the building
* and also everyone in the same building/ship in sequence */
for (r = regions;r;r=r->next) {
reorder_units(r);
}
}
int

View file

@ -651,7 +651,7 @@ rps_nowrap(FILE * F, const char *s)
}
static void
rpunit(FILE * F, const faction * f, const unit * u, int indent, int mode)
report_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
{
attrib *a_otherfaction;
char marker;
@ -829,8 +829,9 @@ see_border(const border * b, const faction * f, const region * r)
}
static void
describe(FILE * F, const region * r, int partial, faction * f)
describe(FILE * F, const seen_region * sr, faction * f)
{
const region * r = sr->r;
int n;
boolean dh;
direction_t d;
@ -885,13 +886,13 @@ describe(FILE * F, const region * r, int partial, faction * f)
bytes = (int)f_regionid(r, f, bufp, size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
if (partial == 1) {
if (sr->mode==see_travel) {
bytes = (int)strlcpy(bufp, " (durchgereist)", size);
}
else if (partial == 3) {
else if (sr->mode==see_neighbour) {
bytes = (int)strlcpy(bufp, " (benachbart)", size);
}
else if (partial == 2) {
else if (sr->mode==see_lighthouse) {
bytes = (int)strlcpy(bufp, " (vom Turm erblickt)", size);
} else {
bytes = 0;
@ -931,35 +932,14 @@ describe(FILE * F, const region * r, int partial, faction * f)
}
/* iron & stone */
if (partial == 0 && f != (faction *) NULL) {
struct rawmaterial * res;
for (res=r->resources;res;res=res->next) {
int level = -1;
int visible = -1;
int maxskill = 0;
const item_type * itype = resource2item(res->type->rtype);
if (res->type->visible==NULL) {
visible = res->amount;
level = res->level + itype->construction->minskill - 1;
} else {
const unit * u;
for (u=r->units; visible!=res->amount && u!=NULL; u=u->next) {
if (u->faction == f) {
int s = eff_skill(u, itype->construction->skill, r);
if (s>maxskill) {
if (s>=itype->construction->minskill) {
level = res->level + itype->construction->minskill - 1;
}
maxskill = s;
visible = res->type->visible(res, maxskill);
}
}
}
}
if (level>=0 && visible >= 0) {
bytes = snprintf(bufp, size, ", %d %s/%d", visible,
LOC(f->locale, res->type->name),
res->level + itype->construction->minskill - 1);
if (sr->mode==see_unit && f != (faction *) NULL) {
resource_report result[MAX_RAWMATERIALS];
int n, numresults = report_resources(sr, result, MAX_RAWMATERIALS, f);
for (n=0;n<numresults;++n) {
if (result[n].number>=0 && result[n].level>=0) {
bytes = snprintf(bufp, size, ", %d %s/%d", result[n].number,
LOC(f->locale, result[n].name), result[n].level);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
}
@ -983,7 +963,7 @@ describe(FILE * F, const region * r, int partial, faction * f)
}
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (rmoney(r) && partial == 0) {
if (rmoney(r) && sr->mode==see_unit) {
bytes = snprintf(bufp, size, ", %d ", rmoney(r));
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, resourcename(oldresourcetype[R_SILVER], rmoney(r)!=1)), size);
@ -1091,7 +1071,7 @@ describe(FILE * F, const region * r, int partial, faction * f)
*bufp = 0;
rparagraph(F, buf, 0, 0, 0);
if (partial==0 && rplane(r) == get_astralplane() &&
if (sr->mode==see_unit && rplane(r) == get_astralplane() &&
!is_cursed(r->attribs, C_ASTRALBLOCK, 0)) {
/* Sonderbehandlung Teleport-Ebene */
region_list *rl = astralregions(r, inhabitable);
@ -1728,11 +1708,72 @@ list_address(FILE * F, const faction * uf, const faction_list * seenfactions)
rpline(F);
}
void
report_building(FILE *F, const region * r, const building * b, const faction * f, int mode)
static void
report_ship(FILE * F, const seen_region * sr, const ship * sh, const faction * f, const unit * captain)
{
const region * r = sr->r;
char buffer[8192], * bufp = buffer;
size_t size = sizeof(buffer) - 1;
int bytes;
char ch;
rnl(F);
if (captain && captain->faction == f) {
int n = 0, p = 0;
getshipweight(sh, &n, &p);
n = (n+99) / 100; /* 1 Silber = 1 GE */
bytes = snprintf(bufp, size, "%s, %s, (%d/%d)", shipname(sh),
LOC(f->locale, sh->type->name[0]), n, shipcapacity(sh) / 100);
} else {
bytes = snprintf(bufp, size, "%s, %s", shipname(sh), LOC(f->locale, sh->type->name[0]));
}
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
assert(sh->type->construction->improvement==NULL); /* sonst ist construction::size nicht ship_type::maxsize */
if (sh->size!=sh->type->construction->maxsize) {
bytes = snprintf(bufp, size, ", %s (%d/%d)",
LOC(f->locale, "nr_undercons"), sh->size,
sh->type->construction->maxsize);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (sh->damage) {
int percent = (sh->damage*100+DAMAGE_SCALE-1)/(sh->size*DAMAGE_SCALE);
bytes = snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (!fval(r->terrain, SEA_REGION)) {
if (sh->coast != NODIRECTION) {
bytes = (int)strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, coasts[sh->coast]), size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
}
ch = 0;
if (sh->display && sh->display[0]) {
bytes = (int)strlcpy(bufp, "; ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, sh->display, size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
ch = sh->display[strlen(sh->display) - 1];
}
if (ch != '!' && ch != '?' && ch != '.') {
bytes = (int)strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
*bufp = 0;
rparagraph(F, buffer, 2, 0, 0);
print_curses(F, f, sh, TYP_SHIP, 4);
}
static void
report_building(FILE *F, const seen_region * sr, const building * b, const faction * f)
{
region * r = sr->r;
int i, bytes;
unit *u;
const char * bname;
const struct locale * lang = NULL;
const building_type * type = b->type;
@ -1740,6 +1781,8 @@ report_building(FILE *F, const region * r, const building * b, const faction * f
char buffer[8192], * bufp = buffer;
size_t size = sizeof(buffer) - 1;
rnl(F);
if (!bt_illusion) bt_illusion = bt_find("illusion");
if (f) lang = f->locale;
@ -1770,7 +1813,7 @@ report_building(FILE *F, const region * r, const building * b, const faction * f
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (b->besieged > 0 && mode>=see_lighthouse) {
if (b->besieged > 0 && sr->mode>=see_lighthouse) {
bytes = (int)strlcpy(bufp, ", belagert von ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, itoa10(b->besieged), size);
@ -1852,21 +1895,9 @@ report_building(FILE *F, const region * r, const building * b, const faction * f
*bufp = 0;
rparagraph(F, buffer, 2, 0, 0);
if (mode<see_lighthouse) return;
if (sr->mode<see_lighthouse) return;
print_curses(F, f, b, TYP_BUILDING, 4);
for (u = r->units; u; u = u->next) {
if (u->building == b) {
assert(fval(u, UFL_OWNER) || !"you must call reorder_owners() first!");
rpunit(F, f, u, 6, mode);
u = u->next;
break;
}
}
for (;u!=NULL && u->building==b;u=u->next) {
rpunit(F, f, u, 6, mode);
}
}
int
@ -1874,12 +1905,9 @@ report_plaintext(const char * filename, report_context * ctx, const char * chars
{
int flag = 0;
char ch;
int dh;
int anyunits;
const struct region *r;
faction * f = ctx->f;
building *b;
ship *sh;
unit *u;
char pzTime[64];
attrib *a;
@ -1955,7 +1983,6 @@ report_plaintext(const char * filename, report_context * ctx, const char * chars
}
#endif
dh = 0;
if (f->age <= 2) {
const char * s;
if (f->age <= 1) {
@ -2154,13 +2181,15 @@ report_plaintext(const char * filename, report_context * ctx, const char * chars
for (;sr!=NULL;sr=sr->next) {
region * r = sr->r;
int stealthmod = stealth_modifier(sr->mode);
building * b = r->buildings;
ship * sh = r->ships;
if (sr->mode<see_lighthouse) continue;
/* Beschreibung */
if (sr->mode==see_unit) {
anyunits = 1;
describe(F, r, 0, f);
describe(F, sr, f);
if (!fval(r->terrain, SEA_REGION) && rpeasants(r)/TRADE_FRACTION > 0) {
rnl(F);
prices(F, r, f);
@ -2170,15 +2199,15 @@ report_plaintext(const char * filename, report_context * ctx, const char * chars
}
else {
if (sr->mode==see_far) {
describe(F, r, 3, f);
describe(F, sr, f);
guards(F, r, f);
durchreisende(F, r, f);
}
else if (sr->mode==see_lighthouse) {
describe(F, r, 2, f);
describe(F, sr, f);
durchreisende(F, r, f);
} else {
describe(F, r, 1, f);
describe(F, sr, f);
durchreisende(F, r, f);
}
}
@ -2194,106 +2223,43 @@ report_plaintext(const char * filename, report_context * ctx, const char * chars
rp_messages(F, r->msgs, f, 0, true);
if (mlist) rp_messages(F, mlist, f, 0, true);
}
/* Burgen und ihre Einheiten */
for (b = rbuildings(r); b; b = b->next) {
rnl(F);
report_building(F, r, b, f, sr->mode);
}
/* Restliche Einheiten */
if (stealthmod>INT_MIN) {
for (u = r->units; u; u = u->next) {
if (!u->building && !u->ship) {
if (u->faction == f || cansee(f, r, u, stealthmod)) {
if (dh == 0 && !(rbuildings(r) || r->ships)) {
dh = 1;
/* rnl(F); */
}
rpunit(F, f, u, 4, sr->mode);
}
/* report all units. they are pre-sorted in an efficient manner */
u = r->units;
while (b) {
while (b && (!u || u->building!=b)) {
report_building(F, sr, b, f);
b = b->next;
}
if (b) {
report_building(F, sr, b, f);
while (u && u->building==b) {
report_unit(F, f, u, 6, sr->mode);
u = u->next;
}
b = b->next;
}
}
/* Schiffe und ihre Einheiten */
for (sh = r->ships; sh; sh = sh->next) {
faction *of = NULL;
rnl(F);
/* Gewicht feststellen */
for (u = r->units; u; u = u->next) {
if (u->ship == sh && fval(u, UFL_OWNER)) {
of = u->faction;
break;
while (u && !u->ship) {
if (stealthmod>INT_MIN) {
if (u->faction == f || cansee(f, r, u, stealthmod)) {
report_unit(F, f, u, 4, sr->mode);
}
}
bufp = buf;
size = sizeof(buf) - 1;
if (of == f) {
int n = 0, p = 0;
getshipweight(sh, &n, &p);
n = (n+99) / 100; /* 1 Silber = 1 GE */
bytes = snprintf(bufp, size, "%s, %s, (%d/%d)", shipname(sh),
LOC(f->locale, sh->type->name[0]), n, shipcapacity(sh) / 100);
} else {
bytes = snprintf(bufp, size, "%s, %s", shipname(sh), LOC(f->locale, sh->type->name[0]));
u = u->next;
}
while (sh) {
while (sh && (!u || u->ship!=sh)) {
report_ship(F, sr, sh, f, NULL);
sh = sh->next;
}
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
assert(sh->type->construction->improvement==NULL); /* sonst ist construction::size nicht ship_type::maxsize */
if (sh->size!=sh->type->construction->maxsize) {
bytes = snprintf(bufp, size, ", %s (%d/%d)",
LOC(f->locale, "nr_undercons"), sh->size,
sh->type->construction->maxsize);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (sh->damage) {
int percent = (sh->damage*100+DAMAGE_SCALE-1)/(sh->size*DAMAGE_SCALE);
bytes = snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (!fval(r->terrain, SEA_REGION)) {
if (sh->coast != NODIRECTION) {
bytes = (int)strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, coasts[sh->coast]), size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
}
ch = 0;
if (sh->display && sh->display[0]) {
bytes = (int)strlcpy(bufp, "; ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, sh->display, size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
ch = sh->display[strlen(sh->display) - 1];
}
if (ch != '!' && ch != '?' && ch != '.') {
bytes = (int)strlcpy(bufp, ".", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
*bufp = 0;
rparagraph(F, buf, 2, 0, 0);
print_curses(F, f, sh, TYP_SHIP, 4);
for (u = r->units; u; u = u->next) {
if (u->ship == sh && fval(u, UFL_OWNER)) {
rpunit(F, f, u, 6, sr->mode);
break;
}
}
for (u = r->units; u; u = u->next) {
if (u->ship == sh && !fval(u, UFL_OWNER)) {
rpunit(F, f, u, 6, sr->mode);
if (sh) {
report_ship(F, sr, sh, f, u);
while (u && u->ship==sh) {
report_unit(F, f, u, 6, sr->mode);
u = u->next;
}
sh = sh->next;
}
}

View file

@ -114,17 +114,116 @@ xml_i(double number)
}
static xmlNodePtr
report_unit(report_context * ctx, unit * u, int mode)
report_inventory(report_context * ctx, item * items, unit * u)
{
xml_context* xct = (xml_context*)ctx->userdata;
xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "items");
item * itm;
for (itm=items;itm;itm=itm->next) {
xmlNodePtr child = xmlNewNode(xct->ns_atl, BAD_CAST "item");
const char * name;
int n;
report_item(u, itm, ctx->f, NULL, &name, &n, true);
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "type", (xmlChar *)name);
xmlNodeAddContent(child, (xmlChar*)itoab(n, 10));
xmlAddChild(node, child);
}
return node;
}
static xmlNodePtr
xml_unit(report_context * ctx, unit * u, int mode)
{
xml_context* xct = (xml_context*)ctx->userdata;
xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "unit");
char unit_id[20];
char idbuffer[20];
static const curse_type * itemcloak_ct = 0;
static boolean init = false;
xmlNodePtr child;
sprintf(unit_id, "unit_%d", u->no);
xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, (xmlChar *)unit_id);
snprintf(idbuffer, sizeof(idbuffer), "unit_%d", u->no);
xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, (xmlChar *)idbuffer);
xmlNewNsProp(node, xct->ns_atl, BAD_CAST "key", BAD_CAST itoa36(u->no));
xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)u->name);
snprintf(idbuffer, sizeof(idbuffer), "faction_%d", u->faction->no);
child = xmlNewNode(xct->ns_atl, BAD_CAST "faction");
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (xmlChar *)idbuffer);
xmlAddChild(node, child);
if (!init) {
init = true;
itemcloak_ct = ct_find("itemcloak");
}
if (u->items) {
item result[MAX_INVENTORY];
item * show = NULL;
if (ctx->f == u->faction || omniscient(ctx->f)) {
show = u->items;
} else {
boolean see_items = (mode >= see_unit);
if (see_items) {
if (itemcloak_ct && !curse_active(get_curse(u->attribs, itemcloak_ct))) {
see_items = false;
} else {
see_items = effskill(u, SK_STEALTH) < 3;
}
}
if (see_items) {
int n = report_items(u->items, result, MAX_INVENTORY, u, ctx->f);
assert(n>=0);
if (n>0) show = result;
else show = NULL;
} else {
show = NULL;
}
}
if (show) {
xmlAddChild(node, report_inventory(ctx, show, u));
}
}
return node;
}
static xmlNodePtr
report_link(report_context * ctx, const xmlChar * role, const xmlChar * ref)
{
xml_context* xct = (xml_context*)ctx->userdata;
xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "link");
xmlNewNsProp(node, xct->ns_atl, BAD_CAST "role", role);
xmlNewNsProp(node, xct->ns_atl, BAD_CAST "ref", ref);
return node;
}
static xmlNodePtr
xml_resources(report_context * ctx, const seen_region * sr)
{
xml_context* xct = (xml_context*)ctx->userdata;
xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "resources");
resource_report result[MAX_RAWMATERIALS];
int n, size = report_resources(sr, result, MAX_RAWMATERIALS, ctx->f);
for (n=0;n<size;++n) {
if (result[n].number>=0) {
xmlNodePtr child = xmlNewNode(xct->ns_atl, BAD_CAST "resource");
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "type", (xmlChar*)result[n].name);
if (result[n].level>=0) {
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "level", (xmlChar*)itoab(result[n].level, 10));
}
xmlNodeAddContent(child, (xmlChar*)itoab(result[n].number, 10));
/* TODO: the visibility logic from creport */
xmlAddChild(node, child);
}
}
return node;
}
@ -135,11 +234,15 @@ report_faction(report_context * ctx, faction * f)
xmlNodePtr node = xmlNewNode(xct->ns_atl, BAD_CAST "faction");
char faction_id[20];
sprintf(faction_id, "faction_%d", f->no);
snprintf(faction_id, sizeof(faction_id), "faction_%d", f->no);
xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, (xmlChar *)faction_id);
xmlNewNsProp(node, xct->ns_atl, BAD_CAST "key", BAD_CAST itoa36(f->no));
xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)f->name);
if (ctx->f==f) {
xmlAddChild(node, report_link(ctx, BAD_CAST "race", BAD_CAST f->race->_name[0]));
if (f->items) xmlAddChild(node, report_inventory(ctx, f->items, NULL));
}
return node;
}
@ -165,16 +268,24 @@ report_region(report_context * ctx, seen_region * sr)
}
xmlAddChild(node, child);
child = xmlNewNode(xct->ns_atl, BAD_CAST "terrain");
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (xmlChar *)r->terrain->_name);
xmlAddChild(node, child);
if (r->land!=NULL) {
child = xmlNewTextChild(node, xct->ns_atl, BAD_CAST "name", (const xmlChar *)r->land->name);
if (r->land->items) {
xmlAddChild(node, report_inventory(ctx, r->land->items, NULL));
}
}
xmlAddChild(node, xml_resources(ctx, sr));
child = xmlNewNode(xct->ns_atl, BAD_CAST "terrain");
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", (const xmlChar *)terrain_name(r));
for (u=r->units;u;u=u->next) {
if (u->building || u->ship || (stealthmod>INT_MIN && cansee(ctx->f, r, u, stealthmod))) {
xmlAddChild(node, report_unit(ctx, u, sr->mode));
xmlAddChild(node, xml_unit(ctx, u, sr->mode));
}
}
return node;
@ -219,6 +330,8 @@ report_xml(const char * filename, report_context * ctx, const char * encoding)
xmlSaveFormatFileEnc(filename, doc, "utf-8", 1);
xmlFreeDoc(doc);
ctx->userdata = NULL;
return 0;
}

View file

@ -2484,7 +2484,7 @@ int
besieged(const unit * u)
{
/* belagert kann man in schiffen und burgen werden */
return (u
return (u && !global.disabled[K_BESIEGE]
&& u->building && u->building->besieged
&& u->building->besieged >= u->building->size * SIEGEFACTOR);
}
@ -2775,95 +2775,105 @@ add_income(unit * u, int type, int want, int qty)
}
void
reorder_owners(region * r)
reorder_units(region * r)
{
unit ** up=&r->units, ** useek;
building * b=NULL;
ship * sh=NULL;
#ifndef NDEBUG
size_t len = listlen(r->units);
#endif
for (b = r->buildings;b;b=b->next) {
unit ** ubegin = up;
unit ** uend = up;
unit ** unext = &r->units;
useek = up;
while (*useek) {
unit * u = *useek;
if (u->building==b) {
unit ** insert;
if (fval(u, UFL_OWNER)) {
unit * nu = *ubegin;
insert = ubegin;
if (nu!=u && nu->building==u->building && fval(nu, UFL_OWNER)) {
log_error(("[reorder_owners] %s hat mehrere Besitzer mit UFL_OWNER.\n", buildingname(nu->building)));
freset(nu, UFL_OWNER);
if (r->buildings) {
building * b = r->buildings;
while (*unext && b) {
unit ** ufirst = unext; /* where the first unit in the building should go */
unit ** umove = unext; /* a unit we consider moving */
unit * owner = NULL;
while (*umove) {
unit * u = *umove;
if (u->number && u->building==b) {
unit ** uinsert = unext;
if (fval(u, UFL_OWNER)) {
uinsert = ufirst;
owner = u;
}
}
else insert = uend;
if (insert != useek) {
*useek = u->next; /* raus aus der liste */
u->next = *insert;
*insert = u;
}
if (insert==uend) uend=&u->next;
}
if (*useek==u) useek = &u->next;
}
up = uend;
}
useek=up;
while (*useek) {
unit * u = *useek;
assert(!u->building);
if (u->ship==NULL) {
if (fval(u, UFL_OWNER)) {
log_warning(("[reorder_owners] Einheit %s war Besitzer von nichts.\n", unitname(u)));
freset(u, UFL_OWNER);
}
if (useek!=up) {
*useek = u->next; /* raus aus der liste */
u->next = *up;
*up = u;
}
up = &u->next;
}
if (*useek==u) useek = &u->next;
}
for (sh = r->ships;sh;sh=sh->next) {
unit ** ubegin = up;
unit ** uend = up;
useek = up;
while (*useek) {
unit * u = *useek;
if (u->ship==sh) {
unit ** insert;
if (fval(u, UFL_OWNER)) {
unit * nu = *ubegin;
insert = ubegin;
if (nu!=u && nu->ship==u->ship && fval(nu, UFL_OWNER)) {
log_error(("[reorder_owners] %s hat mehrere Besitzer mit UFL_OWNER.\n", shipname(nu->ship)));
freset(nu, UFL_OWNER);
if (umove!=uinsert) {
*umove = u->next;
u->next = *uinsert;
*uinsert = u;
} else {
/* no need to move, skip ahead */
umove = &u->next;
}
if (unext==uinsert) {
/* we have a new well-placed unit. jump over it */
unext = &u->next;
}
} else {
umove = &u->next;
}
else insert = uend;
if (insert!=useek) {
*useek = u->next; /* raus aus der liste */
u->next = *insert;
*insert = u;
}
if (insert==uend) uend=&u->next;
}
if (*useek==u) useek = &u->next;
if (!owner && ufirst!=unext) {
owner = *ufirst;
fset(owner, UFL_OWNER);
}
b = b->next;
}
}
if (r->ships) {
ship * sh = r->ships;
/* first, move all units up that are not on ships */
unit ** umove = unext; /* a unit we consider moving */
while (*umove) {
unit * u = *umove;
if (u->number && !u->ship) {
if (umove!=unext) {
*umove = u->next;
u->next = *unext;
*unext = u;
} else {
/* no need to move, skip ahead */
umove = &u->next;
}
/* we have a new well-placed unit. jump over it */
unext = &u->next;
} else {
umove = &u->next;
}
}
while (*unext && sh) {
unit ** ufirst = unext; /* where the first unit in the building should go */
unit ** umove = unext; /* a unit we consider moving */
unit * owner = NULL;
while (*umove) {
unit * u = *umove;
if (u->number && u->ship==sh) {
unit ** uinsert = unext;
if (fval(u, UFL_OWNER)) {
uinsert = ufirst;
owner = u;
}
if (umove!=uinsert) {
*umove = u->next;
u->next = *uinsert;
*uinsert = u;
} else {
/* no need to move, skip ahead */
umove = &u->next;
}
if (unext==uinsert) {
/* we have a new well-placed unit. jump over it */
unext = &u->next;
}
} else {
umove = &u->next;
}
}
if (!owner && ufirst!=unext) {
owner = *ufirst;
fset(owner, UFL_OWNER);
}
sh = sh->next;
}
up = uend;
}
#ifndef NDEBUG
assert(len==listlen(r->units));
#endif
}
int

View file

@ -355,7 +355,7 @@ extern const char * resourcepath(void);
extern void kernel_init(void);
extern void kernel_done(void);
extern void reorder_owners(struct region * r);
extern void reorder_units(struct region * r);
extern const char *localenames[];

View file

@ -203,9 +203,9 @@ new_itemtype(resource_type * rtype,
int iflags, int weight, int capacity)
{
item_type * itype;
assert (resource2item(rtype) == NULL);
assert(resource2item(rtype) == NULL);
assert(rtype->flags & RTF_ITEM);
itype = calloc(sizeof(item_type), 1);
itype->rtype = rtype;

View file

@ -37,6 +37,7 @@
#include <kernel/plane.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/resources.h>
#include <kernel/ship.h>
#include <kernel/skill.h>
#include <kernel/terrain.h>
@ -146,12 +147,12 @@ hp_status(const unit * u)
void
report_item(const unit * owner, const item * i, const faction * viewer, const char ** name, const char ** basename, int * number, boolean singular)
{
assert(owner->number);
if (owner->faction == viewer) {
assert(!owner || owner->number);
if (owner && 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) {
} else if (owner && i->type->rtype==r_silver) {
int pp = i->number/owner->number;
if (number) *number = 1;
if (pp > 50000 && dragonrace(owner->race)) {
@ -240,6 +241,132 @@ buforder(char * bufp, size_t size, const order * ord, int mode)
return tsize;
}
/** create a report of a list of items to a non-owner.
* \param result: an array of size items.
* \param size: maximum number of items to return
* \param owner: the owner of the items, or NULL for faction::items etc.
* \param viewer: the faction looking at the items
*/
int
report_items(const item * items, item * result, int size, const unit * owner, const faction * viewer)
{
const item * itm;
int n = 0; /* number of results */
assert(owner==NULL || viewer!=owner->faction || !"not required for owner=viewer!");
assert(size);
for (itm=items;itm;itm=itm->next) {
item * ishow;
const char * ic;
report_item(owner, itm, viewer, NULL, &ic, NULL, false);
if (ic && *ic) {
for (ishow = result; ishow!=result+n; ishow=ishow->next) {
const char * sc;
if (ishow->type==itm->type) sc = ic;
else report_item(owner, ishow, viewer, NULL, &sc, NULL, false);
if (sc==ic || strcmp(sc, ic)==0) {
ishow->number+=itm->number;
break;
}
}
if (ishow==result+n) {
if (n==size) {
return -1;
}
result[n].number = itm->number;
result[n].type = itm->type;
result[n].next = (n+1==size)?NULL:result+n+1;
++n;
}
}
}
if (n>0) result[n-1].next = NULL;
return n;
}
static void
report_resource(resource_report * result, const char * name, int number, int level)
{
result->name = name;
result->number = number;
result->level = level;
}
int
report_resources(const seen_region * sr, resource_report * result, int size, const faction * viewer)
{
const region * r = sr->r;
int n = 0;
if (r->land) {
int peasants = rpeasants(r);
int horses = rhorses(r);
int trees = rtrees(r, 2);
int saplings = rtrees(r, 1);
boolean mallorn = fval(r, RF_MALLORN)!=0;
if (peasants) {
if (n>=size) return -1;
report_resource(result+n, "rm_peasant", peasants, -1);
++n;
}
if (horses) {
if (n>=size) return -1;
report_resource(result+n, "rm_horse", horses, -1);
++n;
}
if (saplings) {
if (n>=size) return -1;
report_resource(result+n, mallorn?"rm_mallornsapling":"rm_sapling", saplings, -1);
++n;
}
if (trees) {
if (n>=size) return -1;
report_resource(result+n, mallorn?"rm_mallorn":"rm_tree", trees, -1);
++n;
}
}
if (sr->mode>=see_unit) {
rawmaterial * res = r->resources;
while (res) {
int maxskill = 0;
int level = -1;
int visible = -1;
const item_type * itype = resource2item(res->type->rtype);
if (res->type->visible==NULL) {
visible = res->amount;
level = res->level + itype->construction->minskill - 1;
} else {
const unit * u;
for (u=r->units; visible!=res->amount && u!=NULL; u=u->next) {
if (u->faction == viewer) {
int s = eff_skill(u, itype->construction->skill, r);
if (s>maxskill) {
if (s>=itype->construction->minskill) {
assert(itype->construction->minskill>0);
level = res->level + itype->construction->minskill - 1;
}
maxskill = s;
visible = res->type->visible(res, maxskill);
}
}
}
}
if (level>=0 && visible>=0) {
if (n>=size) return -1;
report_resource(result+n, res->type->name, visible, level);
n++;
}
res = res->next;
}
}
return n;
}
int
bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, size_t size)
{
@ -258,6 +385,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz
static const curse_type * itemcloak_ct = 0;
static boolean init = false;
int bytes;
item result[MAX_INVENTORY];
if (!init) {
init = true;
@ -425,28 +553,10 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz
} 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));
}
}
}
int n = report_items(u->items, result, MAX_INVENTORY, u, f);
assert(n>=0);
if (n>0) show = result;
else show = NULL;
} else {
show = NULL;
}
@ -470,7 +580,6 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz
}
if (bytes<0 || wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
}
if (show!=u->items) while (show) i_free(i_remove(&show, show));
if (u->faction == f || telepath_see) {
sc_mage * m = get_mage(u);

View file

@ -95,9 +95,8 @@ typedef struct report_context {
typedef int (*report_fun)(const char * filename, report_context * ctx, const char * charset);
extern void register_reporttype(const char * extension, report_fun write, int flag);
extern void report_item(const struct unit * owner, const struct item * i, const struct faction * viewer, const char ** name, const char ** basename, int * number, boolean singular);
extern void report_building(FILE *F, const struct region * r, const struct building * b, const struct faction * f, int mode);
extern int bufunit(const struct faction * f, const struct unit * u, int indent, int mode, char * buf, size_t size);
extern const char * reportpath(void);
@ -116,9 +115,20 @@ extern const char * report_kampfstatus(const struct unit * u, const struct local
struct region ** regions;
} arg_regions;
typedef struct resource_report {
const char * name;
int number;
int level;
} resource_report;
int report_resources(const struct seen_region * sr, struct resource_report * result, int size, const struct faction * viewer);
int report_items(const struct item * items, struct item * result, int size, const struct unit * owner, const struct faction * viewer);
void report_item(const struct unit * owner, const struct item * i, const struct faction * viewer, const char ** name, const char ** basename, int * number, boolean singular);
extern size_t f_regionid(const struct region * r, const struct faction * f, char * buffer, size_t size);
#define GR_PLURAL 0x01 /* grammar: plural */
#define MAX_INVENTORY 64 /* maimum number of different items in an inventory */
#define MAX_RAWMATERIALS 8 /* maximum kinds of raw materials in a regions */
#ifdef __cplusplus
}

View file

@ -88,8 +88,6 @@
#undef XMAS2001
#undef XMAS2002
extern void reorder_owners(struct region * r);
static int
curse_emptiness(void)
{
@ -164,7 +162,7 @@ verify_owners(boolean bOnce)
}
}
}
if (bFail) reorder_owners(r);
if (bFail) reorder_units(r);
}
}

View file

@ -45,7 +45,7 @@ operator==(const ship& a, const ship& sh)
}
static ship *
add_ship(const char * sname, region& r)
add_ship(region& r, const char * sname)
{
const ship_type * stype = st_find(sname);
ship * sh = new_ship(stype, NULL, &r);

View file

@ -21,6 +21,7 @@ using namespace luabind;
#include <util/language.h>
#include <util/rng.h>
#include <kernel/skill.h>
#include <kernel/region.h>
static const char *
loc_getskill(const char * loc, const char * locstring)
@ -46,6 +47,7 @@ bind_test(lua_State * L)
module(L, "test")[
def("loc_skill", &loc_getskill),
def("loc_keyword", &loc_getkeyword),
def("reorder_units", &reorder_units),
def("rng_int", &rng_int)
];
}