more monster iteration
Re-use the array allocated for iterating over all monsters during monster movement much of the time. It was being allocated from scratch for each round of monster movement, then freed after they moved, then repeated the next round.
This commit is contained in:
@@ -1736,6 +1736,7 @@ extern void wake_nearby(void);
|
||||
extern void wake_nearto(coordxy, coordxy, int);
|
||||
extern void seemimic(struct monst *) NONNULLARG1;
|
||||
extern void normal_shape(struct monst *) NONNULLARG1;
|
||||
extern void alloc_itermonarr(unsigned);
|
||||
extern void iter_mons_safe(boolean (*)(struct monst *));
|
||||
extern void iter_mons(void (*)(struct monst *));
|
||||
extern struct monst *get_iter_mons(boolean (*)(struct monst *));
|
||||
|
||||
45
src/mon.c
45
src/mon.c
@@ -4102,6 +4102,34 @@ normal_shape(struct monst *mon)
|
||||
}
|
||||
}
|
||||
|
||||
/* freed by freedynamicdata() when game ends; doesn't need to be struct g */
|
||||
static struct monst **itermonarr = NULL;
|
||||
static unsigned itermonsiz = 0; /* size in 'monst *' pointers */
|
||||
|
||||
/* manage itermonarr; it used to be allocated and freed every time the
|
||||
monster movement loop ran; now, keep it around most of the time */
|
||||
void
|
||||
alloc_itermonarr(unsigned count)
|
||||
{
|
||||
/* if count is 0 or bigger than itemarrsiz or much smaller than
|
||||
itemarrsiz, release itermonarr (add reset itermarrsiz to 0) */
|
||||
if (!count || count > itermonsiz || count + 40 < itermonsiz) {
|
||||
if (itermonarr)
|
||||
free((genericptr_t) itermonarr), itermonarr = NULL;
|
||||
itermonsiz = 0;
|
||||
}
|
||||
/* when count is more than itermonsiz (including when that just
|
||||
got reset to 0), allocate a new instance of itermonarr;
|
||||
implies that count is greater than 0 */
|
||||
if (count > itermonsiz) {
|
||||
/* overallocate to reduce free/alloc-again thrashing when the
|
||||
number of monsters varies from turn to turn */
|
||||
itermonsiz = count + 20;
|
||||
itermonarr = (struct monst **) alloc(
|
||||
itermonsiz * sizeof (struct monst *));
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate all monsters on the level, even dead or off-map ones, calling
|
||||
bfunc() for each monster. If bfunc() returns TRUE, stop iterating.
|
||||
If the game ends during the call to bfunc(), then freedynamicdata()
|
||||
@@ -4112,27 +4140,24 @@ normal_shape(struct monst *mon)
|
||||
void
|
||||
iter_mons_safe(boolean (*bfunc)(struct monst *))
|
||||
{
|
||||
struct monst **monarr, *mtmp;
|
||||
int i, nmons;
|
||||
struct monst *mtmp;
|
||||
unsigned i, nmons;
|
||||
|
||||
for (nmons = 0, mtmp = fmon; mtmp; mtmp = mtmp->nmon)
|
||||
nmons++;
|
||||
|
||||
if (nmons) {
|
||||
monarr = (struct monst **) alloc(nmons * sizeof (struct monst *));
|
||||
gi.itermonarr = monarr; /* accessible to freedynamicdata() */
|
||||
/* make sure itermonarr[] is big enough to hold nmons entries */
|
||||
alloc_itermonarr(nmons);
|
||||
|
||||
if (nmons) {
|
||||
for (i = 0, mtmp = fmon; mtmp; mtmp = mtmp->nmon)
|
||||
monarr[i++] = mtmp;
|
||||
itermonarr[i++] = mtmp;
|
||||
|
||||
for (i = 0; i < nmons; i++) {
|
||||
mtmp = monarr[i];
|
||||
mtmp = itermonarr[i];
|
||||
if ((*bfunc)(mtmp))
|
||||
break;
|
||||
}
|
||||
|
||||
free(monarr);
|
||||
gi.itermonarr = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1184,8 +1184,7 @@ freedynamicdata(void)
|
||||
|
||||
/* move-specific data */
|
||||
dmonsfree(); /* release dead monsters */
|
||||
if (gi.itermonarr)
|
||||
free((genericptr_t) gi.itermonarr), gi.itermonarr = NULL;
|
||||
alloc_itermonarr(0U); /* a request of 0 releases existing allocation */
|
||||
|
||||
/* level-specific data */
|
||||
done_object_cleanup(); /* maybe force some OBJ_FREE items onto map */
|
||||
|
||||
Reference in New Issue
Block a user