get_rnd_text() selection distribution

While testing 'the("Capitalized Hallucinatory Monster")' I noticed that
some hallucinatory monsters showed up more often than others.  When
the random engravings, epitaphs, and bogus monsters were converted from
hard-coded arrays to data files accessed by random seek (3.6.0), they
became subject to the same distribution irregularites that rumors suffer
from.  The chance that an entry will be chosen depends upon the chance
that a random seek will hit somewhere in the line which precedes it, so
entries that follow long lines are more likely to be chosen and entries
that follow short lines are less likely.  We improved that for rumors
by having makedefs pad the shortest lines.  Distribution still isn't
uniform but is much better than it was (and could be further improved
with a longer padding length at the cost of making data files bigger so
possibly slower to access; both overall size and access speed mattered
back when floppy discs were supported but are probably irrelevant now).

Start doing the same thing for the newer files:  pad the shortest lines
to increase the chance that seek will find them.  The tradeoff is that
the data files become bigger.  Rumors, engravings, and epitaphs lines
are all at least 60 characters now; bogus monsters are at least 20.
These are the data file sizes I see (in bytes:  old, new; padding for
rumors was already in use so its size hasn't changed):
  bogusmon    4449    7211
  engrave     1326    2894
  epitaph    14159   24075
  rumors     49173   49173

The only place that padding is noticeable in-game is #wizrumorcheck.
This commit is contained in:
PatR
2021-11-25 17:57:37 -08:00
parent 3f3d1ad85c
commit 59beebcbcc
3 changed files with 107 additions and 55 deletions

View File

@@ -40,6 +40,7 @@
* and placed there by 'makedefs'.
*/
static void unpadline(char *);
static void init_rumors(dlb *);
static void init_oracles(dlb *);
static void others_check(const char *ftype, const char *, winid *);
@@ -51,6 +52,24 @@ static void init_CapMons(void);
static unsigned CapMonSiz = 0;
static const char **CapMons = 0;
/* makedefs pads short rumors, epitaphs, engravings, and hallucinatory
monster names with trailing underscores; strip those off */
static void
unpadline(char *line)
{
char *p = eos(line);
/* remove newline if still present; caller should have stripped it */
if (p > line && p[-1] == '\n')
--p;
/* remove padding */
while (p > line && p[-1] == '_')
--p;
*p = '\0';
}
DISABLE_WARNING_FORMAT_NONLITERAL
static void
@@ -158,21 +177,7 @@ getrumor(
g.true_rumor_size = -1; /* don't try to open it again */
}
/* this is safe either way, so do it always since we can't get the
* definition out of makedefs.c
*/
#define PAD_RUMORS_TO
#ifdef PAD_RUMORS_TO
/* remove padding */
{
char *x = eos(rumor_buf) - 1;
while (x > rumor_buf && *x == '_')
x--;
*++x = '\n';
*x = '\0';
}
#endif
unpadline(rumor_buf);
return rumor_buf;
}
@@ -426,8 +431,9 @@ get_rnd_text(const char* fname, char* buf, int (*rng)(int))
(void) dlb_fgets(line, sizeof line, fh);
}
if ((endp = index(line, '\n')) != 0)
*endp = 0;
*endp = '\0';
Strcat(buf, xcrypt(line, xbuf));
unpadline(buf); /* strip padding that makedefs added to end of line */
(void) dlb_fclose(fh);
} else {
couldnt_open_file(fname);