extend wizard-mode '#stats' command

Extend #stats beyond just monsters and objects.  Have it display
memory usage for traps, engravings, light sources, timers, pending
shop wall/floor repair, regions, bones tracking, named object types,
and dungeon overview.

No doubt there are other memory consumers that I've overlooked.
This commit is contained in:
PatR
2016-04-16 15:37:35 -07:00
parent 41ade6d37d
commit 953ee96f7e
8 changed files with 333 additions and 62 deletions

View File

@@ -294,6 +294,7 @@ REPRODUCIBLE_BUILD is new config.h setting to fetch build date+time from
default value for vibrating square symbol changed from yellow '^' to purple '~'
allow symbol set values to be specified via char within single quotes
add symbols set "plain", same as default except it uses '+' for corner walls
extend wizard-mode '#stats' command
Platform- and/or Interface-Specific New Features

View File

@@ -594,6 +594,7 @@ E void NDECL(recalc_mapseen);
E void FDECL(mapseen_temple, (struct monst *));
E void FDECL(room_discovered, (int));
E void FDECL(recbranch_mapseen, (d_level *, d_level *));
E void FDECL(overview_stats, (winid, const char *, long *, long *));
E void FDECL(remdun_mapseen, (int));
/* ### eat.c ### */
@@ -680,6 +681,7 @@ E int NDECL(doengrave);
E void NDECL(sanitize_engravings);
E void FDECL(save_engravings, (int, int));
E void FDECL(rest_engravings, (int));
E void FDECL(engr_stats, (const char *, char *, long *, long *));
E void FDECL(del_engr, (struct engr *));
E void FDECL(rloc_engr, (struct engr *));
E void FDECL(make_grave, (int, int, const char *));
@@ -984,6 +986,7 @@ E void FDECL(do_light_sources, (char **));
E struct monst *FDECL(find_mid, (unsigned, unsigned));
E void FDECL(save_light_sources, (int, int, int));
E void FDECL(restore_light_sources, (int));
E void FDECL(light_stats, (const char *, char *, long *, long *));
E void FDECL(relink_light_sources, (BOOLEAN_P));
E void NDECL(light_sources_sanity_check);
E void FDECL(obj_move_light_source, (struct obj *, struct obj *));
@@ -1963,6 +1966,7 @@ E NhRegion *FDECL(visible_region_at, (XCHAR_P, XCHAR_P));
E void FDECL(show_region, (NhRegion *, XCHAR_P, XCHAR_P));
E void FDECL(save_regions, (int, int));
E void FDECL(rest_regions, (int, BOOLEAN_P));
E void FDECL(region_stats, (const char *, char *, long *, long *));
E NhRegion *FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
E boolean NDECL(region_danger);
E void NDECL(region_safety);
@@ -2307,6 +2311,7 @@ E long FDECL(spot_time_left, (XCHAR_P, XCHAR_P, SHORT_P));
E boolean FDECL(obj_is_local, (struct obj *));
E void FDECL(save_timers, (int, int, int));
E void FDECL(restore_timers, (int, int, BOOLEAN_P, long));
E void FDECL(timer_stats, (const char *, char *, long *, long *));
E void FDECL(relink_timers, (BOOLEAN_P));
E int NDECL(wiz_timeout_queue);
E void NDECL(timer_sanity_check);

249
src/cmd.c
View File

@@ -149,12 +149,13 @@ STATIC_DCL int FDECL(size_obj, (struct obj *));
STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *,
BOOLEAN_P, BOOLEAN_P));
STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *,
long *, long *));
BOOLEAN_P, long *, long *));
STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
long *, long *));
STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
long *, long *));
STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
BOOLEAN_P, long *, long *));
STATIC_DCL void FDECL(contained_stats, (winid, const char *, long *, long *));
STATIC_DCL void FDECL(misc_stats, (winid, long *, long *));
STATIC_PTR int NDECL(wiz_show_stats);
STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
#ifdef PORT_DEBUG
@@ -2905,9 +2906,9 @@ int NDECL((*fn));
return 0;
}
static const char template[] = "%-18s %4ld %6ld";
static const char count_str[] = " count bytes";
static const char separator[] = "------------------ ----- ------";
static const char template[] = "%-27s %4ld %6ld";
static const char stats_hdr[] = " count bytes";
static const char stats_sep[] = "--------------------------- ----- -------";
STATIC_OVL int
size_obj(otmp)
@@ -2955,21 +2956,25 @@ boolean recurse;
}
STATIC_OVL void
obj_chain(win, src, chain, total_count, total_size)
obj_chain(win, src, chain, force, total_count, total_size)
winid win;
const char *src;
struct obj *chain;
boolean force;
long *total_count;
long *total_size;
{
char buf[BUFSZ];
long count = 0, size = 0;
long count = 0L, size = 0L;
count_obj(chain, &count, &size, TRUE, FALSE);
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
if (count || size || force) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
}
}
STATIC_OVL void
@@ -2986,14 +2991,17 @@ long *total_size;
for (mon = chain; mon; mon = mon->nmon)
count_obj(mon->minvent, &count, &size, TRUE, FALSE);
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
}
}
STATIC_OVL void
contained(win, src, total_count, total_size)
contained_stats(win, src, total_count, total_size)
winid win;
const char *src;
long *total_count;
@@ -3014,11 +3022,12 @@ long *total_size;
for (mon = migrating_mons; mon; mon = mon->nmon)
count_obj(mon->minvent, &count, &size, FALSE, TRUE);
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
}
}
STATIC_OVL int
@@ -3047,10 +3056,11 @@ struct monst *mtmp;
}
STATIC_OVL void
mon_chain(win, src, chain, total_count, total_size)
mon_chain(win, src, chain, force, total_count, total_size)
winid win;
const char *src;
struct monst *chain;
boolean force;
long *total_count;
long *total_size;
{
@@ -3058,14 +3068,121 @@ long *total_size;
long count, size;
struct monst *mon;
for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
count = size = 0L;
for (mon = chain; mon; mon = mon->nmon) {
count++;
size += size_monst(mon);
}
if (count || size || force) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
putstr(win, 0, buf);
}
}
STATIC_OVL void
misc_stats(win, total_count, total_size)
winid win;
long *total_count;
long *total_size;
{
char buf[BUFSZ], hdrbuf[QBUFSZ];
long count, size;
int idx;
struct trap *tt;
struct damage *sd; /* shop damage */
struct cemetery *bi; /* bones info */
/* traps and engravings are output unconditionally;
* others only if nonzero
*/
count = size = 0L;
for (tt = ftrap; tt; tt = tt->ntrap) {
++count;
size += (long) sizeof *tt;
}
*total_count += count;
*total_size += size;
Sprintf(buf, template, src, count, size);
Sprintf(hdrbuf, "traps, size %ld", (long) sizeof (struct trap));
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
count = size = 0L;
engr_stats("engravings, size %ld+text", hdrbuf, &count, &size);
*total_count += count;
*total_size += size;
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
count = size = 0L;
light_stats("light sources, size %ld", hdrbuf, &count, &size);
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
count = size = 0L;
timer_stats("timers, size %ld", hdrbuf, &count, &size);
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
count = size = 0L;
for (sd = level.damagelist; sd; sd = sd->next) {
++count;
size += (long) sizeof *sd;
}
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(hdrbuf, "shop damage, size %ld",
(long) sizeof (struct damage));
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
count = size = 0L;
region_stats("regions, size %ld+%ld*rect+N", hdrbuf, &count, &size);
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
count = size = 0L;
for (bi = level.bonesinfo; bi; bi = bi->next) {
++count;
size += (long) sizeof *bi;
}
if (count || size) {
*total_count += count;
*total_size += size;
Sprintf(hdrbuf, "bones history, size %ld",
(long) sizeof (struct cemetery));
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
count = size = 0L;
for (idx = 0; idx < NUM_OBJECTS; ++idx)
if (objects[idx].oc_uname) {
++count;
size += (long) (strlen(objects[idx].oc_uname) + 1);
}
if (count || size) {
*total_count += count;
*total_size += size;
Strcpy(hdrbuf, "object type names, text");
Sprintf(buf, template, hdrbuf, count, size);
putstr(win, 0, buf);
}
}
/*
@@ -3076,45 +3193,73 @@ wiz_show_stats()
{
char buf[BUFSZ];
winid win;
long total_obj_size = 0, total_obj_count = 0;
long total_mon_size = 0, total_mon_count = 0;
long total_obj_size, total_obj_count,
total_mon_size, total_mon_count,
total_ovr_size, total_ovr_count,
total_misc_size, total_misc_count;
win = create_nhwindow(NHW_TEXT);
putstr(win, 0, "Current memory statistics:");
putstr(win, 0, "");
Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
putstr(win, 0, buf);
putstr(win, 0, "");
putstr(win, 0, count_str);
obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
obj_chain(win, "buried", level.buriedobjlist, &total_obj_count,
&total_obj_size);
obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
&total_obj_size);
total_obj_count = total_obj_size = 0L;
putstr(win, 0, stats_hdr);
Sprintf(buf, " Objects, base size %ld", (long) sizeof (struct obj));
putstr(win, 0, buf);
obj_chain(win, "invent", invent, TRUE, &total_obj_count, &total_obj_size);
obj_chain(win, "fobj", fobj, TRUE, &total_obj_count, &total_obj_size);
obj_chain(win, "buried", level.buriedobjlist, FALSE,
&total_obj_count, &total_obj_size);
obj_chain(win, "migrating obj", migrating_objs, FALSE,
&total_obj_count, &total_obj_size);
obj_chain(win, "billobjs", billobjs, FALSE,
&total_obj_count, &total_obj_size);
mon_invent_chain(win, "minvent", fmon, &total_obj_count, &total_obj_size);
mon_invent_chain(win, "migrating minvent", migrating_mons,
&total_obj_count, &total_obj_size);
contained_stats(win, "contained", &total_obj_count, &total_obj_size);
putstr(win, 0, stats_sep);
Sprintf(buf, template, " Obj total", total_obj_count, total_obj_size);
putstr(win, 0, buf);
contained(win, "contained", &total_obj_count, &total_obj_size);
total_mon_count = total_mon_size = 0L;
putstr(win, 0, "");
Sprintf(buf, " Monsters, base size %ld", (long) sizeof (struct monst));
putstr(win, 0, buf);
mon_chain(win, "fmon", fmon, TRUE, &total_mon_count, &total_mon_size);
mon_chain(win, "migrating", migrating_mons, FALSE,
&total_mon_count, &total_mon_size);
/* 'mydogs' is only valid during level change or end of game disclosure,
but conceivably we've been called from within debugger at such time */
if (mydogs) /* monsters accompanying hero */
mon_chain(win, "mydogs", mydogs, FALSE,
&total_mon_count, &total_mon_size);
putstr(win, 0, stats_sep);
Sprintf(buf, template, " Mon total", total_mon_count, total_mon_size);
putstr(win, 0, buf);
putstr(win, 0, separator);
Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
total_ovr_count = total_ovr_size = 0L;
putstr(win, 0, "");
putstr(win, 0, " Overview");
overview_stats(win, template, &total_ovr_count, &total_ovr_size);
putstr(win, 0, stats_sep);
Sprintf(buf, template, " Over total", total_ovr_count, total_ovr_size);
putstr(win, 0, buf);
total_misc_count = total_misc_size = 0L;
putstr(win, 0, "");
putstr(win, 0, " Miscellaneous");
misc_stats(win, &total_misc_count, &total_misc_size);
putstr(win, 0, stats_sep);
Sprintf(buf, template, " Misc total", total_misc_count, total_misc_size);
putstr(win, 0, buf);
putstr(win, 0, "");
putstr(win, 0, "");
Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
putstr(win, 0, buf);
putstr(win, 0, "");
mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
mon_chain(win, "migrating", migrating_mons, &total_mon_count,
&total_mon_size);
putstr(win, 0, separator);
Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
putstr(win, 0, stats_sep);
Sprintf(buf, template, " Grand total",
(total_obj_count + total_mon_count
+ total_ovr_count + total_misc_count),
(total_obj_size + total_mon_size
+ total_ovr_size + total_misc_size));
putstr(win, 0, buf);
#if defined(__BORLANDC__) && !defined(_WIN32)

View File

@@ -2119,6 +2119,50 @@ int fd;
return load;
}
/* to support '#stats' wizard-mode command */
void
overview_stats(win, statsfmt, total_count, total_size)
winid win;
const char *statsfmt;
long *total_count, *total_size;
{
char buf[BUFSZ], hdrbuf[QBUFSZ];
long ocount, osize, bcount, bsize, acount, asize;
struct cemetery *ce;
mapseen *mptr = find_mapseen(&u.uz);
ocount = bcount = acount = osize = bsize = asize = 0L;
for (mptr = mapseenchn; mptr; mptr = mptr->next) {
++ocount;
osize += (long) sizeof *mptr;
for (ce = mptr->final_resting_place; ce; ce = ce->next) {
++bcount;
bsize += (long) sizeof *ce;
}
if (mptr->custom_lth) {
++acount;
asize += (long) (mptr->custom_lth + 1);
}
}
Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
putstr(win, 0, buf);
if (bcount) {
Sprintf(hdrbuf, "cemetery, size %ld",
(long) sizeof (struct cemetery));
Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
putstr(win, 0, buf);
}
if (acount) {
Sprintf(hdrbuf, "annotations, text");
Sprintf(buf, statsfmt, hdrbuf, acount, asize);
putstr(win, 0, buf);
}
*total_count += ocount + bcount + acount;
*total_size += osize + bsize + asize;
}
/* Remove all mapseen objects for a particular dnum.
* Useful during quest expulsion to remove quest levels.
* [No longer deleted, just marked as unreachable. #overview will

View File

@@ -1201,6 +1201,23 @@ int fd;
}
}
/* to support '#stats' wizard-mode command */
void
engr_stats(hdrfmt, hdrbuf, count, size)
const char *hdrfmt;
char *hdrbuf;
long *count, *size;
{
struct engr *ep;
Sprintf(hdrbuf, hdrfmt, (long) sizeof (struct engr));
*count = *size = 0L;
for (ep = head_engr; ep; ep = ep->nxt_engr) {
++*count;
*size += (long) sizeof *ep + (long) ep->engr_lth;
}
}
void
del_engr(ep)
register struct engr *ep;

View File

@@ -306,6 +306,23 @@ int fd;
}
}
/* to support '#stats' wizard-mode command */
void
light_stats(hdrfmt, hdrbuf, count, size)
const char *hdrfmt;
char *hdrbuf;
long *count, *size;
{
light_source *ls;
Sprintf(hdrbuf, hdrfmt, (long) sizeof (light_source));
*count = *size = 0L;
for (ls = light_base; ls; ls = ls->next) {
++*count;
*size += (long) sizeof *ls;
}
}
/* Relink all lights that are so marked. */
void
relink_light_sources(ghostly)

View File

@@ -95,14 +95,13 @@ int nrect;
if (nrect > 0) {
reg->bounding_box = rects[0];
} else {
reg->bounding_box.lx = 99;
reg->bounding_box.ly = 99;
reg->bounding_box.hx = 0;
reg->bounding_box.lx = COLNO;
reg->bounding_box.ly = ROWNO;
reg->bounding_box.hx = 0; /* 1 */
reg->bounding_box.hy = 0;
}
reg->nrects = nrect;
reg->rects =
nrect > 0 ? (NhRect *) alloc((sizeof(NhRect)) * nrect) : (NhRect *) 0;
reg->rects = (nrect > 0) ? (NhRect *) alloc(nrect * sizeof (NhRect)) : 0;
for (i = 0; i < nrect; i++) {
if (rects[i].lx < reg->bounding_box.lx)
reg->bounding_box.lx = rects[i].lx;
@@ -145,10 +144,10 @@ NhRect *rect;
{
NhRect *tmp_rect;
tmp_rect = (NhRect *) alloc(sizeof(NhRect) * (reg->nrects + 1));
tmp_rect = (NhRect *) alloc((reg->nrects + 1) * sizeof (NhRect));
if (reg->nrects > 0) {
(void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects,
(sizeof(NhRect) * reg->nrects));
reg->nrects * sizeof (NhRect));
free((genericptr_t) reg->rects);
}
tmp_rect[reg->nrects] = *rect;
@@ -177,7 +176,7 @@ struct monst *mon;
unsigned *tmp_m;
if (reg->max_monst <= reg->n_monst) {
tmp_m = (unsigned *) alloc(sizeof(unsigned)
tmp_m = (unsigned *) alloc(sizeof (unsigned)
* (reg->max_monst + MONST_INC));
if (reg->max_monst > 0) {
for (i = 0; i < reg->max_monst; i++)
@@ -297,10 +296,10 @@ NhRegion *reg;
if (max_regions <= n_regions) {
tmp_reg = regions;
regions =
(NhRegion **) alloc(sizeof(NhRegion *) * (max_regions + 10));
(NhRegion **) alloc((max_regions + 10) * sizeof (NhRegion *));
if (max_regions > 0) {
(void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg,
max_regions * sizeof(NhRegion *));
max_regions * sizeof (NhRegion *));
free((genericptr_t) tmp_reg);
}
max_regions += 10;
@@ -763,6 +762,32 @@ boolean ghostly; /* If a bones file restore */
reset_region_mids(regions[i]);
}
/* to support '#stats' wizard-mode command */
void
region_stats(hdrfmt, hdrbuf, count, size)
const char *hdrfmt;
char *hdrbuf;
long *count, *size;
{
NhRegion *rg;
int i;
/* other stats formats take one parameter; this takes two */
Sprintf(hdrbuf, hdrfmt, (long) sizeof (NhRegion), (long) sizeof (NhRect));
*count = (long) n_regions; /* might be 0 even though max_regions isn't */
*size = (long) max_regions * (long) sizeof (NhRegion);
for (i = 0; i < n_regions; ++i) {
rg = regions[i];
*size += (long) rg->nrects * (long) sizeof (NhRect);
if (rg->enter_msg)
*size += (long) (strlen(rg->enter_msg) + 1);
if (rg->leave_msg)
*size += (long) (strlen(rg->leave_msg) + 1);
*size += (long) rg->max_monst * (long) sizeof *rg->monsters;
}
/* ? */
}
/* update monster IDs for region being loaded from bones; `ghostly' implied */
STATIC_OVL void
reset_region_mids(reg)

View File

@@ -1998,6 +1998,23 @@ long adjust; /* how much to adjust timeout */
}
}
/* to support '#stats' wizard-mode command */
void
timer_stats(hdrfmt, hdrbuf, count, size)
const char *hdrfmt;
char *hdrbuf;
long *count, *size;
{
timer_element *te;
Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
*count = *size = 0L;
for (te = timer_base; te; te = te->next) {
++*count;
*size += (long) sizeof *te;
}
}
/* reset all timers that are marked for reseting */
void
relink_timers(ghostly)